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 }; 19 20 #define typeof_percpu(name) typeof(((struct percpu_data *)0)->name) 21 #define offsetof_percpu(name) offsetof(struct percpu_data, name) 22 23 #define BUILD_PERCPU_OP(name) \ 24 static inline typeof_percpu(name) this_cpu_read_##name(void) \ 25 { \ 26 typeof_percpu(name) val; \ 27 \ 28 switch (sizeof(val)) { \ 29 case 1: \ 30 asm("movb %%gs:%c1, %0" : "=q" (val) : "i" (offsetof_percpu(name))); \ 31 break; \ 32 case 2: \ 33 asm("movw %%gs:%c1, %0" : "=r" (val) : "i" (offsetof_percpu(name))); \ 34 break; \ 35 case 4: \ 36 asm("movl %%gs:%c1, %0" : "=r" (val) : "i" (offsetof_percpu(name))); \ 37 break; \ 38 case 8: \ 39 asm("movq %%gs:%c1, %0" : "=r" (val) : "i" (offsetof_percpu(name))); \ 40 break; \ 41 default: \ 42 asm volatile("ud2"); \ 43 } \ 44 return val; \ 45 } \ 46 static inline void this_cpu_write_##name(typeof_percpu(name) val) \ 47 { \ 48 switch (sizeof(val)) { \ 49 case 1: \ 50 asm("movb %0, %%gs:%c1" :: "q" (val), "i" (offsetof_percpu(name))); \ 51 break; \ 52 case 2: \ 53 asm("movw %0, %%gs:%c1" :: "r" (val), "i" (offsetof_percpu(name))); \ 54 break; \ 55 case 4: \ 56 asm("movl %0, %%gs:%c1" :: "r" (val), "i" (offsetof_percpu(name))); \ 57 break; \ 58 case 8: \ 59 asm("movq %0, %%gs:%c1" :: "r" (val), "i" (offsetof_percpu(name))); \ 60 break; \ 61 default: \ 62 asm volatile("ud2"); \ 63 } \ 64 } 65 BUILD_PERCPU_OP(smp_id); 66 BUILD_PERCPU_OP(exception_vector); 67 BUILD_PERCPU_OP(exception_rflags_rf); 68 BUILD_PERCPU_OP(exception_error_code); 69 70 void smp_init(void); 71 72 int cpu_count(void); 73 int smp_id(void); 74 int cpus_active(void); 75 void on_cpu(int cpu, void (*function)(void *data), void *data); 76 void on_cpu_async(int cpu, void (*function)(void *data), void *data); 77 void on_cpus(void (*function)(void *data), void *data); 78 void smp_reset_apic(void); 79 80 #endif 81