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