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> 6*d36b378fSVarad Gautam #include "libcflat.h" 7*d36b378fSVarad Gautam #include "atomic.h" 87d36db35SAvi Kivity 9e5e3ed09SSean Christopherson /* Offsets into the per-cpu page. */ 10e5e3ed09SSean Christopherson struct percpu_data { 11e5e3ed09SSean Christopherson uint32_t smp_id; 12e5e3ed09SSean Christopherson union { 13e5e3ed09SSean Christopherson struct { 14e5e3ed09SSean Christopherson uint8_t exception_vector; 15e5e3ed09SSean Christopherson uint8_t exception_rflags_rf; 16e5e3ed09SSean Christopherson uint16_t exception_error_code; 17e5e3ed09SSean Christopherson }; 18e5e3ed09SSean Christopherson uint32_t exception_data; 19e5e3ed09SSean Christopherson }; 202d18ccd3SSean Christopherson void *apic_ops; 21e5e3ed09SSean Christopherson }; 22e5e3ed09SSean Christopherson 23e5e3ed09SSean Christopherson #define typeof_percpu(name) typeof(((struct percpu_data *)0)->name) 24e5e3ed09SSean Christopherson #define offsetof_percpu(name) offsetof(struct percpu_data, name) 25e5e3ed09SSean Christopherson 26e5e3ed09SSean Christopherson #define BUILD_PERCPU_OP(name) \ 27e5e3ed09SSean Christopherson static inline typeof_percpu(name) this_cpu_read_##name(void) \ 28e5e3ed09SSean Christopherson { \ 29e5e3ed09SSean Christopherson typeof_percpu(name) val; \ 30e5e3ed09SSean Christopherson \ 31e5e3ed09SSean Christopherson switch (sizeof(val)) { \ 32e5e3ed09SSean Christopherson case 1: \ 33e5e3ed09SSean Christopherson asm("movb %%gs:%c1, %0" : "=q" (val) : "i" (offsetof_percpu(name))); \ 34e5e3ed09SSean Christopherson break; \ 35e5e3ed09SSean Christopherson case 2: \ 36e5e3ed09SSean Christopherson asm("movw %%gs:%c1, %0" : "=r" (val) : "i" (offsetof_percpu(name))); \ 37e5e3ed09SSean Christopherson break; \ 38e5e3ed09SSean Christopherson case 4: \ 39e5e3ed09SSean Christopherson asm("movl %%gs:%c1, %0" : "=r" (val) : "i" (offsetof_percpu(name))); \ 40e5e3ed09SSean Christopherson break; \ 41e5e3ed09SSean Christopherson case 8: \ 42e5e3ed09SSean Christopherson asm("movq %%gs:%c1, %0" : "=r" (val) : "i" (offsetof_percpu(name))); \ 43e5e3ed09SSean Christopherson break; \ 44e5e3ed09SSean Christopherson default: \ 45e5e3ed09SSean Christopherson asm volatile("ud2"); \ 46e5e3ed09SSean Christopherson } \ 47e5e3ed09SSean Christopherson return val; \ 48e5e3ed09SSean Christopherson } \ 49e5e3ed09SSean Christopherson static inline void this_cpu_write_##name(typeof_percpu(name) val) \ 50e5e3ed09SSean Christopherson { \ 51e5e3ed09SSean Christopherson switch (sizeof(val)) { \ 52e5e3ed09SSean Christopherson case 1: \ 53e5e3ed09SSean Christopherson asm("movb %0, %%gs:%c1" :: "q" (val), "i" (offsetof_percpu(name))); \ 54e5e3ed09SSean Christopherson break; \ 55e5e3ed09SSean Christopherson case 2: \ 56e5e3ed09SSean Christopherson asm("movw %0, %%gs:%c1" :: "r" (val), "i" (offsetof_percpu(name))); \ 57e5e3ed09SSean Christopherson break; \ 58e5e3ed09SSean Christopherson case 4: \ 59e5e3ed09SSean Christopherson asm("movl %0, %%gs:%c1" :: "r" (val), "i" (offsetof_percpu(name))); \ 60e5e3ed09SSean Christopherson break; \ 61e5e3ed09SSean Christopherson case 8: \ 62e5e3ed09SSean Christopherson asm("movq %0, %%gs:%c1" :: "r" (val), "i" (offsetof_percpu(name))); \ 63e5e3ed09SSean Christopherson break; \ 64e5e3ed09SSean Christopherson default: \ 65e5e3ed09SSean Christopherson asm volatile("ud2"); \ 66e5e3ed09SSean Christopherson } \ 67e5e3ed09SSean Christopherson } 68e5e3ed09SSean Christopherson BUILD_PERCPU_OP(smp_id); 69e5e3ed09SSean Christopherson BUILD_PERCPU_OP(exception_vector); 70e5e3ed09SSean Christopherson BUILD_PERCPU_OP(exception_rflags_rf); 71e5e3ed09SSean Christopherson BUILD_PERCPU_OP(exception_error_code); 722d18ccd3SSean Christopherson BUILD_PERCPU_OP(apic_ops); 73e5e3ed09SSean Christopherson 747d36db35SAvi Kivity void smp_init(void); 757d36db35SAvi Kivity 767d36db35SAvi Kivity int cpu_count(void); 777d36db35SAvi Kivity int smp_id(void); 78b73c7c6eSAndrew Jones int cpus_active(void); 797d36db35SAvi Kivity void on_cpu(int cpu, void (*function)(void *data), void *data); 807d36db35SAvi Kivity void on_cpu_async(int cpu, void (*function)(void *data), void *data); 81b73c7c6eSAndrew Jones void on_cpus(void (*function)(void *data), void *data); 8274e79380SPaolo Bonzini void smp_reset_apic(void); 83*d36b378fSVarad Gautam void ap_init(void); 84*d36b378fSVarad Gautam 85*d36b378fSVarad Gautam extern atomic_t cpu_online_count; 867d36db35SAvi Kivity 877d36db35SAvi Kivity #endif 88