xref: /kvm-unit-tests/lib/x86/processor.h (revision dd5d5bf1bc5bfc0eb3d8d45b1e44e18ed7f165f2)
1c865f654SCornelia Huck #ifndef _X86_PROCESSOR_H_
2c865f654SCornelia Huck #define _X86_PROCESSOR_H_
37d36db35SAvi Kivity 
47d36db35SAvi Kivity #include "libcflat.h"
5142ff635SSean Christopherson #include "desc.h"
6867f820dSPaolo Bonzini #include "msr.h"
7e2f3fe1dSSean Christopherson #include <bitops.h>
82b2d7aadSAvi Kivity #include <stdint.h>
97d36db35SAvi Kivity 
1088f0bb17SSean Christopherson #define NONCANONICAL	0xaaaaaaaaaaaaaaaaull
1188f0bb17SSean Christopherson 
12a3d1fb55SPaolo Bonzini #ifdef __x86_64__
13a3d1fb55SPaolo Bonzini #  define R "r"
14a3d1fb55SPaolo Bonzini #  define W "q"
15a3d1fb55SPaolo Bonzini #  define S "8"
16a3d1fb55SPaolo Bonzini #else
17a3d1fb55SPaolo Bonzini #  define R "e"
18a3d1fb55SPaolo Bonzini #  define W "l"
19a3d1fb55SPaolo Bonzini #  define S "4"
20a3d1fb55SPaolo Bonzini #endif
21a3d1fb55SPaolo Bonzini 
222b934609SXiaoyao Li #define DB_VECTOR 1
232b934609SXiaoyao Li #define BP_VECTOR 3
242b934609SXiaoyao Li #define UD_VECTOR 6
258d2cdb35SMarc Orr #define DF_VECTOR 8
268d2cdb35SMarc Orr #define TS_VECTOR 10
278d2cdb35SMarc Orr #define NP_VECTOR 11
288d2cdb35SMarc Orr #define SS_VECTOR 12
298d2cdb35SMarc Orr #define GP_VECTOR 13
308d2cdb35SMarc Orr #define PF_VECTOR 14
318d2cdb35SMarc Orr #define AC_VECTOR 17
32c986dbe8SNadav Amit #define CP_VECTOR 21
338d2cdb35SMarc Orr 
34a106b30dSPaolo Bonzini #define X86_CR0_PE_BIT		(0)
35a106b30dSPaolo Bonzini #define X86_CR0_PE		BIT(X86_CR0_PE_BIT)
36a106b30dSPaolo Bonzini #define X86_CR0_MP_BIT		(1)
37a106b30dSPaolo Bonzini #define X86_CR0_MP		BIT(X86_CR0_MP_BIT)
38a106b30dSPaolo Bonzini #define X86_CR0_EM_BIT		(2)
39a106b30dSPaolo Bonzini #define X86_CR0_EM		BIT(X86_CR0_EM_BIT)
40a106b30dSPaolo Bonzini #define X86_CR0_TS_BIT		(3)
41a106b30dSPaolo Bonzini #define X86_CR0_TS		BIT(X86_CR0_TS_BIT)
42a106b30dSPaolo Bonzini #define X86_CR0_ET_BIT		(4)
43a106b30dSPaolo Bonzini #define X86_CR0_ET		BIT(X86_CR0_ET_BIT)
44a106b30dSPaolo Bonzini #define X86_CR0_NE_BIT		(5)
45a106b30dSPaolo Bonzini #define X86_CR0_NE		BIT(X86_CR0_NE_BIT)
46a106b30dSPaolo Bonzini #define X86_CR0_WP_BIT		(16)
47a106b30dSPaolo Bonzini #define X86_CR0_WP		BIT(X86_CR0_WP_BIT)
48a106b30dSPaolo Bonzini #define X86_CR0_AM_BIT		(18)
49a106b30dSPaolo Bonzini #define X86_CR0_AM		BIT(X86_CR0_AM_BIT)
50a106b30dSPaolo Bonzini #define X86_CR0_NW_BIT		(29)
51a106b30dSPaolo Bonzini #define X86_CR0_NW		BIT(X86_CR0_NW_BIT)
52a106b30dSPaolo Bonzini #define X86_CR0_CD_BIT		(30)
53a106b30dSPaolo Bonzini #define X86_CR0_CD		BIT(X86_CR0_CD_BIT)
54a106b30dSPaolo Bonzini #define X86_CR0_PG_BIT		(31)
55a106b30dSPaolo Bonzini #define X86_CR0_PG		BIT(X86_CR0_PG_BIT)
56b6a0ff03SPaolo Bonzini 
57e2f3fe1dSSean Christopherson #define X86_CR3_PCID_MASK	GENMASK(11, 0)
58e2f3fe1dSSean Christopherson 
59a106b30dSPaolo Bonzini #define X86_CR4_VME_BIT		(0)
60a106b30dSPaolo Bonzini #define X86_CR4_VME		BIT(X86_CR4_VME_BIT)
61a106b30dSPaolo Bonzini #define X86_CR4_PVI_BIT		(1)
62a106b30dSPaolo Bonzini #define X86_CR4_PVI		BIT(X86_CR4_PVI_BIT)
63a106b30dSPaolo Bonzini #define X86_CR4_TSD_BIT		(2)
64a106b30dSPaolo Bonzini #define X86_CR4_TSD		BIT(X86_CR4_TSD_BIT)
65a106b30dSPaolo Bonzini #define X86_CR4_DE_BIT		(3)
66a106b30dSPaolo Bonzini #define X86_CR4_DE		BIT(X86_CR4_DE_BIT)
67a106b30dSPaolo Bonzini #define X86_CR4_PSE_BIT		(4)
68a106b30dSPaolo Bonzini #define X86_CR4_PSE		BIT(X86_CR4_PSE_BIT)
69a106b30dSPaolo Bonzini #define X86_CR4_PAE_BIT		(5)
70a106b30dSPaolo Bonzini #define X86_CR4_PAE		BIT(X86_CR4_PAE_BIT)
71a106b30dSPaolo Bonzini #define X86_CR4_MCE_BIT		(6)
72a106b30dSPaolo Bonzini #define X86_CR4_MCE		BIT(X86_CR4_MCE_BIT)
73a106b30dSPaolo Bonzini #define X86_CR4_PGE_BIT		(7)
74a106b30dSPaolo Bonzini #define X86_CR4_PGE		BIT(X86_CR4_PGE_BIT)
75a106b30dSPaolo Bonzini #define X86_CR4_PCE_BIT		(8)
76a106b30dSPaolo Bonzini #define X86_CR4_PCE		BIT(X86_CR4_PCE_BIT)
77a106b30dSPaolo Bonzini #define X86_CR4_OSFXSR_BIT	(9)
78a106b30dSPaolo Bonzini #define X86_CR4_OSFXSR		BIT(X86_CR4_OSFXSR_BIT)
79a106b30dSPaolo Bonzini #define X86_CR4_OSXMMEXCPT_BIT	(10)
80a106b30dSPaolo Bonzini #define X86_CR4_OSXMMEXCPT	BIT(X86_CR4_OSXMMEXCPT_BIT)
81a106b30dSPaolo Bonzini #define X86_CR4_UMIP_BIT	(11)
82a106b30dSPaolo Bonzini #define X86_CR4_UMIP		BIT(X86_CR4_UMIP_BIT)
83a106b30dSPaolo Bonzini #define X86_CR4_LA57_BIT	(12)
84a106b30dSPaolo Bonzini #define X86_CR4_LA57		BIT(X86_CR4_LA57_BIT)
85a106b30dSPaolo Bonzini #define X86_CR4_VMXE_BIT	(13)
86a106b30dSPaolo Bonzini #define X86_CR4_VMXE		BIT(X86_CR4_VMXE_BIT)
87a106b30dSPaolo Bonzini #define X86_CR4_SMXE_BIT	(14)
88a106b30dSPaolo Bonzini #define X86_CR4_SMXE		BIT(X86_CR4_SMXE_BIT)
89a106b30dSPaolo Bonzini /* UNUSED			(15) */
90a106b30dSPaolo Bonzini #define X86_CR4_FSGSBASE_BIT	(16)
91a106b30dSPaolo Bonzini #define X86_CR4_FSGSBASE	BIT(X86_CR4_FSGSBASE_BIT)
92a106b30dSPaolo Bonzini #define X86_CR4_PCIDE_BIT	(17)
93a106b30dSPaolo Bonzini #define X86_CR4_PCIDE		BIT(X86_CR4_PCIDE_BIT)
94a106b30dSPaolo Bonzini #define X86_CR4_OSXSAVE_BIT	(18)
95a106b30dSPaolo Bonzini #define X86_CR4_OSXSAVE		BIT(X86_CR4_OSXSAVE_BIT)
96a106b30dSPaolo Bonzini #define X86_CR4_KL_BIT		(19)
97a106b30dSPaolo Bonzini #define X86_CR4_KL		BIT(X86_CR4_KL_BIT)
98a106b30dSPaolo Bonzini #define X86_CR4_SMEP_BIT	(20)
99a106b30dSPaolo Bonzini #define X86_CR4_SMEP		BIT(X86_CR4_SMEP_BIT)
100a106b30dSPaolo Bonzini #define X86_CR4_SMAP_BIT	(21)
101a106b30dSPaolo Bonzini #define X86_CR4_SMAP		BIT(X86_CR4_SMAP_BIT)
102a106b30dSPaolo Bonzini #define X86_CR4_PKE_BIT		(22)
103a106b30dSPaolo Bonzini #define X86_CR4_PKE		BIT(X86_CR4_PKE_BIT)
104a106b30dSPaolo Bonzini #define X86_CR4_CET_BIT		(23)
105a106b30dSPaolo Bonzini #define X86_CR4_CET		BIT(X86_CR4_CET_BIT)
106a106b30dSPaolo Bonzini #define X86_CR4_PKS_BIT		(24)
107a106b30dSPaolo Bonzini #define X86_CR4_PKS		BIT(X86_CR4_PKS_BIT)
108e2f3fe1dSSean Christopherson 
109a106b30dSPaolo Bonzini #define X86_EFLAGS_CF_BIT	(0)
110a106b30dSPaolo Bonzini #define X86_EFLAGS_CF		BIT(X86_EFLAGS_CF_BIT)
111a106b30dSPaolo Bonzini #define X86_EFLAGS_FIXED_BIT	(1)
112a106b30dSPaolo Bonzini #define X86_EFLAGS_FIXED	BIT(X86_EFLAGS_FIXED_BIT)
113a106b30dSPaolo Bonzini #define X86_EFLAGS_PF_BIT	(2)
114a106b30dSPaolo Bonzini #define X86_EFLAGS_PF		BIT(X86_EFLAGS_PF_BIT)
115a106b30dSPaolo Bonzini /* RESERVED 0			(3) */
116a106b30dSPaolo Bonzini #define X86_EFLAGS_AF_BIT	(4)
117a106b30dSPaolo Bonzini #define X86_EFLAGS_AF		BIT(X86_EFLAGS_AF_BIT)
118a106b30dSPaolo Bonzini /* RESERVED 0			(5) */
119a106b30dSPaolo Bonzini #define X86_EFLAGS_ZF_BIT	(6)
120a106b30dSPaolo Bonzini #define X86_EFLAGS_ZF		BIT(X86_EFLAGS_ZF_BIT)
121a106b30dSPaolo Bonzini #define X86_EFLAGS_SF_BIT	(7)
122a106b30dSPaolo Bonzini #define X86_EFLAGS_SF		BIT(X86_EFLAGS_SF_BIT)
123a106b30dSPaolo Bonzini #define X86_EFLAGS_TF_BIT	(8)
124a106b30dSPaolo Bonzini #define X86_EFLAGS_TF		BIT(X86_EFLAGS_TF_BIT)
125a106b30dSPaolo Bonzini #define X86_EFLAGS_IF_BIT	(9)
126a106b30dSPaolo Bonzini #define X86_EFLAGS_IF		BIT(X86_EFLAGS_IF_BIT)
127a106b30dSPaolo Bonzini #define X86_EFLAGS_DF_BIT	(10)
128a106b30dSPaolo Bonzini #define X86_EFLAGS_DF		BIT(X86_EFLAGS_DF_BIT)
129a106b30dSPaolo Bonzini #define X86_EFLAGS_OF_BIT	(11)
130a106b30dSPaolo Bonzini #define X86_EFLAGS_OF		BIT(X86_EFLAGS_OF_BIT)
131e2f3fe1dSSean Christopherson #define X86_EFLAGS_IOPL		GENMASK(13, 12)
132a106b30dSPaolo Bonzini #define X86_EFLAGS_NT_BIT	(14)
133a106b30dSPaolo Bonzini #define X86_EFLAGS_NT		BIT(X86_EFLAGS_NT_BIT)
134a106b30dSPaolo Bonzini /* RESERVED 0			(15) */
135a106b30dSPaolo Bonzini #define X86_EFLAGS_RF_BIT	(16)
136a106b30dSPaolo Bonzini #define X86_EFLAGS_RF		BIT(X86_EFLAGS_RF_BIT)
137a106b30dSPaolo Bonzini #define X86_EFLAGS_VM_BIT	(17)
138a106b30dSPaolo Bonzini #define X86_EFLAGS_VM		BIT(X86_EFLAGS_VM_BIT)
139a106b30dSPaolo Bonzini #define X86_EFLAGS_AC_BIT	(18)
140a106b30dSPaolo Bonzini #define X86_EFLAGS_AC		BIT(X86_EFLAGS_AC_BIT)
141a106b30dSPaolo Bonzini #define X86_EFLAGS_VIF_BIT	(19)
142a106b30dSPaolo Bonzini #define X86_EFLAGS_VIF		BIT(X86_EFLAGS_VIF_BIT)
143a106b30dSPaolo Bonzini #define X86_EFLAGS_VIP_BIT	(20)
144a106b30dSPaolo Bonzini #define X86_EFLAGS_VIP		BIT(X86_EFLAGS_VIP_BIT)
145a106b30dSPaolo Bonzini #define X86_EFLAGS_ID_BIT	(21)
146a106b30dSPaolo Bonzini #define X86_EFLAGS_ID		BIT(X86_EFLAGS_ID_BIT)
1477488d290SPaolo Bonzini 
14860d8090cSLiran Alon #define X86_EFLAGS_ALU (X86_EFLAGS_CF | X86_EFLAGS_PF | X86_EFLAGS_AF | \
14960d8090cSLiran Alon 			X86_EFLAGS_ZF | X86_EFLAGS_SF | X86_EFLAGS_OF)
15060d8090cSLiran Alon 
151a3d1fb55SPaolo Bonzini 
1526ddcc298SKrish Sadhukhan /*
1536ddcc298SKrish Sadhukhan  * CPU features
1546ddcc298SKrish Sadhukhan  */
1556ddcc298SKrish Sadhukhan 
1566ddcc298SKrish Sadhukhan enum cpuid_output_regs {
1576ddcc298SKrish Sadhukhan 	EAX,
1586ddcc298SKrish Sadhukhan 	EBX,
1596ddcc298SKrish Sadhukhan 	ECX,
1606ddcc298SKrish Sadhukhan 	EDX
1616ddcc298SKrish Sadhukhan };
1626ddcc298SKrish Sadhukhan 
1636ddcc298SKrish Sadhukhan struct cpuid { u32 a, b, c, d; };
1646ddcc298SKrish Sadhukhan 
1656ddcc298SKrish Sadhukhan static inline struct cpuid raw_cpuid(u32 function, u32 index)
1666ddcc298SKrish Sadhukhan {
1676ddcc298SKrish Sadhukhan 	struct cpuid r;
1686ddcc298SKrish Sadhukhan 	asm volatile ("cpuid"
1696ddcc298SKrish Sadhukhan 		      : "=a"(r.a), "=b"(r.b), "=c"(r.c), "=d"(r.d)
1706ddcc298SKrish Sadhukhan 		      : "0"(function), "2"(index));
1716ddcc298SKrish Sadhukhan 	return r;
1726ddcc298SKrish Sadhukhan }
1736ddcc298SKrish Sadhukhan 
1746ddcc298SKrish Sadhukhan static inline struct cpuid cpuid_indexed(u32 function, u32 index)
1756ddcc298SKrish Sadhukhan {
1766ddcc298SKrish Sadhukhan 	u32 level = raw_cpuid(function & 0xf0000000, 0).a;
1776ddcc298SKrish Sadhukhan 	if (level < function)
1786ddcc298SKrish Sadhukhan 	return (struct cpuid) { 0, 0, 0, 0 };
1796ddcc298SKrish Sadhukhan 	return raw_cpuid(function, index);
1806ddcc298SKrish Sadhukhan }
1816ddcc298SKrish Sadhukhan 
1826ddcc298SKrish Sadhukhan static inline struct cpuid cpuid(u32 function)
1836ddcc298SKrish Sadhukhan {
1846ddcc298SKrish Sadhukhan 	return cpuid_indexed(function, 0);
1856ddcc298SKrish Sadhukhan }
1866ddcc298SKrish Sadhukhan 
1876ddcc298SKrish Sadhukhan static inline u8 cpuid_maxphyaddr(void)
1886ddcc298SKrish Sadhukhan {
1896ddcc298SKrish Sadhukhan 	if (raw_cpuid(0x80000000, 0).a < 0x80000008)
1906ddcc298SKrish Sadhukhan 	return 36;
1916ddcc298SKrish Sadhukhan 	return raw_cpuid(0x80000008, 0).a & 0xff;
1926ddcc298SKrish Sadhukhan }
1936ddcc298SKrish Sadhukhan 
19422abdd39SNadav Amit static inline bool is_intel(void)
19522abdd39SNadav Amit {
19622abdd39SNadav Amit 	struct cpuid c = cpuid(0);
19722abdd39SNadav Amit 	u32 name[4] = {c.b, c.d, c.c };
19822abdd39SNadav Amit 
19922abdd39SNadav Amit 	return strcmp((char *)name, "GenuineIntel") == 0;
20022abdd39SNadav Amit }
20122abdd39SNadav Amit 
2026ddcc298SKrish Sadhukhan #define	CPUID(a, b, c, d) ((((unsigned long long) a) << 32) | (b << 16) | \
2036ddcc298SKrish Sadhukhan 			  (c << 8) | d)
2046ddcc298SKrish Sadhukhan 
2056ddcc298SKrish Sadhukhan /*
2066ddcc298SKrish Sadhukhan  * Each X86_FEATURE_XXX definition is 64-bit and contains the following
2076ddcc298SKrish Sadhukhan  * CPUID meta-data:
2086ddcc298SKrish Sadhukhan  *
2096ddcc298SKrish Sadhukhan  * 	[63:32] :  input value for EAX
2106ddcc298SKrish Sadhukhan  * 	[31:16] :  input value for ECX
2116ddcc298SKrish Sadhukhan  * 	[15:8]  :  output register
2126ddcc298SKrish Sadhukhan  * 	[7:0]   :  bit position in output register
2136ddcc298SKrish Sadhukhan  */
2146ddcc298SKrish Sadhukhan 
2156ddcc298SKrish Sadhukhan /*
216b52bf046SSean Christopherson  * Basic Leafs, a.k.a. Intel defined
2176ddcc298SKrish Sadhukhan  */
2186ddcc298SKrish Sadhukhan #define	X86_FEATURE_MWAIT		(CPUID(0x1, 0, ECX, 3))
2196ddcc298SKrish Sadhukhan #define	X86_FEATURE_VMX			(CPUID(0x1, 0, ECX, 5))
2209d9000a5SYang Weijiang #define	X86_FEATURE_PDCM		(CPUID(0x1, 0, ECX, 15))
2216ddcc298SKrish Sadhukhan #define	X86_FEATURE_PCID		(CPUID(0x1, 0, ECX, 17))
222baf248c5SSean Christopherson #define X86_FEATURE_X2APIC		(CPUID(0x1, 0, ECX, 21))
2236ddcc298SKrish Sadhukhan #define	X86_FEATURE_MOVBE		(CPUID(0x1, 0, ECX, 22))
2246ddcc298SKrish Sadhukhan #define	X86_FEATURE_TSC_DEADLINE_TIMER	(CPUID(0x1, 0, ECX, 24))
2256ddcc298SKrish Sadhukhan #define	X86_FEATURE_XSAVE		(CPUID(0x1, 0, ECX, 26))
2266ddcc298SKrish Sadhukhan #define	X86_FEATURE_OSXSAVE		(CPUID(0x1, 0, ECX, 27))
2276ddcc298SKrish Sadhukhan #define	X86_FEATURE_RDRAND		(CPUID(0x1, 0, ECX, 30))
2286ddcc298SKrish Sadhukhan #define	X86_FEATURE_MCE			(CPUID(0x1, 0, EDX, 7))
2296ddcc298SKrish Sadhukhan #define	X86_FEATURE_APIC		(CPUID(0x1, 0, EDX, 9))
2306ddcc298SKrish Sadhukhan #define	X86_FEATURE_CLFLUSH		(CPUID(0x1, 0, EDX, 19))
2316ddcc298SKrish Sadhukhan #define	X86_FEATURE_XMM			(CPUID(0x1, 0, EDX, 25))
2326ddcc298SKrish Sadhukhan #define	X86_FEATURE_XMM2		(CPUID(0x1, 0, EDX, 26))
2336ddcc298SKrish Sadhukhan #define	X86_FEATURE_TSC_ADJUST		(CPUID(0x7, 0, EBX, 1))
2346163f75dSPaolo Bonzini #define	X86_FEATURE_HLE			(CPUID(0x7, 0, EBX, 4))
23597b5f955SSean Christopherson #define	X86_FEATURE_SMEP		(CPUID(0x7, 0, EBX, 7))
2366ddcc298SKrish Sadhukhan #define	X86_FEATURE_INVPCID		(CPUID(0x7, 0, EBX, 10))
2376ddcc298SKrish Sadhukhan #define	X86_FEATURE_RTM			(CPUID(0x7, 0, EBX, 11))
2386ddcc298SKrish Sadhukhan #define	X86_FEATURE_SMAP		(CPUID(0x7, 0, EBX, 20))
2396ddcc298SKrish Sadhukhan #define	X86_FEATURE_PCOMMIT		(CPUID(0x7, 0, EBX, 22))
2406ddcc298SKrish Sadhukhan #define	X86_FEATURE_CLFLUSHOPT		(CPUID(0x7, 0, EBX, 23))
2416ddcc298SKrish Sadhukhan #define	X86_FEATURE_CLWB		(CPUID(0x7, 0, EBX, 24))
2426ddcc298SKrish Sadhukhan #define	X86_FEATURE_UMIP		(CPUID(0x7, 0, ECX, 2))
2436ddcc298SKrish Sadhukhan #define	X86_FEATURE_PKU			(CPUID(0x7, 0, ECX, 3))
2446ddcc298SKrish Sadhukhan #define	X86_FEATURE_LA57		(CPUID(0x7, 0, ECX, 16))
2456ddcc298SKrish Sadhukhan #define	X86_FEATURE_RDPID		(CPUID(0x7, 0, ECX, 22))
24679e53994SYang Weijiang #define	X86_FEATURE_SHSTK		(CPUID(0x7, 0, ECX, 7))
24779e53994SYang Weijiang #define	X86_FEATURE_IBT			(CPUID(0x7, 0, EDX, 20))
2486ddcc298SKrish Sadhukhan #define	X86_FEATURE_SPEC_CTRL		(CPUID(0x7, 0, EDX, 26))
2495cf6a3faSSean Christopherson #define	X86_FEATURE_FLUSH_L1D		(CPUID(0x7, 0, EDX, 28))
2506163f75dSPaolo Bonzini #define	X86_FEATURE_ARCH_CAPABILITIES	(CPUID(0x7, 0, EDX, 29))
251fdae6092SChenyi Qiang #define	X86_FEATURE_PKS			(CPUID(0x7, 0, ECX, 31))
2526ddcc298SKrish Sadhukhan 
2536ddcc298SKrish Sadhukhan /*
254b52bf046SSean Christopherson  * Extended Leafs, a.k.a. AMD defined
2556ddcc298SKrish Sadhukhan  */
2566ddcc298SKrish Sadhukhan #define	X86_FEATURE_SVM			(CPUID(0x80000001, 0, ECX, 2))
257b883751aSLike Xu #define	X86_FEATURE_PERFCTR_CORE	(CPUID(0x80000001, 0, ECX, 23))
258b52bf046SSean Christopherson #define	X86_FEATURE_NX			(CPUID(0x80000001, 0, EDX, 20))
259b52bf046SSean Christopherson #define	X86_FEATURE_GBPAGES		(CPUID(0x80000001, 0, EDX, 26))
2606ddcc298SKrish Sadhukhan #define	X86_FEATURE_RDTSCP		(CPUID(0x80000001, 0, EDX, 27))
261b52bf046SSean Christopherson #define	X86_FEATURE_LM			(CPUID(0x80000001, 0, EDX, 29))
262b52bf046SSean Christopherson #define	X86_FEATURE_RDPRU		(CPUID(0x80000008, 0, EBX, 4))
2636ddcc298SKrish Sadhukhan #define	X86_FEATURE_AMD_IBPB		(CPUID(0x80000008, 0, EBX, 12))
2646ddcc298SKrish Sadhukhan #define	X86_FEATURE_NPT			(CPUID(0x8000000A, 0, EDX, 0))
265537d39dfSMaxim Levitsky #define	X86_FEATURE_LBRV		(CPUID(0x8000000A, 0, EDX, 1))
2666ddcc298SKrish Sadhukhan #define	X86_FEATURE_NRIPS		(CPUID(0x8000000A, 0, EDX, 3))
267a8503d50SMaxim Levitsky #define X86_FEATURE_TSCRATEMSR		(CPUID(0x8000000A, 0, EDX, 4))
2688650dffeSMaxim Levitsky #define X86_FEATURE_PAUSEFILTER		(CPUID(0x8000000A, 0, EDX, 10))
2698650dffeSMaxim Levitsky #define X86_FEATURE_PFTHRESHOLD		(CPUID(0x8000000A, 0, EDX, 12))
270f6972bd6SLara Lazier #define	X86_FEATURE_VGIF		(CPUID(0x8000000A, 0, EDX, 16))
27108200397SSantosh Shukla #define X86_FEATURE_VNMI		(CPUID(0x8000000A, 0, EDX, 25))
272952cf19cSLike Xu #define	X86_FEATURE_AMD_PMU_V2		(CPUID(0x80000022, 0, EAX, 0))
2736ddcc298SKrish Sadhukhan 
2746ddcc298SKrish Sadhukhan static inline bool this_cpu_has(u64 feature)
2756ddcc298SKrish Sadhukhan {
2766ddcc298SKrish Sadhukhan 	u32 input_eax = feature >> 32;
2776ddcc298SKrish Sadhukhan 	u32 input_ecx = (feature >> 16) & 0xffff;
2786ddcc298SKrish Sadhukhan 	u32 output_reg = (feature >> 8) & 0xff;
2796ddcc298SKrish Sadhukhan 	u8 bit = feature & 0xff;
2806ddcc298SKrish Sadhukhan 	struct cpuid c;
2816ddcc298SKrish Sadhukhan 	u32 *tmp;
2826ddcc298SKrish Sadhukhan 
2836ddcc298SKrish Sadhukhan 	c = cpuid_indexed(input_eax, input_ecx);
2846ddcc298SKrish Sadhukhan 	tmp = (u32 *)&c;
2856ddcc298SKrish Sadhukhan 
2866ddcc298SKrish Sadhukhan 	return ((*(tmp + (output_reg % 32))) & (1 << bit));
2876ddcc298SKrish Sadhukhan }
2886ddcc298SKrish Sadhukhan 
2891bde9127SJim Mattson struct far_pointer32 {
2901bde9127SJim Mattson 	u32 offset;
2911bde9127SJim Mattson 	u16 selector;
2921bde9127SJim Mattson } __attribute__((packed));
2931bde9127SJim Mattson 
2947d36db35SAvi Kivity struct descriptor_table_ptr {
2957d36db35SAvi Kivity 	u16 limit;
2967d36db35SAvi Kivity 	ulong base;
2977d36db35SAvi Kivity } __attribute__((packed));
2987d36db35SAvi Kivity 
299fa6318d1SPaolo Bonzini static inline void clac(void)
300fa6318d1SPaolo Bonzini {
301fa6318d1SPaolo Bonzini 	asm volatile (".byte 0x0f, 0x01, 0xca" : : : "memory");
302fa6318d1SPaolo Bonzini }
303fa6318d1SPaolo Bonzini 
304fa6318d1SPaolo Bonzini static inline void stac(void)
305fa6318d1SPaolo Bonzini {
306fa6318d1SPaolo Bonzini 	asm volatile (".byte 0x0f, 0x01, 0xcb" : : : "memory");
307fa6318d1SPaolo Bonzini }
308fa6318d1SPaolo Bonzini 
3097d36db35SAvi Kivity static inline u16 read_cs(void)
3107d36db35SAvi Kivity {
3117d36db35SAvi Kivity 	unsigned val;
3127d36db35SAvi Kivity 
313eab64501SPaolo Bonzini 	asm volatile ("mov %%cs, %0" : "=mr"(val));
3147d36db35SAvi Kivity 	return val;
3157d36db35SAvi Kivity }
3167d36db35SAvi Kivity 
3177d36db35SAvi Kivity static inline u16 read_ds(void)
3187d36db35SAvi Kivity {
3197d36db35SAvi Kivity 	unsigned val;
3207d36db35SAvi Kivity 
321eab64501SPaolo Bonzini 	asm volatile ("mov %%ds, %0" : "=mr"(val));
3227d36db35SAvi Kivity 	return val;
3237d36db35SAvi Kivity }
3247d36db35SAvi Kivity 
3257d36db35SAvi Kivity static inline u16 read_es(void)
3267d36db35SAvi Kivity {
3277d36db35SAvi Kivity 	unsigned val;
3287d36db35SAvi Kivity 
329eab64501SPaolo Bonzini 	asm volatile ("mov %%es, %0" : "=mr"(val));
3307d36db35SAvi Kivity 	return val;
3317d36db35SAvi Kivity }
3327d36db35SAvi Kivity 
3337d36db35SAvi Kivity static inline u16 read_ss(void)
3347d36db35SAvi Kivity {
3357d36db35SAvi Kivity 	unsigned val;
3367d36db35SAvi Kivity 
337eab64501SPaolo Bonzini 	asm volatile ("mov %%ss, %0" : "=mr"(val));
3387d36db35SAvi Kivity 	return val;
3397d36db35SAvi Kivity }
3407d36db35SAvi Kivity 
3417d36db35SAvi Kivity static inline u16 read_fs(void)
3427d36db35SAvi Kivity {
3437d36db35SAvi Kivity 	unsigned val;
3447d36db35SAvi Kivity 
345eab64501SPaolo Bonzini 	asm volatile ("mov %%fs, %0" : "=mr"(val));
3467d36db35SAvi Kivity 	return val;
3477d36db35SAvi Kivity }
3487d36db35SAvi Kivity 
3497d36db35SAvi Kivity static inline u16 read_gs(void)
3507d36db35SAvi Kivity {
3517d36db35SAvi Kivity 	unsigned val;
3527d36db35SAvi Kivity 
353eab64501SPaolo Bonzini 	asm volatile ("mov %%gs, %0" : "=mr"(val));
3547d36db35SAvi Kivity 	return val;
3557d36db35SAvi Kivity }
3567d36db35SAvi Kivity 
35777e03b63SGleb Natapov static inline unsigned long read_rflags(void)
35877e03b63SGleb Natapov {
35977e03b63SGleb Natapov 	unsigned long f;
360eab64501SPaolo Bonzini 	asm volatile ("pushf; pop %0\n\t" : "=rm"(f));
36177e03b63SGleb Natapov 	return f;
36277e03b63SGleb Natapov }
36377e03b63SGleb Natapov 
3647d36db35SAvi Kivity static inline void write_ds(unsigned val)
3657d36db35SAvi Kivity {
366eab64501SPaolo Bonzini 	asm volatile ("mov %0, %%ds" : : "rm"(val) : "memory");
3677d36db35SAvi Kivity }
3687d36db35SAvi Kivity 
3697d36db35SAvi Kivity static inline void write_es(unsigned val)
3707d36db35SAvi Kivity {
371eab64501SPaolo Bonzini 	asm volatile ("mov %0, %%es" : : "rm"(val) : "memory");
3727d36db35SAvi Kivity }
3737d36db35SAvi Kivity 
3747d36db35SAvi Kivity static inline void write_ss(unsigned val)
3757d36db35SAvi Kivity {
376eab64501SPaolo Bonzini 	asm volatile ("mov %0, %%ss" : : "rm"(val) : "memory");
3777d36db35SAvi Kivity }
3787d36db35SAvi Kivity 
3797d36db35SAvi Kivity static inline void write_fs(unsigned val)
3807d36db35SAvi Kivity {
381eab64501SPaolo Bonzini 	asm volatile ("mov %0, %%fs" : : "rm"(val) : "memory");
3827d36db35SAvi Kivity }
3837d36db35SAvi Kivity 
3847d36db35SAvi Kivity static inline void write_gs(unsigned val)
3857d36db35SAvi Kivity {
386eab64501SPaolo Bonzini 	asm volatile ("mov %0, %%gs" : : "rm"(val) : "memory");
3877d36db35SAvi Kivity }
3887d36db35SAvi Kivity 
3897488d290SPaolo Bonzini static inline void write_rflags(unsigned long f)
3907488d290SPaolo Bonzini {
391eab64501SPaolo Bonzini 	asm volatile ("push %0; popf\n\t" : : "rm"(f));
3927488d290SPaolo Bonzini }
3937488d290SPaolo Bonzini 
394728e71eeSPaolo Bonzini static inline void set_iopl(int iopl)
395728e71eeSPaolo Bonzini {
396728e71eeSPaolo Bonzini 	unsigned long flags = read_rflags() & ~X86_EFLAGS_IOPL;
397728e71eeSPaolo Bonzini 	flags |= iopl * (X86_EFLAGS_IOPL / 3);
398728e71eeSPaolo Bonzini 	write_rflags(flags);
399728e71eeSPaolo Bonzini }
400728e71eeSPaolo Bonzini 
40164c8b768SSean Christopherson /*
40264c8b768SSean Christopherson  * Don't use the safe variants for rdmsr() or wrmsr().  The exception fixup
40364c8b768SSean Christopherson  * infrastructure uses per-CPU data and thus consumes GS.base.  Various tests
40464c8b768SSean Christopherson  * temporarily modify MSR_GS_BASE and will explode when trying to determine
40564c8b768SSean Christopherson  * whether or not RDMSR/WRMSR faulted.
40664c8b768SSean Christopherson  */
4077d36db35SAvi Kivity static inline u64 rdmsr(u32 index)
4087d36db35SAvi Kivity {
4097d36db35SAvi Kivity 	u32 a, d;
4107d36db35SAvi Kivity 	asm volatile ("rdmsr" : "=a"(a), "=d"(d) : "c"(index) : "memory");
4117d36db35SAvi Kivity 	return a | ((u64)d << 32);
4127d36db35SAvi Kivity }
4137d36db35SAvi Kivity 
4147d36db35SAvi Kivity static inline void wrmsr(u32 index, u64 val)
4157d36db35SAvi Kivity {
4167d36db35SAvi Kivity 	u32 a = val, d = val >> 32;
4177d36db35SAvi Kivity 	asm volatile ("wrmsr" : : "a"(a), "d"(d), "c"(index) : "memory");
4187d36db35SAvi Kivity }
4197d36db35SAvi Kivity 
4200a4d8626SSean Christopherson static inline int rdmsr_safe(u32 index, uint64_t *val)
421142ff635SSean Christopherson {
4220a4d8626SSean Christopherson 	uint32_t a, d;
4230a4d8626SSean Christopherson 
424142ff635SSean Christopherson 	asm volatile (ASM_TRY("1f")
425142ff635SSean Christopherson 		      "rdmsr\n\t"
426142ff635SSean Christopherson 		      "1:"
4270a4d8626SSean Christopherson 		      : "=a"(a), "=d"(d)
4280a4d8626SSean Christopherson 		      : "c"(index) : "memory");
4290a4d8626SSean Christopherson 
4300a4d8626SSean Christopherson 	*val = (uint64_t)a | ((uint64_t)d << 32);
431142ff635SSean Christopherson 	return exception_vector();
432142ff635SSean Christopherson }
433142ff635SSean Christopherson 
4344143fbfdSSean Christopherson static inline int wrmsr_safe(u32 index, u64 val)
435142ff635SSean Christopherson {
436142ff635SSean Christopherson 	u32 a = val, d = val >> 32;
437142ff635SSean Christopherson 
438*dd5d5bf1SSean Christopherson 	return asm_safe("wrmsr", "a"(a), "d"(d), "c"(index));
439142ff635SSean Christopherson }
440142ff635SSean Christopherson 
44185c21181SLike Xu static inline int rdpmc_safe(u32 index, uint64_t *val)
4422b2d7aadSAvi Kivity {
4432b2d7aadSAvi Kivity 	uint32_t a, d;
44485c21181SLike Xu 
44585c21181SLike Xu 	asm volatile (ASM_TRY("1f")
44685c21181SLike Xu 		      "rdpmc\n\t"
44785c21181SLike Xu 		      "1:"
44885c21181SLike Xu 		      : "=a"(a), "=d"(d) : "c"(index) : "memory");
44985c21181SLike Xu 	*val = (uint64_t)a | ((uint64_t)d << 32);
45085c21181SLike Xu 	return exception_vector();
45185c21181SLike Xu }
45285c21181SLike Xu 
453eab2fcf3SThomas Huth static inline uint64_t rdpmc(uint32_t index)
45485c21181SLike Xu {
45585c21181SLike Xu 	uint64_t val;
45685c21181SLike Xu 	int vector = rdpmc_safe(index, &val);
45785c21181SLike Xu 
45896772b2eSLike Xu 	assert_msg(!vector, "Unexpected %s on RDPMC(%" PRId32 ")",
45985c21181SLike Xu 		   exception_mnemonic(vector), index);
46085c21181SLike Xu 	return val;
4612b2d7aadSAvi Kivity }
4622b2d7aadSAvi Kivity 
46364c8b768SSean Christopherson static inline int write_cr0_safe(ulong val)
46464c8b768SSean Christopherson {
465*dd5d5bf1SSean Christopherson 	return asm_safe("mov %0,%%cr0", "r" (val));
46664c8b768SSean Christopherson }
46764c8b768SSean Christopherson 
4687d36db35SAvi Kivity static inline void write_cr0(ulong val)
4697d36db35SAvi Kivity {
47064c8b768SSean Christopherson 	int vector = write_cr0_safe(val);
47164c8b768SSean Christopherson 
47264c8b768SSean Christopherson 	assert_msg(!vector, "Unexpected fault '%d' writing CR0 = %lx",
47364c8b768SSean Christopherson 		   vector, val);
4747d36db35SAvi Kivity }
4757d36db35SAvi Kivity 
4767d36db35SAvi Kivity static inline ulong read_cr0(void)
4777d36db35SAvi Kivity {
4787d36db35SAvi Kivity 	ulong val;
4797d36db35SAvi Kivity 	asm volatile ("mov %%cr0, %0" : "=r"(val) : : "memory");
4807d36db35SAvi Kivity 	return val;
4817d36db35SAvi Kivity }
4827d36db35SAvi Kivity 
4837d36db35SAvi Kivity static inline void write_cr2(ulong val)
4847d36db35SAvi Kivity {
4857d36db35SAvi Kivity 	asm volatile ("mov %0, %%cr2" : : "r"(val) : "memory");
4867d36db35SAvi Kivity }
4877d36db35SAvi Kivity 
4887d36db35SAvi Kivity static inline ulong read_cr2(void)
4897d36db35SAvi Kivity {
4907d36db35SAvi Kivity 	ulong val;
4917d36db35SAvi Kivity 	asm volatile ("mov %%cr2, %0" : "=r"(val) : : "memory");
4927d36db35SAvi Kivity 	return val;
4937d36db35SAvi Kivity }
4947d36db35SAvi Kivity 
49564c8b768SSean Christopherson static inline int write_cr3_safe(ulong val)
49664c8b768SSean Christopherson {
497*dd5d5bf1SSean Christopherson 	return asm_safe("mov %0,%%cr3", "r" (val));
49864c8b768SSean Christopherson }
49964c8b768SSean Christopherson 
5007d36db35SAvi Kivity static inline void write_cr3(ulong val)
5017d36db35SAvi Kivity {
50264c8b768SSean Christopherson 	int vector = write_cr3_safe(val);
50364c8b768SSean Christopherson 
50464c8b768SSean Christopherson 	assert_msg(!vector, "Unexpected fault '%d' writing CR3 = %lx",
50564c8b768SSean Christopherson 		   vector, val);
5067d36db35SAvi Kivity }
5077d36db35SAvi Kivity 
5087d36db35SAvi Kivity static inline ulong read_cr3(void)
5097d36db35SAvi Kivity {
5107d36db35SAvi Kivity 	ulong val;
5117d36db35SAvi Kivity 	asm volatile ("mov %%cr3, %0" : "=r"(val) : : "memory");
5127d36db35SAvi Kivity 	return val;
5137d36db35SAvi Kivity }
5147d36db35SAvi Kivity 
5151c320e18SYadong Qi static inline void update_cr3(void *cr3)
5161c320e18SYadong Qi {
5171c320e18SYadong Qi 	write_cr3((ulong)cr3);
5181c320e18SYadong Qi }
5191c320e18SYadong Qi 
52064c8b768SSean Christopherson static inline int write_cr4_safe(ulong val)
52164c8b768SSean Christopherson {
522*dd5d5bf1SSean Christopherson 	return asm_safe("mov %0,%%cr4", "r" (val));
52364c8b768SSean Christopherson }
52464c8b768SSean Christopherson 
5257d36db35SAvi Kivity static inline void write_cr4(ulong val)
5267d36db35SAvi Kivity {
52764c8b768SSean Christopherson 	int vector = write_cr4_safe(val);
52864c8b768SSean Christopherson 
52964c8b768SSean Christopherson 	assert_msg(!vector, "Unexpected fault '%d' writing CR4 = %lx",
53064c8b768SSean Christopherson 		   vector, val);
5317d36db35SAvi Kivity }
5327d36db35SAvi Kivity 
5337d36db35SAvi Kivity static inline ulong read_cr4(void)
5347d36db35SAvi Kivity {
5357d36db35SAvi Kivity 	ulong val;
5367d36db35SAvi Kivity 	asm volatile ("mov %%cr4, %0" : "=r"(val) : : "memory");
5377d36db35SAvi Kivity 	return val;
5387d36db35SAvi Kivity }
5397d36db35SAvi Kivity 
5407d36db35SAvi Kivity static inline void write_cr8(ulong val)
5417d36db35SAvi Kivity {
5427d36db35SAvi Kivity 	asm volatile ("mov %0, %%cr8" : : "r"(val) : "memory");
5437d36db35SAvi Kivity }
5447d36db35SAvi Kivity 
5457d36db35SAvi Kivity static inline ulong read_cr8(void)
5467d36db35SAvi Kivity {
5477d36db35SAvi Kivity 	ulong val;
5487d36db35SAvi Kivity 	asm volatile ("mov %%cr8, %0" : "=r"(val) : : "memory");
5497d36db35SAvi Kivity 	return val;
5507d36db35SAvi Kivity }
5517d36db35SAvi Kivity 
5527d36db35SAvi Kivity static inline void lgdt(const struct descriptor_table_ptr *ptr)
5537d36db35SAvi Kivity {
5547d36db35SAvi Kivity 	asm volatile ("lgdt %0" : : "m"(*ptr));
5557d36db35SAvi Kivity }
5567d36db35SAvi Kivity 
5577d36db35SAvi Kivity static inline void sgdt(struct descriptor_table_ptr *ptr)
5587d36db35SAvi Kivity {
5597d36db35SAvi Kivity 	asm volatile ("sgdt %0" : "=m"(*ptr));
5607d36db35SAvi Kivity }
5617d36db35SAvi Kivity 
5627d36db35SAvi Kivity static inline void lidt(const struct descriptor_table_ptr *ptr)
5637d36db35SAvi Kivity {
5647d36db35SAvi Kivity 	asm volatile ("lidt %0" : : "m"(*ptr));
5657d36db35SAvi Kivity }
5667d36db35SAvi Kivity 
5677d36db35SAvi Kivity static inline void sidt(struct descriptor_table_ptr *ptr)
5687d36db35SAvi Kivity {
5697d36db35SAvi Kivity 	asm volatile ("sidt %0" : "=m"(*ptr));
5707d36db35SAvi Kivity }
5717d36db35SAvi Kivity 
5727a14c1d9SJim Mattson static inline void lldt(u16 val)
5737d36db35SAvi Kivity {
5747d36db35SAvi Kivity 	asm volatile ("lldt %0" : : "rm"(val));
5757d36db35SAvi Kivity }
5767d36db35SAvi Kivity 
5777d36db35SAvi Kivity static inline u16 sldt(void)
5787d36db35SAvi Kivity {
5797d36db35SAvi Kivity 	u16 val;
5807d36db35SAvi Kivity 	asm volatile ("sldt %0" : "=rm"(val));
5817d36db35SAvi Kivity 	return val;
5827d36db35SAvi Kivity }
5837d36db35SAvi Kivity 
584fd5d3dc6SAvi Kivity static inline void ltr(u16 val)
5857d36db35SAvi Kivity {
5867d36db35SAvi Kivity 	asm volatile ("ltr %0" : : "rm"(val));
5877d36db35SAvi Kivity }
5887d36db35SAvi Kivity 
5897d36db35SAvi Kivity static inline u16 str(void)
5907d36db35SAvi Kivity {
5917d36db35SAvi Kivity 	u16 val;
5927d36db35SAvi Kivity 	asm volatile ("str %0" : "=rm"(val));
5937d36db35SAvi Kivity 	return val;
5947d36db35SAvi Kivity }
5957d36db35SAvi Kivity 
5967f8f7356SKrish Sadhukhan static inline void write_dr0(void *val)
5977f8f7356SKrish Sadhukhan {
5987f8f7356SKrish Sadhukhan 	asm volatile ("mov %0, %%dr0" : : "r"(val) : "memory");
5997f8f7356SKrish Sadhukhan }
6007f8f7356SKrish Sadhukhan 
6017f8f7356SKrish Sadhukhan static inline void write_dr1(void *val)
6027f8f7356SKrish Sadhukhan {
6037f8f7356SKrish Sadhukhan 	asm volatile ("mov %0, %%dr1" : : "r"(val) : "memory");
6047f8f7356SKrish Sadhukhan }
6057f8f7356SKrish Sadhukhan 
6067f8f7356SKrish Sadhukhan static inline void write_dr2(void *val)
6077f8f7356SKrish Sadhukhan {
6087f8f7356SKrish Sadhukhan 	asm volatile ("mov %0, %%dr2" : : "r"(val) : "memory");
6097f8f7356SKrish Sadhukhan }
6107f8f7356SKrish Sadhukhan 
6117f8f7356SKrish Sadhukhan static inline void write_dr3(void *val)
6127f8f7356SKrish Sadhukhan {
6137f8f7356SKrish Sadhukhan 	asm volatile ("mov %0, %%dr3" : : "r"(val) : "memory");
6147f8f7356SKrish Sadhukhan }
6157f8f7356SKrish Sadhukhan 
6167d36db35SAvi Kivity static inline void write_dr6(ulong val)
6177d36db35SAvi Kivity {
6187d36db35SAvi Kivity 	asm volatile ("mov %0, %%dr6" : : "r"(val) : "memory");
6197d36db35SAvi Kivity }
6207d36db35SAvi Kivity 
6217d36db35SAvi Kivity static inline ulong read_dr6(void)
6227d36db35SAvi Kivity {
6237d36db35SAvi Kivity 	ulong val;
6247d36db35SAvi Kivity 	asm volatile ("mov %%dr6, %0" : "=r"(val));
6257d36db35SAvi Kivity 	return val;
6267d36db35SAvi Kivity }
6277d36db35SAvi Kivity 
6287d36db35SAvi Kivity static inline void write_dr7(ulong val)
6297d36db35SAvi Kivity {
6307d36db35SAvi Kivity 	asm volatile ("mov %0, %%dr7" : : "r"(val) : "memory");
6317d36db35SAvi Kivity }
6327d36db35SAvi Kivity 
6337d36db35SAvi Kivity static inline ulong read_dr7(void)
6347d36db35SAvi Kivity {
6357d36db35SAvi Kivity 	ulong val;
6367d36db35SAvi Kivity 	asm volatile ("mov %%dr7, %0" : "=r"(val));
6377d36db35SAvi Kivity 	return val;
6387d36db35SAvi Kivity }
6397d36db35SAvi Kivity 
6407d36db35SAvi Kivity static inline void pause(void)
6417d36db35SAvi Kivity {
6427d36db35SAvi Kivity 	asm volatile ("pause");
6437d36db35SAvi Kivity }
6447d36db35SAvi Kivity 
6457d36db35SAvi Kivity static inline void cli(void)
6467d36db35SAvi Kivity {
6477d36db35SAvi Kivity 	asm volatile ("cli");
6487d36db35SAvi Kivity }
6497d36db35SAvi Kivity 
6507d36db35SAvi Kivity static inline void sti(void)
6517d36db35SAvi Kivity {
6527d36db35SAvi Kivity 	asm volatile ("sti");
6537d36db35SAvi Kivity }
6547d36db35SAvi Kivity 
655520e2789SBabu Moger static inline unsigned long long rdrand(void)
656520e2789SBabu Moger {
657520e2789SBabu Moger 	long long r;
658520e2789SBabu Moger 
659520e2789SBabu Moger 	asm volatile("rdrand %0\n\t"
660520e2789SBabu Moger 		     "jc 1f\n\t"
661520e2789SBabu Moger 		     "mov $0, %0\n\t"
662520e2789SBabu Moger 		     "1:\n\t" : "=r" (r));
663520e2789SBabu Moger 	return r;
664520e2789SBabu Moger }
665520e2789SBabu Moger 
6667db17e21SThomas Huth static inline unsigned long long rdtsc(void)
6670d7251beSJason Wang {
6680d7251beSJason Wang 	long long r;
6690d7251beSJason Wang 
6700d7251beSJason Wang #ifdef __x86_64__
6710d7251beSJason Wang 	unsigned a, d;
6720d7251beSJason Wang 
6730d7251beSJason Wang 	asm volatile ("rdtsc" : "=a"(a), "=d"(d));
6740d7251beSJason Wang 	r = a | ((long long)d << 32);
6750d7251beSJason Wang #else
6760d7251beSJason Wang 	asm volatile ("rdtsc" : "=A"(r));
6770d7251beSJason Wang #endif
6780d7251beSJason Wang 	return r;
6790d7251beSJason Wang }
6800d7251beSJason Wang 
681b49a1a6dSJim Mattson /*
682b49a1a6dSJim Mattson  * Per the advice in the SDM, volume 2, the sequence "mfence; lfence"
683b49a1a6dSJim Mattson  * executed immediately before rdtsc ensures that rdtsc will be
684b49a1a6dSJim Mattson  * executed only after all previous instructions have executed and all
685b49a1a6dSJim Mattson  * previous loads and stores are globally visible. In addition, the
686b49a1a6dSJim Mattson  * lfence immediately after rdtsc ensures that rdtsc will be executed
687b49a1a6dSJim Mattson  * prior to the execution of any subsequent instruction.
688b49a1a6dSJim Mattson  */
689b49a1a6dSJim Mattson static inline unsigned long long fenced_rdtsc(void)
690b49a1a6dSJim Mattson {
691b49a1a6dSJim Mattson 	unsigned long long tsc;
692b49a1a6dSJim Mattson 
693b49a1a6dSJim Mattson #ifdef __x86_64__
694b49a1a6dSJim Mattson 	unsigned int eax, edx;
695b49a1a6dSJim Mattson 
696b49a1a6dSJim Mattson 	asm volatile ("mfence; lfence; rdtsc; lfence" : "=a"(eax), "=d"(edx));
697b49a1a6dSJim Mattson 	tsc = eax | ((unsigned long long)edx << 32);
698b49a1a6dSJim Mattson #else
699b49a1a6dSJim Mattson 	asm volatile ("mfence; lfence; rdtsc; lfence" : "=A"(tsc));
700b49a1a6dSJim Mattson #endif
701b49a1a6dSJim Mattson 	return tsc;
702b49a1a6dSJim Mattson }
703b49a1a6dSJim Mattson 
704867f820dSPaolo Bonzini static inline unsigned long long rdtscp(u32 *aux)
705867f820dSPaolo Bonzini {
706867f820dSPaolo Bonzini 	long long r;
707867f820dSPaolo Bonzini 
708867f820dSPaolo Bonzini #ifdef __x86_64__
709867f820dSPaolo Bonzini 	unsigned a, d;
710867f820dSPaolo Bonzini 
711867f820dSPaolo Bonzini 	asm volatile ("rdtscp" : "=a"(a), "=d"(d), "=c"(*aux));
712867f820dSPaolo Bonzini 	r = a | ((long long)d << 32);
713867f820dSPaolo Bonzini #else
714867f820dSPaolo Bonzini 	asm volatile ("rdtscp" : "=A"(r), "=c"(*aux));
715867f820dSPaolo Bonzini #endif
716867f820dSPaolo Bonzini 	return r;
717867f820dSPaolo Bonzini }
718867f820dSPaolo Bonzini 
7190d7251beSJason Wang static inline void wrtsc(u64 tsc)
7200d7251beSJason Wang {
721c47292f4SJim Mattson 	wrmsr(MSR_IA32_TSC, tsc);
7220d7251beSJason Wang }
7230d7251beSJason Wang 
724ae0a920bSGleb Natapov static inline void irq_disable(void)
725ae0a920bSGleb Natapov {
726ae0a920bSGleb Natapov 	asm volatile("cli");
727ae0a920bSGleb Natapov }
728ae0a920bSGleb Natapov 
729132c700dSPeter Feiner /* Note that irq_enable() does not ensure an interrupt shadow due
730132c700dSPeter Feiner  * to the vagaries of compiler optimizations.  If you need the
731132c700dSPeter Feiner  * shadow, use a single asm with "sti" and the instruction after it.
732132c700dSPeter Feiner  */
733ae0a920bSGleb Natapov static inline void irq_enable(void)
734ae0a920bSGleb Natapov {
735ae0a920bSGleb Natapov 	asm volatile("sti");
736ae0a920bSGleb Natapov }
737ae0a920bSGleb Natapov 
738fa6318d1SPaolo Bonzini static inline void invlpg(volatile void *va)
7394029c34bSGleb Natapov {
7404029c34bSGleb Natapov 	asm volatile("invlpg (%0)" ::"r" (va) : "memory");
7414029c34bSGleb Natapov }
742334cd2bfSGleb Natapov 
743334cd2bfSGleb Natapov static inline void safe_halt(void)
744334cd2bfSGleb Natapov {
745334cd2bfSGleb Natapov 	asm volatile("sti; hlt");
746334cd2bfSGleb Natapov }
7479d7eaa29SArthur Chunqi Li 
748e94079c5SPaolo Bonzini static inline u32 read_pkru(void)
749e94079c5SPaolo Bonzini {
750e94079c5SPaolo Bonzini 	unsigned int eax, edx;
751e94079c5SPaolo Bonzini 	unsigned int ecx = 0;
752e94079c5SPaolo Bonzini 	unsigned int pkru;
753e94079c5SPaolo Bonzini 
754e94079c5SPaolo Bonzini 	asm volatile(".byte 0x0f,0x01,0xee\n\t"
755e94079c5SPaolo Bonzini 		     : "=a" (eax), "=d" (edx)
756e94079c5SPaolo Bonzini 		     : "c" (ecx));
757e94079c5SPaolo Bonzini 	pkru = eax;
758e94079c5SPaolo Bonzini 	return pkru;
759e94079c5SPaolo Bonzini }
760e94079c5SPaolo Bonzini 
761e94079c5SPaolo Bonzini static inline void write_pkru(u32 pkru)
762e94079c5SPaolo Bonzini {
763e94079c5SPaolo Bonzini 	unsigned int eax = pkru;
764e94079c5SPaolo Bonzini 	unsigned int ecx = 0;
765e94079c5SPaolo Bonzini 	unsigned int edx = 0;
766e94079c5SPaolo Bonzini 
767e94079c5SPaolo Bonzini 	asm volatile(".byte 0x0f,0x01,0xef\n\t"
768e94079c5SPaolo Bonzini 		     : : "a" (eax), "c" (ecx), "d" (edx));
769e94079c5SPaolo Bonzini }
770e94079c5SPaolo Bonzini 
771aedfd771SJim Mattson static inline bool is_canonical(u64 addr)
772aedfd771SJim Mattson {
773f4a8b68cSLara Lazier 	int va_width = (raw_cpuid(0x80000008, 0).a & 0xff00) >> 8;
774f4a8b68cSLara Lazier 	int shift_amt = 64 - va_width;
775f4a8b68cSLara Lazier 
776f4a8b68cSLara Lazier 	return (s64)(addr << shift_amt) >> shift_amt == addr;
777aedfd771SJim Mattson }
778aedfd771SJim Mattson 
779e60c87fdSLiran Alon static inline void clear_bit(int bit, u8 *addr)
780e60c87fdSLiran Alon {
781e60c87fdSLiran Alon 	__asm__ __volatile__("btr %1, %0"
782e60c87fdSLiran Alon 			     : "+m" (*addr) : "Ir" (bit) : "cc", "memory");
783e60c87fdSLiran Alon }
784e60c87fdSLiran Alon 
785e60c87fdSLiran Alon static inline void set_bit(int bit, u8 *addr)
786e60c87fdSLiran Alon {
787e60c87fdSLiran Alon 	__asm__ __volatile__("bts %1, %0"
788e60c87fdSLiran Alon 			     : "+m" (*addr) : "Ir" (bit) : "cc", "memory");
789e60c87fdSLiran Alon }
790e60c87fdSLiran Alon 
7915868743aSMarc Orr static inline void flush_tlb(void)
7925868743aSMarc Orr {
7935868743aSMarc Orr 	ulong cr4;
7945868743aSMarc Orr 
7955868743aSMarc Orr 	cr4 = read_cr4();
7965868743aSMarc Orr 	write_cr4(cr4 ^ X86_CR4_PGE);
7975868743aSMarc Orr 	write_cr4(cr4);
7985868743aSMarc Orr }
7995868743aSMarc Orr 
800e39bee8fSSean Christopherson static inline void generate_non_canonical_gp(void)
801e39bee8fSSean Christopherson {
802e39bee8fSSean Christopherson 	*(volatile u64 *)NONCANONICAL = 0;
803e39bee8fSSean Christopherson }
804e39bee8fSSean Christopherson 
805e39bee8fSSean Christopherson static inline void generate_ud(void)
806e39bee8fSSean Christopherson {
807e39bee8fSSean Christopherson 	asm volatile ("ud2");
808e39bee8fSSean Christopherson }
809e39bee8fSSean Christopherson 
810e39bee8fSSean Christopherson static inline void generate_de(void)
811e39bee8fSSean Christopherson {
812e39bee8fSSean Christopherson 	asm volatile (
813e39bee8fSSean Christopherson 		"xor %%eax, %%eax\n\t"
814e39bee8fSSean Christopherson 		"xor %%ebx, %%ebx\n\t"
815e39bee8fSSean Christopherson 		"xor %%edx, %%edx\n\t"
816e39bee8fSSean Christopherson 		"idiv %%ebx\n\t"
817e39bee8fSSean Christopherson 		::: "eax", "ebx", "edx");
818e39bee8fSSean Christopherson }
819e39bee8fSSean Christopherson 
820e39bee8fSSean Christopherson static inline void generate_bp(void)
821e39bee8fSSean Christopherson {
822e39bee8fSSean Christopherson 	asm volatile ("int3");
823e39bee8fSSean Christopherson }
824e39bee8fSSean Christopherson 
825e39bee8fSSean Christopherson static inline void generate_single_step_db(void)
826e39bee8fSSean Christopherson {
827e39bee8fSSean Christopherson 	write_rflags(read_rflags() | X86_EFLAGS_TF);
828e39bee8fSSean Christopherson 	asm volatile("nop");
829e39bee8fSSean Christopherson }
830e39bee8fSSean Christopherson 
831e39bee8fSSean Christopherson static inline uint64_t generate_usermode_ac(void)
832e39bee8fSSean Christopherson {
833e39bee8fSSean Christopherson 	/*
834e39bee8fSSean Christopherson 	 * Trigger an #AC by writing 8 bytes to a 4-byte aligned address.
835e39bee8fSSean Christopherson 	 * Disclaimer: It is assumed that the stack pointer is aligned
836e39bee8fSSean Christopherson 	 * on a 16-byte boundary as x86_64 stacks should be.
837e39bee8fSSean Christopherson 	 */
838e39bee8fSSean Christopherson 	asm volatile("movq $0, -0x4(%rsp)");
839e39bee8fSSean Christopherson 
840e39bee8fSSean Christopherson 	return 0;
841e39bee8fSSean Christopherson }
842e39bee8fSSean Christopherson 
8435faf5f60SSean Christopherson /*
8445faf5f60SSean Christopherson  * Switch from 64-bit to 32-bit mode and generate #OF via INTO.  Note, if RIP
8455faf5f60SSean Christopherson  * or RSP holds a 64-bit value, this helper will NOT generate #OF.
8465faf5f60SSean Christopherson  */
8475faf5f60SSean Christopherson static inline void generate_of(void)
8485faf5f60SSean Christopherson {
8495faf5f60SSean Christopherson 	struct far_pointer32 fp = {
8505faf5f60SSean Christopherson 		.offset = (uintptr_t)&&into,
8515faf5f60SSean Christopherson 		.selector = KERNEL_CS32,
8525faf5f60SSean Christopherson 	};
8535faf5f60SSean Christopherson 	uintptr_t rsp;
8545faf5f60SSean Christopherson 
8555faf5f60SSean Christopherson 	asm volatile ("mov %%rsp, %0" : "=r"(rsp));
8565faf5f60SSean Christopherson 
8575faf5f60SSean Christopherson 	if (fp.offset != (uintptr_t)&&into) {
8585faf5f60SSean Christopherson 		printf("Code address too high.\n");
8595faf5f60SSean Christopherson 		return;
8605faf5f60SSean Christopherson 	}
8615faf5f60SSean Christopherson 	if ((u32)rsp != rsp) {
8625faf5f60SSean Christopherson 		printf("Stack address too high.\n");
8635faf5f60SSean Christopherson 		return;
8645faf5f60SSean Christopherson 	}
8655faf5f60SSean Christopherson 
8665faf5f60SSean Christopherson 	asm goto ("lcall *%0" : : "m" (fp) : "rax" : into);
8675faf5f60SSean Christopherson 	return;
8685faf5f60SSean Christopherson into:
8695faf5f60SSean Christopherson 	asm volatile (".code32;"
8705faf5f60SSean Christopherson 		      "movl $0x7fffffff, %eax;"
8715faf5f60SSean Christopherson 		      "addl %eax, %eax;"
8725faf5f60SSean Christopherson 		      "into;"
8735faf5f60SSean Christopherson 		      "lret;"
8745faf5f60SSean Christopherson 		      ".code64");
8755faf5f60SSean Christopherson 	__builtin_unreachable();
8765faf5f60SSean Christopherson }
8775faf5f60SSean Christopherson 
878694e59baSManali Shukla static inline void fnop(void)
879694e59baSManali Shukla {
880694e59baSManali Shukla 	asm volatile("fnop");
881694e59baSManali Shukla }
882694e59baSManali Shukla 
883694e59baSManali Shukla /* If CR0.TS is set in L2, #NM is generated. */
884694e59baSManali Shukla static inline void generate_cr0_ts_nm(void)
885694e59baSManali Shukla {
886694e59baSManali Shukla 	write_cr0((read_cr0() & ~X86_CR0_EM) | X86_CR0_TS);
887694e59baSManali Shukla 	fnop();
888694e59baSManali Shukla }
889694e59baSManali Shukla 
890694e59baSManali Shukla /* If CR0.TS is cleared and CR0.EM is set, #NM is generated. */
891694e59baSManali Shukla static inline void generate_cr0_em_nm(void)
892694e59baSManali Shukla {
893694e59baSManali Shukla 	write_cr0((read_cr0() & ~X86_CR0_TS) | X86_CR0_EM);
894694e59baSManali Shukla 	fnop();
895694e59baSManali Shukla }
896694e59baSManali Shukla 
8977d36db35SAvi Kivity #endif
898