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" 87d36db35SAvi Kivity 9*1542cd7bSVarad Gautam /* Address where to store the address of realmode GDT descriptor. */ 10*1542cd7bSVarad Gautam #define REALMODE_GDT_LOWMEM (PAGE_SIZE - 2) 11*1542cd7bSVarad Gautam 12e5e3ed09SSean Christopherson /* Offsets into the per-cpu page. */ 13e5e3ed09SSean Christopherson struct percpu_data { 14e5e3ed09SSean Christopherson uint32_t smp_id; 15e5e3ed09SSean Christopherson union { 16e5e3ed09SSean Christopherson struct { 17e5e3ed09SSean Christopherson uint8_t exception_vector; 18e5e3ed09SSean Christopherson uint8_t exception_rflags_rf; 19e5e3ed09SSean Christopherson uint16_t exception_error_code; 20e5e3ed09SSean Christopherson }; 21e5e3ed09SSean Christopherson uint32_t exception_data; 22e5e3ed09SSean Christopherson }; 232d18ccd3SSean Christopherson void *apic_ops; 24e5e3ed09SSean Christopherson }; 25e5e3ed09SSean Christopherson 26e5e3ed09SSean Christopherson #define typeof_percpu(name) typeof(((struct percpu_data *)0)->name) 27e5e3ed09SSean Christopherson #define offsetof_percpu(name) offsetof(struct percpu_data, name) 28e5e3ed09SSean Christopherson 29e5e3ed09SSean Christopherson #define BUILD_PERCPU_OP(name) \ 30e5e3ed09SSean Christopherson static inline typeof_percpu(name) this_cpu_read_##name(void) \ 31e5e3ed09SSean Christopherson { \ 32e5e3ed09SSean Christopherson typeof_percpu(name) val; \ 33e5e3ed09SSean Christopherson \ 34e5e3ed09SSean Christopherson switch (sizeof(val)) { \ 35e5e3ed09SSean Christopherson case 1: \ 36e5e3ed09SSean Christopherson asm("movb %%gs:%c1, %0" : "=q" (val) : "i" (offsetof_percpu(name))); \ 37e5e3ed09SSean Christopherson break; \ 38e5e3ed09SSean Christopherson case 2: \ 39e5e3ed09SSean Christopherson asm("movw %%gs:%c1, %0" : "=r" (val) : "i" (offsetof_percpu(name))); \ 40e5e3ed09SSean Christopherson break; \ 41e5e3ed09SSean Christopherson case 4: \ 42e5e3ed09SSean Christopherson asm("movl %%gs:%c1, %0" : "=r" (val) : "i" (offsetof_percpu(name))); \ 43e5e3ed09SSean Christopherson break; \ 44e5e3ed09SSean Christopherson case 8: \ 45e5e3ed09SSean Christopherson asm("movq %%gs:%c1, %0" : "=r" (val) : "i" (offsetof_percpu(name))); \ 46e5e3ed09SSean Christopherson break; \ 47e5e3ed09SSean Christopherson default: \ 48e5e3ed09SSean Christopherson asm volatile("ud2"); \ 49e5e3ed09SSean Christopherson } \ 50e5e3ed09SSean Christopherson return val; \ 51e5e3ed09SSean Christopherson } \ 52e5e3ed09SSean Christopherson static inline void this_cpu_write_##name(typeof_percpu(name) val) \ 53e5e3ed09SSean Christopherson { \ 54e5e3ed09SSean Christopherson switch (sizeof(val)) { \ 55e5e3ed09SSean Christopherson case 1: \ 56e5e3ed09SSean Christopherson asm("movb %0, %%gs:%c1" :: "q" (val), "i" (offsetof_percpu(name))); \ 57e5e3ed09SSean Christopherson break; \ 58e5e3ed09SSean Christopherson case 2: \ 59e5e3ed09SSean Christopherson asm("movw %0, %%gs:%c1" :: "r" (val), "i" (offsetof_percpu(name))); \ 60e5e3ed09SSean Christopherson break; \ 61e5e3ed09SSean Christopherson case 4: \ 62e5e3ed09SSean Christopherson asm("movl %0, %%gs:%c1" :: "r" (val), "i" (offsetof_percpu(name))); \ 63e5e3ed09SSean Christopherson break; \ 64e5e3ed09SSean Christopherson case 8: \ 65e5e3ed09SSean Christopherson asm("movq %0, %%gs:%c1" :: "r" (val), "i" (offsetof_percpu(name))); \ 66e5e3ed09SSean Christopherson break; \ 67e5e3ed09SSean Christopherson default: \ 68e5e3ed09SSean Christopherson asm volatile("ud2"); \ 69e5e3ed09SSean Christopherson } \ 70e5e3ed09SSean Christopherson } 71e5e3ed09SSean Christopherson BUILD_PERCPU_OP(smp_id); 72e5e3ed09SSean Christopherson BUILD_PERCPU_OP(exception_vector); 73e5e3ed09SSean Christopherson BUILD_PERCPU_OP(exception_rflags_rf); 74e5e3ed09SSean Christopherson BUILD_PERCPU_OP(exception_error_code); 752d18ccd3SSean Christopherson BUILD_PERCPU_OP(apic_ops); 76e5e3ed09SSean Christopherson 777d36db35SAvi Kivity void smp_init(void); 787d36db35SAvi Kivity 797d36db35SAvi Kivity int cpu_count(void); 807d36db35SAvi Kivity int smp_id(void); 81b73c7c6eSAndrew Jones int cpus_active(void); 827d36db35SAvi Kivity void on_cpu(int cpu, void (*function)(void *data), void *data); 837d36db35SAvi Kivity void on_cpu_async(int cpu, void (*function)(void *data), void *data); 84b73c7c6eSAndrew Jones void on_cpus(void (*function)(void *data), void *data); 8574e79380SPaolo Bonzini void smp_reset_apic(void); 86d36b378fSVarad Gautam void ap_init(void); 87d36b378fSVarad Gautam 88d36b378fSVarad Gautam extern atomic_t cpu_online_count; 897d36db35SAvi Kivity 907d36db35SAvi Kivity #endif 91