xref: /kvm-unit-tests/x86/msr.c (revision f3f338619e4938c2509f5c691adc1f331b07c203)
17d36db35SAvi Kivity /* msr tests */
27d36db35SAvi Kivity 
37d36db35SAvi Kivity #include "libcflat.h"
47c47d0d4SSean Christopherson #include "apic.h"
5850479e3SJason Wang #include "processor.h"
6d1bdd07cSAvi Kivity #include "msr.h"
75b4855b3SDaniele Ahmed #include <stdlib.h>
85b4855b3SDaniele Ahmed 
96b31aa76SNico Boehr /*
105b4855b3SDaniele Ahmed  * This test allows two modes:
115b4855b3SDaniele Ahmed  * 1. Default: the `msr_info' array contains the default test configurations
125b4855b3SDaniele Ahmed  * 2. Custom: by providing command line arguments it is possible to test any MSR and value
135b4855b3SDaniele Ahmed  *	Parameters order:
145b4855b3SDaniele Ahmed  *		1. msr index as a base 16 number
155b4855b3SDaniele Ahmed  *		2. value as a base 16 number
165b4855b3SDaniele Ahmed  */
177d36db35SAvi Kivity 
187d36db35SAvi Kivity struct msr_info {
197d36db35SAvi Kivity 	int index;
20142ff635SSean Christopherson 	bool is_64bit_only;
21797d79a2SThomas Huth 	const char *name;
227d36db35SAvi Kivity 	unsigned long long value;
23bab19cadSPaolo Bonzini 	unsigned long long keep;
247d36db35SAvi Kivity };
257d36db35SAvi Kivity 
267d36db35SAvi Kivity 
277d36db35SAvi Kivity #define addr_64 0x0000123456789abcULL
288feb8cfbSSean Christopherson #define addr_ul (unsigned long)addr_64
297d36db35SAvi Kivity 
30ca85dda2SSean Christopherson #define MSR_TEST(msr, val, ro)	\
31ca85dda2SSean Christopherson 	{ .index = msr, .name = #msr, .value = val, .is_64bit_only = false, .keep = ro }
32ca85dda2SSean Christopherson #define MSR_TEST_ONLY64(msr, val, ro)	\
33ca85dda2SSean Christopherson 	{ .index = msr, .name = #msr, .value = val, .is_64bit_only = true, .keep = ro }
3464662079SSean Christopherson 
357d36db35SAvi Kivity struct msr_info msr_info[] =
367d36db35SAvi Kivity {
37ca85dda2SSean Christopherson 	MSR_TEST(MSR_IA32_SYSENTER_CS, 0x1234, 0),
38ca85dda2SSean Christopherson 	MSR_TEST(MSR_IA32_SYSENTER_ESP, addr_ul, 0),
39ca85dda2SSean Christopherson 	MSR_TEST(MSR_IA32_SYSENTER_EIP, addr_ul, 0),
407d36db35SAvi Kivity 	// reserved: 1:2, 4:6, 8:10, 13:15, 17, 19:21, 24:33, 35:63
41bab19cadSPaolo Bonzini 	// read-only: 7, 11, 12
42ca85dda2SSean Christopherson 	MSR_TEST(MSR_IA32_MISC_ENABLE, 0x400c50809, 0x1880),
43ca85dda2SSean Christopherson 	MSR_TEST(MSR_IA32_CR_PAT, 0x07070707, 0),
44ca85dda2SSean Christopherson 	MSR_TEST_ONLY64(MSR_FS_BASE, addr_64, 0),
45ca85dda2SSean Christopherson 	MSR_TEST_ONLY64(MSR_GS_BASE, addr_64, 0),
46ca85dda2SSean Christopherson 	MSR_TEST_ONLY64(MSR_KERNEL_GS_BASE, addr_64, 0),
47ca85dda2SSean Christopherson 	MSR_TEST(MSR_EFER, EFER_SCE, 0),
48ca85dda2SSean Christopherson 	MSR_TEST_ONLY64(MSR_LSTAR, addr_64, 0),
49ca85dda2SSean Christopherson 	MSR_TEST_ONLY64(MSR_CSTAR, addr_64, 0),
50ca85dda2SSean Christopherson 	MSR_TEST_ONLY64(MSR_SYSCALL_MASK, 0xffffffff, 0),
517d36db35SAvi Kivity //	MSR_IA32_DEBUGCTLMSR needs svm feature LBRV
527d36db35SAvi Kivity //	MSR_VM_HSAVE_PA only AMD host
537d36db35SAvi Kivity };
547d36db35SAvi Kivity 
__test_msr_rw(u32 msr,const char * name,unsigned long long val,unsigned long long keep_mask)55039d9207SSean Christopherson static void __test_msr_rw(u32 msr, const char *name, unsigned long long val,
56fb0d9894SSean Christopherson 			  unsigned long long keep_mask)
577d36db35SAvi Kivity {
58a73d6ae4SSean Christopherson 	unsigned long long r, orig;
5950273266SSean Christopherson 
60fb0d9894SSean Christopherson 	orig = rdmsr(msr);
61dcae8d5fSSean Christopherson 	/*
62dcae8d5fSSean Christopherson 	 * Special case EFER since clearing LME/LMA is not allowed in 64-bit mode,
63dcae8d5fSSean Christopherson 	 * and conversely setting those bits on 32-bit CPUs is not allowed.  Treat
64dcae8d5fSSean Christopherson 	 * the desired value as extra bits to set.
65dcae8d5fSSean Christopherson 	 */
66fb0d9894SSean Christopherson 	if (msr == MSR_EFER)
67dcae8d5fSSean Christopherson 		val |= orig;
68bab19cadSPaolo Bonzini 	else
69fb0d9894SSean Christopherson 		val = (val & ~keep_mask) | (orig & keep_mask);
70fb0d9894SSean Christopherson 
71fb0d9894SSean Christopherson 	wrmsr(msr, val);
72fb0d9894SSean Christopherson 	r = rdmsr(msr);
73fb0d9894SSean Christopherson 	wrmsr(msr, orig);
74fb0d9894SSean Christopherson 
759295327cSSean Christopherson 	if (r != val) {
76d26193a0SRoman Bolshakov 		printf("testing %s: output = %#" PRIx32 ":%#" PRIx32
77fb0d9894SSean Christopherson 		       " expected = %#" PRIx32 ":%#" PRIx32 "\n", name,
789295327cSSean Christopherson 		       (u32)(r >> 32), (u32)r, (u32)(val >> 32), (u32)val);
797d36db35SAvi Kivity 	}
80fb0d9894SSean Christopherson 	report(val == r, "%s", name);
817d36db35SAvi Kivity }
827d36db35SAvi Kivity 
test_msr_rw(u32 msr,const char * name,unsigned long long val)83039d9207SSean Christopherson static void test_msr_rw(u32 msr, const char *name, unsigned long long val)
84039d9207SSean Christopherson {
85039d9207SSean Christopherson 	__test_msr_rw(msr, name, val, 0);
86039d9207SSean Christopherson }
87039d9207SSean Christopherson 
test_wrmsr(u32 msr,const char * name,unsigned long long val)88fbd98087SSean Christopherson static void test_wrmsr(u32 msr, const char *name, unsigned long long val)
89fbd98087SSean Christopherson {
90fbd98087SSean Christopherson 	unsigned char vector = wrmsr_safe(msr, val);
91fbd98087SSean Christopherson 
92fbd98087SSean Christopherson 	report(!vector,
93784dd85dSJack Wang 	       "Expected success on WRMSR(%s, 0x%llx), got vector %d",
94fbd98087SSean Christopherson 	       name, val, vector);
95fbd98087SSean Christopherson }
96fbd98087SSean Christopherson 
test_wrmsr_fault(u32 msr,const char * name,unsigned long long val)97fb0d9894SSean Christopherson static void test_wrmsr_fault(u32 msr, const char *name, unsigned long long val)
98142ff635SSean Christopherson {
994143fbfdSSean Christopherson 	unsigned char vector = wrmsr_safe(msr, val);
100142ff635SSean Christopherson 
101142ff635SSean Christopherson 	report(vector == GP_VECTOR,
102784dd85dSJack Wang 	       "Expected #GP on WRMSR(%s, 0x%llx), got vector %d",
103fb0d9894SSean Christopherson 	       name, val, vector);
104142ff635SSean Christopherson }
105142ff635SSean Christopherson 
test_rdmsr_fault(u32 msr,const char * name)106fb0d9894SSean Christopherson static void test_rdmsr_fault(u32 msr, const char *name)
107142ff635SSean Christopherson {
1080a4d8626SSean Christopherson 	uint64_t ignored;
1090a4d8626SSean Christopherson 	unsigned char vector = rdmsr_safe(msr, &ignored);
110142ff635SSean Christopherson 
111142ff635SSean Christopherson 	report(vector == GP_VECTOR,
112784dd85dSJack Wang 	       "Expected #GP on RDMSR(%s), got vector %d", name, vector);
113142ff635SSean Christopherson }
114142ff635SSean Christopherson 
test_wrmsr_fep_fault(u32 msr,const char * name,unsigned long long val)11513a12056SMingwei Zhang static void test_wrmsr_fep_fault(u32 msr, const char *name,
11613a12056SMingwei Zhang 				 unsigned long long val)
11713a12056SMingwei Zhang {
11813a12056SMingwei Zhang 	unsigned char vector = wrmsr_fep_safe(msr, val);
11913a12056SMingwei Zhang 
12013a12056SMingwei Zhang 	report(vector == GP_VECTOR,
12113a12056SMingwei Zhang 	       "Expected #GP on emulated WRSMR(%s, 0x%llx), got vector %d",
12213a12056SMingwei Zhang 	       name, val, vector);
12313a12056SMingwei Zhang }
12413a12056SMingwei Zhang 
test_msr(struct msr_info * msr,bool is_64bit_host)1259e8ecb28SDaniele Ahmed static void test_msr(struct msr_info *msr, bool is_64bit_host)
1269e8ecb28SDaniele Ahmed {
1279e8ecb28SDaniele Ahmed 	if (is_64bit_host || !msr->is_64bit_only) {
128039d9207SSean Christopherson 		__test_msr_rw(msr->index, msr->name, msr->value, msr->keep);
1299e8ecb28SDaniele Ahmed 
1309e8ecb28SDaniele Ahmed 		/*
1319e8ecb28SDaniele Ahmed 		 * The 64-bit only MSRs that take an address always perform
1329e8ecb28SDaniele Ahmed 		 * canonical checks on both Intel and AMD.
1339e8ecb28SDaniele Ahmed 		 */
1349e8ecb28SDaniele Ahmed 		if (msr->is_64bit_only &&
1359e8ecb28SDaniele Ahmed 		    msr->value == addr_64)
136fb0d9894SSean Christopherson 			test_wrmsr_fault(msr->index, msr->name, NONCANONICAL);
1379e8ecb28SDaniele Ahmed 	} else {
138fb0d9894SSean Christopherson 		test_wrmsr_fault(msr->index, msr->name, msr->value);
139fb0d9894SSean Christopherson 		test_rdmsr_fault(msr->index, msr->name);
1409e8ecb28SDaniele Ahmed 	}
1419e8ecb28SDaniele Ahmed }
1429e8ecb28SDaniele Ahmed 
test_custom_msr(int ac,char ** av)14365096195SSean Christopherson static void test_custom_msr(int ac, char **av)
1447d36db35SAvi Kivity {
145142ff635SSean Christopherson 	bool is_64bit_host = this_cpu_has(X86_FEATURE_LM);
146039d9207SSean Christopherson 	char msr_name[32];
1475b4855b3SDaniele Ahmed 	int index = strtoul(av[1], NULL, 0x10);
1485b4855b3SDaniele Ahmed 	snprintf(msr_name, sizeof(msr_name), "MSR:0x%x", index);
1495b4855b3SDaniele Ahmed 
1505b4855b3SDaniele Ahmed 	struct msr_info msr = {
1515b4855b3SDaniele Ahmed 		.index = index,
1525b4855b3SDaniele Ahmed 		.name = msr_name,
1535b4855b3SDaniele Ahmed 		.value = strtoull(av[2], NULL, 0x10)
1545b4855b3SDaniele Ahmed 	};
1555b4855b3SDaniele Ahmed 	test_msr(&msr, is_64bit_host);
15665096195SSean Christopherson }
15765096195SSean Christopherson 
test_misc_msrs(void)15865096195SSean Christopherson static void test_misc_msrs(void)
15965096195SSean Christopherson {
16065096195SSean Christopherson 	bool is_64bit_host = this_cpu_has(X86_FEATURE_LM);
16165096195SSean Christopherson 	int i;
16265096195SSean Christopherson 
163039d9207SSean Christopherson 	for (i = 0 ; i < ARRAY_SIZE(msr_info); i++)
1649e8ecb28SDaniele Ahmed 		test_msr(&msr_info[i], is_64bit_host);
16565096195SSean Christopherson }
16665096195SSean Christopherson 
test_mce_msrs(void)16765096195SSean Christopherson static void test_mce_msrs(void)
16865096195SSean Christopherson {
16965096195SSean Christopherson 	bool is_64bit_host = this_cpu_has(X86_FEATURE_LM);
17065096195SSean Christopherson 	unsigned int nr_mce_banks;
17165096195SSean Christopherson 	char msr_name[32];
17265096195SSean Christopherson 	int i;
173039d9207SSean Christopherson 
174039d9207SSean Christopherson 	nr_mce_banks = rdmsr(MSR_IA32_MCG_CAP) & 0xff;
175039d9207SSean Christopherson 	for (i = 0; i < nr_mce_banks; i++) {
176039d9207SSean Christopherson 		snprintf(msr_name, sizeof(msr_name), "MSR_IA32_MC%u_CTL", i);
177039d9207SSean Christopherson 		test_msr_rw(MSR_IA32_MCx_CTL(i), msr_name, 0);
178039d9207SSean Christopherson 		test_msr_rw(MSR_IA32_MCx_CTL(i), msr_name, -1ull);
179039d9207SSean Christopherson 		test_wrmsr_fault(MSR_IA32_MCx_CTL(i), msr_name, NONCANONICAL);
180039d9207SSean Christopherson 
181039d9207SSean Christopherson 		snprintf(msr_name, sizeof(msr_name), "MSR_IA32_MC%u_STATUS", i);
182039d9207SSean Christopherson 		test_msr_rw(MSR_IA32_MCx_STATUS(i), msr_name, 0);
183039d9207SSean Christopherson 		/*
18465096195SSean Christopherson 		 * STATUS MSRs can only be written with '0' (to clear the MSR),
18565096195SSean Christopherson 		 * except on AMD-based systems with bit 18 set in MSR_K7_HWCR.
18665096195SSean Christopherson 		 * That bit is not architectural and should not be set by
18765096195SSean Christopherson 		 * default by KVM or by the VMM (though this might fail if run
18865096195SSean Christopherson 		 * on bare metal).
189039d9207SSean Christopherson 		 */
190039d9207SSean Christopherson 		test_wrmsr_fault(MSR_IA32_MCx_STATUS(i), msr_name, 1);
191039d9207SSean Christopherson 
192039d9207SSean Christopherson 		snprintf(msr_name, sizeof(msr_name), "MSR_IA32_MC%u_ADDR", i);
193039d9207SSean Christopherson 		test_msr_rw(MSR_IA32_MCx_ADDR(i), msr_name, 0);
194039d9207SSean Christopherson 		test_msr_rw(MSR_IA32_MCx_ADDR(i), msr_name, -1ull);
195039d9207SSean Christopherson 		/*
19665096195SSean Christopherson 		 * The ADDR is a physical address, and all bits are writable on
19765096195SSean Christopherson 		 * 64-bit hosts.  Don't test the negative case, as KVM doesn't
19865096195SSean Christopherson 		 * enforce checks on bits 63:36 for 32-bit hosts.  The behavior
19965096195SSean Christopherson 		 * depends on the underlying hardware, e.g. a 32-bit guest on a
20065096195SSean Christopherson 		 * 64-bit host may observe 64-bit values in the ADDR MSRs.
201039d9207SSean Christopherson 		 */
202039d9207SSean Christopherson 		if (is_64bit_host)
203039d9207SSean Christopherson 			test_msr_rw(MSR_IA32_MCx_ADDR(i), msr_name, NONCANONICAL);
204039d9207SSean Christopherson 
205039d9207SSean Christopherson 		snprintf(msr_name, sizeof(msr_name), "MSR_IA32_MC%u_MISC", i);
206039d9207SSean Christopherson 		test_msr_rw(MSR_IA32_MCx_MISC(i), msr_name, 0);
207039d9207SSean Christopherson 		test_msr_rw(MSR_IA32_MCx_MISC(i), msr_name, -1ull);
208039d9207SSean Christopherson 		test_msr_rw(MSR_IA32_MCx_MISC(i), msr_name, NONCANONICAL);
209039d9207SSean Christopherson 	}
210039d9207SSean Christopherson 
211039d9207SSean Christopherson 	/*
21265096195SSean Christopherson 	 * The theoretical maximum number of MCE banks is 32 (on Intel CPUs,
21365096195SSean Christopherson 	 * without jumping to a new base address), as the last unclaimed MSR is
21465096195SSean Christopherson 	 * 0x479; 0x480 begins the VMX MSRs.  Verify accesses to theoretically
21565096195SSean Christopherson 	 * legal, unsupported MSRs fault.
216039d9207SSean Christopherson 	 */
217039d9207SSean Christopherson 	for (i = nr_mce_banks; i < 32; i++) {
218039d9207SSean Christopherson 		snprintf(msr_name, sizeof(msr_name), "MSR_IA32_MC%u_CTL", i);
219039d9207SSean Christopherson 		test_rdmsr_fault(MSR_IA32_MCx_CTL(i), msr_name);
220039d9207SSean Christopherson 		test_wrmsr_fault(MSR_IA32_MCx_CTL(i), msr_name, 0);
221039d9207SSean Christopherson 
222039d9207SSean Christopherson 		snprintf(msr_name, sizeof(msr_name), "MSR_IA32_MC%u_STATUS", i);
223039d9207SSean Christopherson 		test_rdmsr_fault(MSR_IA32_MCx_STATUS(i), msr_name);
224039d9207SSean Christopherson 		test_wrmsr_fault(MSR_IA32_MCx_STATUS(i), msr_name, 0);
225039d9207SSean Christopherson 
226039d9207SSean Christopherson 		snprintf(msr_name, sizeof(msr_name), "MSR_IA32_MC%u_ADDR", i);
227039d9207SSean Christopherson 		test_rdmsr_fault(MSR_IA32_MCx_ADDR(i), msr_name);
228039d9207SSean Christopherson 		test_wrmsr_fault(MSR_IA32_MCx_ADDR(i), msr_name, 0);
229039d9207SSean Christopherson 
230039d9207SSean Christopherson 		snprintf(msr_name, sizeof(msr_name), "MSR_IA32_MC%u_MISC", i);
231039d9207SSean Christopherson 		test_rdmsr_fault(MSR_IA32_MCx_MISC(i), msr_name);
232039d9207SSean Christopherson 		test_wrmsr_fault(MSR_IA32_MCx_MISC(i), msr_name, 0);
233142ff635SSean Christopherson 	}
2345b4855b3SDaniele Ahmed }
2357d36db35SAvi Kivity 
__test_x2apic_msrs(bool x2apic_enabled)2367c47d0d4SSean Christopherson static void __test_x2apic_msrs(bool x2apic_enabled)
2377c47d0d4SSean Christopherson {
2387c47d0d4SSean Christopherson 	enum x2apic_reg_semantics semantics;
2397c47d0d4SSean Christopherson 	unsigned int index, i;
2407c47d0d4SSean Christopherson 	char msr_name[32];
2417c47d0d4SSean Christopherson 
2427c47d0d4SSean Christopherson 	for (i = 0; i < 0x1000; i += 0x10) {
2437c47d0d4SSean Christopherson 		index = x2apic_msr(i);
2447c47d0d4SSean Christopherson 		snprintf(msr_name, sizeof(msr_name), "x2APIC MSR 0x%x", index);
2457c47d0d4SSean Christopherson 
2467c47d0d4SSean Christopherson 		if (x2apic_enabled)
2477c47d0d4SSean Christopherson 			semantics = get_x2apic_reg_semantics(i);
2487c47d0d4SSean Christopherson 		else
2497c47d0d4SSean Christopherson 			semantics = X2APIC_INVALID;
2507c47d0d4SSean Christopherson 
2517c47d0d4SSean Christopherson 		if (!(semantics & X2APIC_WRITABLE))
2527c47d0d4SSean Christopherson 			test_wrmsr_fault(index, msr_name, 0);
2537c47d0d4SSean Christopherson 
2547c47d0d4SSean Christopherson 		if (!(semantics & X2APIC_READABLE))
2557c47d0d4SSean Christopherson 			test_rdmsr_fault(index, msr_name);
2567c47d0d4SSean Christopherson 
2577c47d0d4SSean Christopherson 		/*
2587c47d0d4SSean Christopherson 		 * Except for ICR, the only 64-bit x2APIC register, bits 64:32
2597c47d0d4SSean Christopherson 		 * are reserved.  ICR is testable if x2APIC is disabled.
2607c47d0d4SSean Christopherson 		 */
2617c47d0d4SSean Christopherson 		if (!x2apic_enabled || i != APIC_ICR)
2627c47d0d4SSean Christopherson 			test_wrmsr_fault(index, msr_name, -1ull);
2637c47d0d4SSean Christopherson 
2647c47d0d4SSean Christopherson 		/* Bits 31:8 of self-IPI are reserved. */
2657c47d0d4SSean Christopherson 		if (i == APIC_SELF_IPI) {
2667c47d0d4SSean Christopherson 			test_wrmsr_fault(index, "x2APIC Self-IPI", 0x100);
2677c47d0d4SSean Christopherson 			test_wrmsr_fault(index, "x2APIC Self-IPI", 0xff00);
2687c47d0d4SSean Christopherson 			test_wrmsr_fault(index, "x2APIC Self-IPI", 0xff000000ull);
2697c47d0d4SSean Christopherson 		}
2707c47d0d4SSean Christopherson 
2717c47d0d4SSean Christopherson 		if (semantics == X2APIC_RW)
2727c47d0d4SSean Christopherson 			__test_msr_rw(index, msr_name, 0, -1ull);
2737c47d0d4SSean Christopherson 		else if (semantics == X2APIC_WO)
2747c47d0d4SSean Christopherson 			wrmsr(index, 0);
2757c47d0d4SSean Christopherson 		else if (semantics == X2APIC_RO)
2767c47d0d4SSean Christopherson 			report(!(rdmsr(index) >> 32),
2777c47d0d4SSean Christopherson 			       "Expected bits 63:32 == 0 for '%s'", msr_name);
2787c47d0d4SSean Christopherson 	}
2797c47d0d4SSean Christopherson }
2807c47d0d4SSean Christopherson 
test_x2apic_msrs(void)2817c47d0d4SSean Christopherson static void test_x2apic_msrs(void)
2827c47d0d4SSean Christopherson {
2837c47d0d4SSean Christopherson 	reset_apic();
2847c47d0d4SSean Christopherson 
2857c47d0d4SSean Christopherson 	__test_x2apic_msrs(false);
2867c47d0d4SSean Christopherson 
2877c47d0d4SSean Christopherson 	if (!enable_x2apic())
2887c47d0d4SSean Christopherson 		return;
2897c47d0d4SSean Christopherson 
2907c47d0d4SSean Christopherson 	__test_x2apic_msrs(true);
2917c47d0d4SSean Christopherson }
2927c47d0d4SSean Christopherson 
test_mitigation_msrs(void)293*70445405SSean Christopherson static void test_mitigation_msrs(void)
294fbd98087SSean Christopherson {
295*70445405SSean Christopherson 	u64 spec_ctrl_bits = 0, val;
296fbd98087SSean Christopherson 	int i;
297fbd98087SSean Christopherson 
298*70445405SSean Christopherson 	if (this_cpu_has(X86_FEATURE_SPEC_CTRL) || this_cpu_has(X86_FEATURE_AMD_IBRS))
299*70445405SSean Christopherson 		spec_ctrl_bits |= SPEC_CTRL_IBRS;
300*70445405SSean Christopherson 
301*70445405SSean Christopherson 	if (this_cpu_has(X86_FEATURE_STIBP) || this_cpu_has(X86_FEATURE_AMD_STIBP))
302*70445405SSean Christopherson 		spec_ctrl_bits |= SPEC_CTRL_STIBP;
303*70445405SSean Christopherson 
304*70445405SSean Christopherson 	if (this_cpu_has(X86_FEATURE_SSBD) || this_cpu_has(X86_FEATURE_AMD_SSBD))
305*70445405SSean Christopherson 		spec_ctrl_bits |= SPEC_CTRL_SSBD;
306*70445405SSean Christopherson 
307*70445405SSean Christopherson 	if (spec_ctrl_bits) {
308*70445405SSean Christopherson 		for (val = 0; val <= spec_ctrl_bits; val++) {
309*70445405SSean Christopherson 			/*
310*70445405SSean Christopherson 			 * Test only values that are guaranteed not to fault,
311*70445405SSean Christopherson 			 * virtualization of SPEC_CTRL has myriad holes that
312*70445405SSean Christopherson 			 * won't be ever closed.
313*70445405SSean Christopherson 			 */
314*70445405SSean Christopherson 			if ((val & spec_ctrl_bits) != val)
315*70445405SSean Christopherson 				continue;
316*70445405SSean Christopherson 
317*70445405SSean Christopherson 			test_msr_rw(MSR_IA32_SPEC_CTRL, "SPEC_CTRL", val);
318*70445405SSean Christopherson 		}
319*70445405SSean Christopherson 	} else {
320*70445405SSean Christopherson 		test_rdmsr_fault(MSR_IA32_SPEC_CTRL, "SPEC_CTRL");
321*70445405SSean Christopherson 		test_wrmsr_fault(MSR_IA32_SPEC_CTRL, "SPEC_CTRL", 0);
322*70445405SSean Christopherson 	}
323*70445405SSean Christopherson 
324fbd98087SSean Christopherson 	test_rdmsr_fault(MSR_IA32_PRED_CMD, "PRED_CMD");
325fbd98087SSean Christopherson 	if (this_cpu_has(X86_FEATURE_SPEC_CTRL) ||
3265cd94b1bSSean Christopherson 	    this_cpu_has(X86_FEATURE_AMD_IBPB) ||
3275cd94b1bSSean Christopherson 	    this_cpu_has(X86_FEATURE_SBPB)) {
328fbd98087SSean Christopherson 		test_wrmsr(MSR_IA32_PRED_CMD, "PRED_CMD", 0);
329fbd98087SSean Christopherson 		test_wrmsr(MSR_IA32_PRED_CMD, "PRED_CMD", PRED_CMD_IBPB);
330fbd98087SSean Christopherson 	} else {
331fbd98087SSean Christopherson 		test_wrmsr_fault(MSR_IA32_PRED_CMD, "PRED_CMD", 0);
332fbd98087SSean Christopherson 		test_wrmsr_fault(MSR_IA32_PRED_CMD, "PRED_CMD", PRED_CMD_IBPB);
333fbd98087SSean Christopherson 	}
3345cf6a3faSSean Christopherson 
3355cf6a3faSSean Christopherson 	test_rdmsr_fault(MSR_IA32_FLUSH_CMD, "FLUSH_CMD");
3365cf6a3faSSean Christopherson 	if (this_cpu_has(X86_FEATURE_FLUSH_L1D)) {
3375cf6a3faSSean Christopherson 		test_wrmsr(MSR_IA32_FLUSH_CMD, "FLUSH_CMD", 0);
3385cf6a3faSSean Christopherson 		test_wrmsr(MSR_IA32_FLUSH_CMD, "FLUSH_CMD", L1D_FLUSH);
3395cf6a3faSSean Christopherson 	} else {
3405cf6a3faSSean Christopherson 		test_wrmsr_fault(MSR_IA32_FLUSH_CMD, "FLUSH_CMD", 0);
3415cf6a3faSSean Christopherson 		test_wrmsr_fault(MSR_IA32_FLUSH_CMD, "FLUSH_CMD", L1D_FLUSH);
3425cf6a3faSSean Christopherson 	}
34313a12056SMingwei Zhang 
344486a097cSSean Christopherson 	if (is_fep_available) {
3455cf6a3faSSean Christopherson 		for (i = 1; i < 64; i++)
34613a12056SMingwei Zhang 			test_wrmsr_fep_fault(MSR_IA32_FLUSH_CMD, "FLUSH_CMD", BIT_ULL(i));
34713a12056SMingwei Zhang 	}
348fbd98087SSean Christopherson }
349fbd98087SSean Christopherson 
main(int ac,char ** av)35065096195SSean Christopherson int main(int ac, char **av)
35165096195SSean Christopherson {
35265096195SSean Christopherson 	/*
35365096195SSean Christopherson 	 * If the user provided an MSR+value, test exactly that and skip all
35465096195SSean Christopherson 	 * built-in testcases.
35565096195SSean Christopherson 	 */
35665096195SSean Christopherson 	if (ac == 3) {
35765096195SSean Christopherson 		test_custom_msr(ac, av);
35865096195SSean Christopherson 	} else {
35965096195SSean Christopherson 		test_misc_msrs();
36065096195SSean Christopherson 		test_mce_msrs();
3617c47d0d4SSean Christopherson 		test_x2apic_msrs();
362*70445405SSean Christopherson 		test_mitigation_msrs();
36365096195SSean Christopherson 	}
36465096195SSean Christopherson 
365f3cdd159SJan Kiszka 	return report_summary();
3667d36db35SAvi Kivity }
367