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