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