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