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