xref: /kvm-unit-tests/lib/x86/smp.h (revision c604fa931a1cb70c3649ac1b7223178fc79eab6a)
1 #ifndef _X86_SMP_H_
2 #define _X86_SMP_H_
3 
4 #include <stddef.h>
5 #include <asm/spinlock.h>
6 
7 /* Offsets into the per-cpu page. */
8 struct percpu_data {
9 	uint32_t  smp_id;
10 	union {
11 		struct {
12 			uint8_t   exception_vector;
13 			uint8_t   exception_rflags_rf;
14 			uint16_t  exception_error_code;
15 		};
16 		uint32_t exception_data;
17 	};
18 	void *apic_ops;
19 };
20 
21 #define typeof_percpu(name) typeof(((struct percpu_data *)0)->name)
22 #define offsetof_percpu(name) offsetof(struct percpu_data, name)
23 
24 #define BUILD_PERCPU_OP(name)								\
25 static inline typeof_percpu(name) this_cpu_read_##name(void)				\
26 {											\
27 	typeof_percpu(name) val;							\
28 											\
29 	switch (sizeof(val)) {								\
30 	case 1:										\
31 		asm("movb %%gs:%c1, %0" : "=q" (val) : "i" (offsetof_percpu(name)));	\
32 		break;									\
33 	case 2:										\
34 		asm("movw %%gs:%c1, %0" : "=r" (val) : "i" (offsetof_percpu(name)));	\
35 		break;									\
36 	case 4:										\
37 		asm("movl %%gs:%c1, %0" : "=r" (val) : "i" (offsetof_percpu(name)));	\
38 		break;									\
39 	case 8:										\
40 		asm("movq %%gs:%c1, %0" : "=r" (val) : "i" (offsetof_percpu(name)));	\
41 		break;									\
42 	default:									\
43 		asm volatile("ud2");							\
44 	}										\
45 	return val;									\
46 }											\
47 static inline void this_cpu_write_##name(typeof_percpu(name) val)			\
48 {											\
49 	switch (sizeof(val)) {								\
50 	case 1:										\
51 		asm("movb %0, %%gs:%c1" :: "q" (val), "i" (offsetof_percpu(name)));	\
52 		break;									\
53 	case 2:										\
54 		asm("movw %0, %%gs:%c1" :: "r" (val), "i" (offsetof_percpu(name)));	\
55 		break;									\
56 	case 4:										\
57 		asm("movl %0, %%gs:%c1" :: "r" (val), "i" (offsetof_percpu(name)));	\
58 		break;									\
59 	case 8:										\
60 		asm("movq %0, %%gs:%c1" :: "r" (val), "i" (offsetof_percpu(name)));	\
61 		break;									\
62 	default:									\
63 		asm volatile("ud2");							\
64 	}										\
65 }
66 BUILD_PERCPU_OP(smp_id);
67 BUILD_PERCPU_OP(exception_vector);
68 BUILD_PERCPU_OP(exception_rflags_rf);
69 BUILD_PERCPU_OP(exception_error_code);
70 BUILD_PERCPU_OP(apic_ops);
71 
72 void smp_init(void);
73 
74 int cpu_count(void);
75 int smp_id(void);
76 int cpus_active(void);
77 void on_cpu(int cpu, void (*function)(void *data), void *data);
78 void on_cpu_async(int cpu, void (*function)(void *data), void *data);
79 void on_cpus(void (*function)(void *data), void *data);
80 void smp_reset_apic(void);
81 
82 #endif
83