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