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