1c865f654SCornelia Huck #ifndef _X86_SMP_H_ 2c865f654SCornelia Huck #define _X86_SMP_H_ 3e5e3ed09SSean Christopherson 4e5e3ed09SSean Christopherson #include <stddef.h> 5cc47ddc1SAndrew Jones #include <asm/spinlock.h> 6d36b378fSVarad Gautam #include "libcflat.h" 7d36b378fSVarad Gautam #include "atomic.h" 80b7501c3SVarad Gautam #include "apic-defs.h" 97d36db35SAvi Kivity 101542cd7bSVarad Gautam /* Address where to store the address of realmode GDT descriptor. */ 111542cd7bSVarad Gautam #define REALMODE_GDT_LOWMEM (PAGE_SIZE - 2) 121542cd7bSVarad Gautam 13e5e3ed09SSean Christopherson /* Offsets into the per-cpu page. */ 14e5e3ed09SSean Christopherson struct percpu_data { 15e5e3ed09SSean Christopherson uint32_t smp_id; 16e5e3ed09SSean Christopherson union { 17e5e3ed09SSean Christopherson struct { 18e5e3ed09SSean Christopherson uint8_t exception_vector; 19e5e3ed09SSean Christopherson uint8_t exception_rflags_rf; 20e5e3ed09SSean Christopherson uint16_t exception_error_code; 21e5e3ed09SSean Christopherson }; 22e5e3ed09SSean Christopherson uint32_t exception_data; 23e5e3ed09SSean Christopherson }; 242d18ccd3SSean Christopherson void *apic_ops; 25e5e3ed09SSean Christopherson }; 26e5e3ed09SSean Christopherson 27e5e3ed09SSean Christopherson #define typeof_percpu(name) typeof(((struct percpu_data *)0)->name) 28e5e3ed09SSean Christopherson #define offsetof_percpu(name) offsetof(struct percpu_data, name) 29e5e3ed09SSean Christopherson 30e5e3ed09SSean Christopherson #define BUILD_PERCPU_OP(name) \ 31e5e3ed09SSean Christopherson static inline typeof_percpu(name) this_cpu_read_##name(void) \ 32e5e3ed09SSean Christopherson { \ 33e5e3ed09SSean Christopherson typeof_percpu(name) val; \ 34e5e3ed09SSean Christopherson \ 35e5e3ed09SSean Christopherson switch (sizeof(val)) { \ 36e5e3ed09SSean Christopherson case 1: \ 37e5e3ed09SSean Christopherson asm("movb %%gs:%c1, %0" : "=q" (val) : "i" (offsetof_percpu(name))); \ 38e5e3ed09SSean Christopherson break; \ 39e5e3ed09SSean Christopherson case 2: \ 40e5e3ed09SSean Christopherson asm("movw %%gs:%c1, %0" : "=r" (val) : "i" (offsetof_percpu(name))); \ 41e5e3ed09SSean Christopherson break; \ 42e5e3ed09SSean Christopherson case 4: \ 43e5e3ed09SSean Christopherson asm("movl %%gs:%c1, %0" : "=r" (val) : "i" (offsetof_percpu(name))); \ 44e5e3ed09SSean Christopherson break; \ 45e5e3ed09SSean Christopherson case 8: \ 46e5e3ed09SSean Christopherson asm("movq %%gs:%c1, %0" : "=r" (val) : "i" (offsetof_percpu(name))); \ 47e5e3ed09SSean Christopherson break; \ 48e5e3ed09SSean Christopherson default: \ 49e5e3ed09SSean Christopherson asm volatile("ud2"); \ 50e5e3ed09SSean Christopherson } \ 51e5e3ed09SSean Christopherson return val; \ 52e5e3ed09SSean Christopherson } \ 53e5e3ed09SSean Christopherson static inline void this_cpu_write_##name(typeof_percpu(name) val) \ 54e5e3ed09SSean Christopherson { \ 55e5e3ed09SSean Christopherson switch (sizeof(val)) { \ 56e5e3ed09SSean Christopherson case 1: \ 57e5e3ed09SSean Christopherson asm("movb %0, %%gs:%c1" :: "q" (val), "i" (offsetof_percpu(name))); \ 58e5e3ed09SSean Christopherson break; \ 59e5e3ed09SSean Christopherson case 2: \ 60e5e3ed09SSean Christopherson asm("movw %0, %%gs:%c1" :: "r" (val), "i" (offsetof_percpu(name))); \ 61e5e3ed09SSean Christopherson break; \ 62e5e3ed09SSean Christopherson case 4: \ 63e5e3ed09SSean Christopherson asm("movl %0, %%gs:%c1" :: "r" (val), "i" (offsetof_percpu(name))); \ 64e5e3ed09SSean Christopherson break; \ 65e5e3ed09SSean Christopherson case 8: \ 66e5e3ed09SSean Christopherson asm("movq %0, %%gs:%c1" :: "r" (val), "i" (offsetof_percpu(name))); \ 67e5e3ed09SSean Christopherson break; \ 68e5e3ed09SSean Christopherson default: \ 69e5e3ed09SSean Christopherson asm volatile("ud2"); \ 70e5e3ed09SSean Christopherson } \ 71e5e3ed09SSean Christopherson } 72e5e3ed09SSean Christopherson BUILD_PERCPU_OP(smp_id); 73e5e3ed09SSean Christopherson BUILD_PERCPU_OP(exception_vector); 74e5e3ed09SSean Christopherson BUILD_PERCPU_OP(exception_rflags_rf); 75e5e3ed09SSean Christopherson BUILD_PERCPU_OP(exception_error_code); 762d18ccd3SSean Christopherson BUILD_PERCPU_OP(apic_ops); 77e5e3ed09SSean Christopherson 787d36db35SAvi Kivity void smp_init(void); 797d36db35SAvi Kivity 807d36db35SAvi Kivity int cpu_count(void); 817d36db35SAvi Kivity int smp_id(void); 82b73c7c6eSAndrew Jones int cpus_active(void); 837d36db35SAvi Kivity void on_cpu(int cpu, void (*function)(void *data), void *data); 847d36db35SAvi Kivity void on_cpu_async(int cpu, void (*function)(void *data), void *data); 85b73c7c6eSAndrew Jones void on_cpus(void (*function)(void *data), void *data); 8674e79380SPaolo Bonzini void smp_reset_apic(void); 87*0afd4dd0SSean Christopherson void bringup_aps(void); 88d36b378fSVarad Gautam 89d36b378fSVarad Gautam extern atomic_t cpu_online_count; 900b7501c3SVarad Gautam extern unsigned char online_cpus[(MAX_TEST_CPUS + 7) / 8]; 917d36db35SAvi Kivity 927d36db35SAvi Kivity #endif 93