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