xref: /kvm-unit-tests/lib/x86/processor.h (revision 77e03b63de798bbefdf7d9b817f05bb9a5dea60c)
17d36db35SAvi Kivity #ifndef LIBCFLAT_PROCESSOR_H
27d36db35SAvi Kivity #define LIBCFLAT_PROCESSOR_H
37d36db35SAvi Kivity 
47d36db35SAvi Kivity #include "libcflat.h"
52b2d7aadSAvi Kivity #include <stdint.h>
67d36db35SAvi Kivity 
77d36db35SAvi Kivity struct descriptor_table_ptr {
87d36db35SAvi Kivity     u16 limit;
97d36db35SAvi Kivity     ulong base;
107d36db35SAvi Kivity } __attribute__((packed));
117d36db35SAvi Kivity 
127d36db35SAvi Kivity static inline void barrier(void)
137d36db35SAvi Kivity {
147d36db35SAvi Kivity     asm volatile ("" : : : "memory");
157d36db35SAvi Kivity }
167d36db35SAvi Kivity 
177d36db35SAvi Kivity static inline u16 read_cs(void)
187d36db35SAvi Kivity {
197d36db35SAvi Kivity     unsigned val;
207d36db35SAvi Kivity 
217d36db35SAvi Kivity     asm ("mov %%cs, %0" : "=mr"(val));
227d36db35SAvi Kivity     return val;
237d36db35SAvi Kivity }
247d36db35SAvi Kivity 
257d36db35SAvi Kivity static inline u16 read_ds(void)
267d36db35SAvi Kivity {
277d36db35SAvi Kivity     unsigned val;
287d36db35SAvi Kivity 
297d36db35SAvi Kivity     asm ("mov %%ds, %0" : "=mr"(val));
307d36db35SAvi Kivity     return val;
317d36db35SAvi Kivity }
327d36db35SAvi Kivity 
337d36db35SAvi Kivity static inline u16 read_es(void)
347d36db35SAvi Kivity {
357d36db35SAvi Kivity     unsigned val;
367d36db35SAvi Kivity 
377d36db35SAvi Kivity     asm ("mov %%es, %0" : "=mr"(val));
387d36db35SAvi Kivity     return val;
397d36db35SAvi Kivity }
407d36db35SAvi Kivity 
417d36db35SAvi Kivity static inline u16 read_ss(void)
427d36db35SAvi Kivity {
437d36db35SAvi Kivity     unsigned val;
447d36db35SAvi Kivity 
457d36db35SAvi Kivity     asm ("mov %%ss, %0" : "=mr"(val));
467d36db35SAvi Kivity     return val;
477d36db35SAvi Kivity }
487d36db35SAvi Kivity 
497d36db35SAvi Kivity static inline u16 read_fs(void)
507d36db35SAvi Kivity {
517d36db35SAvi Kivity     unsigned val;
527d36db35SAvi Kivity 
537d36db35SAvi Kivity     asm ("mov %%fs, %0" : "=mr"(val));
547d36db35SAvi Kivity     return val;
557d36db35SAvi Kivity }
567d36db35SAvi Kivity 
577d36db35SAvi Kivity static inline u16 read_gs(void)
587d36db35SAvi Kivity {
597d36db35SAvi Kivity     unsigned val;
607d36db35SAvi Kivity 
617d36db35SAvi Kivity     asm ("mov %%gs, %0" : "=mr"(val));
627d36db35SAvi Kivity     return val;
637d36db35SAvi Kivity }
647d36db35SAvi Kivity 
65*77e03b63SGleb Natapov static inline unsigned long read_rflags(void)
66*77e03b63SGleb Natapov {
67*77e03b63SGleb Natapov 	unsigned long f;
68*77e03b63SGleb Natapov 	asm ("pushf; pop %0\n\t" : "=rm"(f));
69*77e03b63SGleb Natapov 	return f;
70*77e03b63SGleb Natapov }
71*77e03b63SGleb Natapov 
727d36db35SAvi Kivity static inline void write_ds(unsigned val)
737d36db35SAvi Kivity {
747d36db35SAvi Kivity     asm ("mov %0, %%ds" : : "rm"(val) : "memory");
757d36db35SAvi Kivity }
767d36db35SAvi Kivity 
777d36db35SAvi Kivity static inline void write_es(unsigned val)
787d36db35SAvi Kivity {
797d36db35SAvi Kivity     asm ("mov %0, %%es" : : "rm"(val) : "memory");
807d36db35SAvi Kivity }
817d36db35SAvi Kivity 
827d36db35SAvi Kivity static inline void write_ss(unsigned val)
837d36db35SAvi Kivity {
847d36db35SAvi Kivity     asm ("mov %0, %%ss" : : "rm"(val) : "memory");
857d36db35SAvi Kivity }
867d36db35SAvi Kivity 
877d36db35SAvi Kivity static inline void write_fs(unsigned val)
887d36db35SAvi Kivity {
897d36db35SAvi Kivity     asm ("mov %0, %%fs" : : "rm"(val) : "memory");
907d36db35SAvi Kivity }
917d36db35SAvi Kivity 
927d36db35SAvi Kivity static inline void write_gs(unsigned val)
937d36db35SAvi Kivity {
947d36db35SAvi Kivity     asm ("mov %0, %%gs" : : "rm"(val) : "memory");
957d36db35SAvi Kivity }
967d36db35SAvi Kivity 
977d36db35SAvi Kivity static inline u64 rdmsr(u32 index)
987d36db35SAvi Kivity {
997d36db35SAvi Kivity     u32 a, d;
1007d36db35SAvi Kivity     asm volatile ("rdmsr" : "=a"(a), "=d"(d) : "c"(index) : "memory");
1017d36db35SAvi Kivity     return a | ((u64)d << 32);
1027d36db35SAvi Kivity }
1037d36db35SAvi Kivity 
1047d36db35SAvi Kivity static inline void wrmsr(u32 index, u64 val)
1057d36db35SAvi Kivity {
1067d36db35SAvi Kivity     u32 a = val, d = val >> 32;
1077d36db35SAvi Kivity     asm volatile ("wrmsr" : : "a"(a), "d"(d), "c"(index) : "memory");
1087d36db35SAvi Kivity }
1097d36db35SAvi Kivity 
1102b2d7aadSAvi Kivity static inline uint64_t rdpmc(uint32_t index)
1112b2d7aadSAvi Kivity {
1122b2d7aadSAvi Kivity     uint32_t a, d;
1132b2d7aadSAvi Kivity     asm volatile ("rdpmc" : "=a"(a), "=d"(d) : "c"(index));
1142b2d7aadSAvi Kivity     return a | ((uint64_t)d << 32);
1152b2d7aadSAvi Kivity }
1162b2d7aadSAvi Kivity 
1177d36db35SAvi Kivity static inline void write_cr0(ulong val)
1187d36db35SAvi Kivity {
1197d36db35SAvi Kivity     asm volatile ("mov %0, %%cr0" : : "r"(val) : "memory");
1207d36db35SAvi Kivity }
1217d36db35SAvi Kivity 
1227d36db35SAvi Kivity static inline ulong read_cr0(void)
1237d36db35SAvi Kivity {
1247d36db35SAvi Kivity     ulong val;
1257d36db35SAvi Kivity     asm volatile ("mov %%cr0, %0" : "=r"(val) : : "memory");
1267d36db35SAvi Kivity     return val;
1277d36db35SAvi Kivity }
1287d36db35SAvi Kivity 
1297d36db35SAvi Kivity static inline void write_cr2(ulong val)
1307d36db35SAvi Kivity {
1317d36db35SAvi Kivity     asm volatile ("mov %0, %%cr2" : : "r"(val) : "memory");
1327d36db35SAvi Kivity }
1337d36db35SAvi Kivity 
1347d36db35SAvi Kivity static inline ulong read_cr2(void)
1357d36db35SAvi Kivity {
1367d36db35SAvi Kivity     ulong val;
1377d36db35SAvi Kivity     asm volatile ("mov %%cr2, %0" : "=r"(val) : : "memory");
1387d36db35SAvi Kivity     return val;
1397d36db35SAvi Kivity }
1407d36db35SAvi Kivity 
1417d36db35SAvi Kivity static inline void write_cr3(ulong val)
1427d36db35SAvi Kivity {
1437d36db35SAvi Kivity     asm volatile ("mov %0, %%cr3" : : "r"(val) : "memory");
1447d36db35SAvi Kivity }
1457d36db35SAvi Kivity 
1467d36db35SAvi Kivity static inline ulong read_cr3(void)
1477d36db35SAvi Kivity {
1487d36db35SAvi Kivity     ulong val;
1497d36db35SAvi Kivity     asm volatile ("mov %%cr3, %0" : "=r"(val) : : "memory");
1507d36db35SAvi Kivity     return val;
1517d36db35SAvi Kivity }
1527d36db35SAvi Kivity 
1537d36db35SAvi Kivity static inline void write_cr4(ulong val)
1547d36db35SAvi Kivity {
1557d36db35SAvi Kivity     asm volatile ("mov %0, %%cr4" : : "r"(val) : "memory");
1567d36db35SAvi Kivity }
1577d36db35SAvi Kivity 
1587d36db35SAvi Kivity static inline ulong read_cr4(void)
1597d36db35SAvi Kivity {
1607d36db35SAvi Kivity     ulong val;
1617d36db35SAvi Kivity     asm volatile ("mov %%cr4, %0" : "=r"(val) : : "memory");
1627d36db35SAvi Kivity     return val;
1637d36db35SAvi Kivity }
1647d36db35SAvi Kivity 
1657d36db35SAvi Kivity static inline void write_cr8(ulong val)
1667d36db35SAvi Kivity {
1677d36db35SAvi Kivity     asm volatile ("mov %0, %%cr8" : : "r"(val) : "memory");
1687d36db35SAvi Kivity }
1697d36db35SAvi Kivity 
1707d36db35SAvi Kivity static inline ulong read_cr8(void)
1717d36db35SAvi Kivity {
1727d36db35SAvi Kivity     ulong val;
1737d36db35SAvi Kivity     asm volatile ("mov %%cr8, %0" : "=r"(val) : : "memory");
1747d36db35SAvi Kivity     return val;
1757d36db35SAvi Kivity }
1767d36db35SAvi Kivity 
1777d36db35SAvi Kivity static inline void lgdt(const struct descriptor_table_ptr *ptr)
1787d36db35SAvi Kivity {
1797d36db35SAvi Kivity     asm volatile ("lgdt %0" : : "m"(*ptr));
1807d36db35SAvi Kivity }
1817d36db35SAvi Kivity 
1827d36db35SAvi Kivity static inline void sgdt(struct descriptor_table_ptr *ptr)
1837d36db35SAvi Kivity {
1847d36db35SAvi Kivity     asm volatile ("sgdt %0" : "=m"(*ptr));
1857d36db35SAvi Kivity }
1867d36db35SAvi Kivity 
1877d36db35SAvi Kivity static inline void lidt(const struct descriptor_table_ptr *ptr)
1887d36db35SAvi Kivity {
1897d36db35SAvi Kivity     asm volatile ("lidt %0" : : "m"(*ptr));
1907d36db35SAvi Kivity }
1917d36db35SAvi Kivity 
1927d36db35SAvi Kivity static inline void sidt(struct descriptor_table_ptr *ptr)
1937d36db35SAvi Kivity {
1947d36db35SAvi Kivity     asm volatile ("sidt %0" : "=m"(*ptr));
1957d36db35SAvi Kivity }
1967d36db35SAvi Kivity 
1977d36db35SAvi Kivity static inline void lldt(unsigned val)
1987d36db35SAvi Kivity {
1997d36db35SAvi Kivity     asm volatile ("lldt %0" : : "rm"(val));
2007d36db35SAvi Kivity }
2017d36db35SAvi Kivity 
2027d36db35SAvi Kivity static inline u16 sldt(void)
2037d36db35SAvi Kivity {
2047d36db35SAvi Kivity     u16 val;
2057d36db35SAvi Kivity     asm volatile ("sldt %0" : "=rm"(val));
2067d36db35SAvi Kivity     return val;
2077d36db35SAvi Kivity }
2087d36db35SAvi Kivity 
209fd5d3dc6SAvi Kivity static inline void ltr(u16 val)
2107d36db35SAvi Kivity {
2117d36db35SAvi Kivity     asm volatile ("ltr %0" : : "rm"(val));
2127d36db35SAvi Kivity }
2137d36db35SAvi Kivity 
2147d36db35SAvi Kivity static inline u16 str(void)
2157d36db35SAvi Kivity {
2167d36db35SAvi Kivity     u16 val;
2177d36db35SAvi Kivity     asm volatile ("str %0" : "=rm"(val));
2187d36db35SAvi Kivity     return val;
2197d36db35SAvi Kivity }
2207d36db35SAvi Kivity 
2217d36db35SAvi Kivity static inline void write_dr6(ulong val)
2227d36db35SAvi Kivity {
2237d36db35SAvi Kivity     asm volatile ("mov %0, %%dr6" : : "r"(val) : "memory");
2247d36db35SAvi Kivity }
2257d36db35SAvi Kivity 
2267d36db35SAvi Kivity static inline ulong read_dr6(void)
2277d36db35SAvi Kivity {
2287d36db35SAvi Kivity     ulong val;
2297d36db35SAvi Kivity     asm volatile ("mov %%dr6, %0" : "=r"(val));
2307d36db35SAvi Kivity     return val;
2317d36db35SAvi Kivity }
2327d36db35SAvi Kivity 
2337d36db35SAvi Kivity static inline void write_dr7(ulong val)
2347d36db35SAvi Kivity {
2357d36db35SAvi Kivity     asm volatile ("mov %0, %%dr7" : : "r"(val) : "memory");
2367d36db35SAvi Kivity }
2377d36db35SAvi Kivity 
2387d36db35SAvi Kivity static inline ulong read_dr7(void)
2397d36db35SAvi Kivity {
2407d36db35SAvi Kivity     ulong val;
2417d36db35SAvi Kivity     asm volatile ("mov %%dr7, %0" : "=r"(val));
2427d36db35SAvi Kivity     return val;
2437d36db35SAvi Kivity }
2447d36db35SAvi Kivity 
2457d36db35SAvi Kivity struct cpuid { u32 a, b, c, d; };
2467d36db35SAvi Kivity 
2477d36db35SAvi Kivity static inline struct cpuid cpuid_indexed(u32 function, u32 index)
2487d36db35SAvi Kivity {
2497d36db35SAvi Kivity     struct cpuid r;
2507d36db35SAvi Kivity     asm volatile ("cpuid"
2517d36db35SAvi Kivity                   : "=a"(r.a), "=b"(r.b), "=c"(r.c), "=d"(r.d)
2527d36db35SAvi Kivity                   : "0"(function), "2"(index));
2537d36db35SAvi Kivity     return r;
2547d36db35SAvi Kivity }
2557d36db35SAvi Kivity 
2567d36db35SAvi Kivity static inline struct cpuid cpuid(u32 function)
2577d36db35SAvi Kivity {
2587d36db35SAvi Kivity     return cpuid_indexed(function, 0);
2597d36db35SAvi Kivity }
2607d36db35SAvi Kivity 
2617d36db35SAvi Kivity static inline void pause(void)
2627d36db35SAvi Kivity {
2637d36db35SAvi Kivity     asm volatile ("pause");
2647d36db35SAvi Kivity }
2657d36db35SAvi Kivity 
2667d36db35SAvi Kivity static inline void cli(void)
2677d36db35SAvi Kivity {
2687d36db35SAvi Kivity     asm volatile ("cli");
2697d36db35SAvi Kivity }
2707d36db35SAvi Kivity 
2717d36db35SAvi Kivity static inline void sti(void)
2727d36db35SAvi Kivity {
2737d36db35SAvi Kivity     asm volatile ("sti");
2747d36db35SAvi Kivity }
2757d36db35SAvi Kivity 
2760d7251beSJason Wang static inline unsigned long long rdtsc()
2770d7251beSJason Wang {
2780d7251beSJason Wang 	long long r;
2790d7251beSJason Wang 
2800d7251beSJason Wang #ifdef __x86_64__
2810d7251beSJason Wang 	unsigned a, d;
2820d7251beSJason Wang 
2830d7251beSJason Wang 	asm volatile ("rdtsc" : "=a"(a), "=d"(d));
2840d7251beSJason Wang 	r = a | ((long long)d << 32);
2850d7251beSJason Wang #else
2860d7251beSJason Wang 	asm volatile ("rdtsc" : "=A"(r));
2870d7251beSJason Wang #endif
2880d7251beSJason Wang 	return r;
2890d7251beSJason Wang }
2900d7251beSJason Wang 
2910d7251beSJason Wang static inline void wrtsc(u64 tsc)
2920d7251beSJason Wang {
2930d7251beSJason Wang 	unsigned a = tsc, d = tsc >> 32;
2940d7251beSJason Wang 
2950d7251beSJason Wang 	asm volatile("wrmsr" : : "a"(a), "d"(d), "c"(0x10));
2960d7251beSJason Wang }
2970d7251beSJason Wang 
298ae0a920bSGleb Natapov static inline void irq_disable(void)
299ae0a920bSGleb Natapov {
300ae0a920bSGleb Natapov     asm volatile("cli");
301ae0a920bSGleb Natapov }
302ae0a920bSGleb Natapov 
303ae0a920bSGleb Natapov static inline void irq_enable(void)
304ae0a920bSGleb Natapov {
305ae0a920bSGleb Natapov     asm volatile("sti");
306ae0a920bSGleb Natapov }
307ae0a920bSGleb Natapov 
3084029c34bSGleb Natapov static inline void invlpg(void *va)
3094029c34bSGleb Natapov {
3104029c34bSGleb Natapov 	asm volatile("invlpg (%0)" ::"r" (va) : "memory");
3114029c34bSGleb Natapov }
312334cd2bfSGleb Natapov 
313334cd2bfSGleb Natapov static inline void safe_halt(void)
314334cd2bfSGleb Natapov {
315334cd2bfSGleb Natapov 	asm volatile("sti; hlt");
316334cd2bfSGleb Natapov }
3179d7eaa29SArthur Chunqi Li 
3189d7eaa29SArthur Chunqi Li #ifdef __x86_64__
3199d7eaa29SArthur Chunqi Li static inline u64 read_rflags(void)
3209d7eaa29SArthur Chunqi Li {
3219d7eaa29SArthur Chunqi Li 	u64 r;
3229d7eaa29SArthur Chunqi Li 	asm volatile("pushf; pop %0\n\t" : "=q"(r) : : "cc");
3239d7eaa29SArthur Chunqi Li 	return r;
3249d7eaa29SArthur Chunqi Li }
3259d7eaa29SArthur Chunqi Li 
3269d7eaa29SArthur Chunqi Li static inline void write_rflags(u64 r)
3279d7eaa29SArthur Chunqi Li {
3289d7eaa29SArthur Chunqi Li 	asm volatile("push %0; popf\n\t" : : "q"(r) : "cc");
3299d7eaa29SArthur Chunqi Li }
3309d7eaa29SArthur Chunqi Li #endif
3319d7eaa29SArthur Chunqi Li 
3327d36db35SAvi Kivity #endif
333