xref: /kvm-unit-tests/x86/msr.c (revision dcae8d5f1ada02b5148e4ffdad850651c95456c1)
17d36db35SAvi Kivity /* msr tests */
27d36db35SAvi Kivity 
37d36db35SAvi Kivity #include "libcflat.h"
4850479e3SJason Wang #include "processor.h"
5d1bdd07cSAvi Kivity #include "msr.h"
67d36db35SAvi Kivity 
77d36db35SAvi Kivity struct msr_info {
87d36db35SAvi Kivity 	int index;
9142ff635SSean Christopherson 	bool is_64bit_only;
10797d79a2SThomas Huth 	const char *name;
117d36db35SAvi Kivity 	unsigned long long value;
127d36db35SAvi Kivity };
137d36db35SAvi Kivity 
147d36db35SAvi Kivity 
157d36db35SAvi Kivity #define addr_64 0x0000123456789abcULL
168feb8cfbSSean Christopherson #define addr_ul (unsigned long)addr_64
177d36db35SAvi Kivity 
18142ff635SSean Christopherson #define MSR_TEST(msr, val, only64)	\
19142ff635SSean Christopherson 	{ .index = msr, .name = #msr, .value = val, .is_64bit_only = only64 }
2064662079SSean Christopherson 
217d36db35SAvi Kivity struct msr_info msr_info[] =
227d36db35SAvi Kivity {
23142ff635SSean Christopherson 	MSR_TEST(MSR_IA32_SYSENTER_CS, 0x1234, false),
24142ff635SSean Christopherson 	MSR_TEST(MSR_IA32_SYSENTER_ESP, addr_ul, false),
25142ff635SSean Christopherson 	MSR_TEST(MSR_IA32_SYSENTER_EIP, addr_ul, false),
267d36db35SAvi Kivity 	// reserved: 1:2, 4:6, 8:10, 13:15, 17, 19:21, 24:33, 35:63
27142ff635SSean Christopherson 	MSR_TEST(MSR_IA32_MISC_ENABLE, 0x400c51889, false),
28142ff635SSean Christopherson 	MSR_TEST(MSR_IA32_CR_PAT, 0x07070707, false),
29142ff635SSean Christopherson 	MSR_TEST(MSR_FS_BASE, addr_64, true),
30142ff635SSean Christopherson 	MSR_TEST(MSR_GS_BASE, addr_64, true),
31142ff635SSean Christopherson 	MSR_TEST(MSR_KERNEL_GS_BASE, addr_64, true),
32*dcae8d5fSSean Christopherson 	MSR_TEST(MSR_EFER, EFER_SCE, false),
33142ff635SSean Christopherson 	MSR_TEST(MSR_LSTAR, addr_64, true),
34142ff635SSean Christopherson 	MSR_TEST(MSR_CSTAR, addr_64, true),
35142ff635SSean Christopherson 	MSR_TEST(MSR_SYSCALL_MASK, 0xffffffff, true),
367d36db35SAvi Kivity //	MSR_IA32_DEBUGCTLMSR needs svm feature LBRV
377d36db35SAvi Kivity //	MSR_VM_HSAVE_PA only AMD host
387d36db35SAvi Kivity };
397d36db35SAvi Kivity 
403e788d91SSean Christopherson static void test_msr_rw(struct msr_info *msr, unsigned long long val)
417d36db35SAvi Kivity {
42a73d6ae4SSean Christopherson 	unsigned long long r, orig;
4350273266SSean Christopherson 
443e788d91SSean Christopherson 	orig = rdmsr(msr->index);
45*dcae8d5fSSean Christopherson 	/*
46*dcae8d5fSSean Christopherson 	 * Special case EFER since clearing LME/LMA is not allowed in 64-bit mode,
47*dcae8d5fSSean Christopherson 	 * and conversely setting those bits on 32-bit CPUs is not allowed.  Treat
48*dcae8d5fSSean Christopherson 	 * the desired value as extra bits to set.
49*dcae8d5fSSean Christopherson 	 */
50*dcae8d5fSSean Christopherson 	if (msr->index == MSR_EFER)
51*dcae8d5fSSean Christopherson 		val |= orig;
523e788d91SSean Christopherson 	wrmsr(msr->index, val);
533e788d91SSean Christopherson 	r = rdmsr(msr->index);
543e788d91SSean Christopherson 	wrmsr(msr->index, orig);
559295327cSSean Christopherson 	if (r != val) {
56d26193a0SRoman Bolshakov 		printf("testing %s: output = %#" PRIx32 ":%#" PRIx32
573e788d91SSean Christopherson 		       " expected = %#" PRIx32 ":%#" PRIx32 "\n", msr->name,
589295327cSSean Christopherson 		       (u32)(r >> 32), (u32)r, (u32)(val >> 32), (u32)val);
597d36db35SAvi Kivity 	}
603e788d91SSean Christopherson 	report(val == r, "%s", msr->name);
617d36db35SAvi Kivity }
627d36db35SAvi Kivity 
63142ff635SSean Christopherson static void test_wrmsr_fault(struct msr_info *msr, unsigned long long val)
64142ff635SSean Christopherson {
65142ff635SSean Christopherson 	unsigned char vector = wrmsr_checking(msr->index, val);
66142ff635SSean Christopherson 
67142ff635SSean Christopherson 	report(vector == GP_VECTOR,
68142ff635SSean Christopherson 	       "Expected #GP on WRSMR(%s, 0x%llx), got vector %d",
69142ff635SSean Christopherson 	       msr->name, val, vector);
70142ff635SSean Christopherson }
71142ff635SSean Christopherson 
72142ff635SSean Christopherson static void test_rdmsr_fault(struct msr_info *msr)
73142ff635SSean Christopherson {
74142ff635SSean Christopherson 	unsigned char vector = rdmsr_checking(msr->index);
75142ff635SSean Christopherson 
76142ff635SSean Christopherson 	report(vector == GP_VECTOR,
77142ff635SSean Christopherson 	       "Expected #GP on RDSMR(%s), got vector %d", msr->name, vector);
78142ff635SSean Christopherson }
79142ff635SSean Christopherson 
807d36db35SAvi Kivity int main(int ac, char **av)
817d36db35SAvi Kivity {
82142ff635SSean Christopherson 	bool is_64bit_host = this_cpu_has(X86_FEATURE_LM);
8364662079SSean Christopherson 	int i;
8464662079SSean Christopherson 
85142ff635SSean Christopherson 	for (i = 0 ; i < ARRAY_SIZE(msr_info); i++) {
86142ff635SSean Christopherson 		if (is_64bit_host || !msr_info[i].is_64bit_only) {
873e788d91SSean Christopherson 			test_msr_rw(&msr_info[i], msr_info[i].value);
8888f0bb17SSean Christopherson 
8988f0bb17SSean Christopherson 			/*
9088f0bb17SSean Christopherson 			 * The 64-bit only MSRs that take an address always perform
9188f0bb17SSean Christopherson 			 * canonical checks on both Intel and AMD.
9288f0bb17SSean Christopherson 			 */
9388f0bb17SSean Christopherson 			if (msr_info[i].is_64bit_only &&
9488f0bb17SSean Christopherson 			    msr_info[i].value == addr_64)
9588f0bb17SSean Christopherson 				test_wrmsr_fault(&msr_info[i], NONCANONICAL);
96142ff635SSean Christopherson 		} else {
97142ff635SSean Christopherson 			test_wrmsr_fault(&msr_info[i], msr_info[i].value);
98142ff635SSean Christopherson 			test_rdmsr_fault(&msr_info[i]);
99142ff635SSean Christopherson 		}
100142ff635SSean Christopherson 	}
1017d36db35SAvi Kivity 
102f3cdd159SJan Kiszka 	return report_summary();
1037d36db35SAvi Kivity }
104