xref: /kvm-unit-tests/x86/msr.c (revision 7d36db351752e29ad27eaafe3f102de7064e429b)
1*7d36db35SAvi Kivity /* msr tests */
2*7d36db35SAvi Kivity 
3*7d36db35SAvi Kivity #include "libcflat.h"
4*7d36db35SAvi Kivity 
5*7d36db35SAvi Kivity struct msr_info {
6*7d36db35SAvi Kivity     int index;
7*7d36db35SAvi Kivity     char *name;
8*7d36db35SAvi Kivity     struct tc {
9*7d36db35SAvi Kivity         int valid;
10*7d36db35SAvi Kivity         unsigned long long value;
11*7d36db35SAvi Kivity         unsigned long long expected;
12*7d36db35SAvi Kivity     } val_pairs[20];
13*7d36db35SAvi Kivity };
14*7d36db35SAvi Kivity 
15*7d36db35SAvi Kivity 
16*7d36db35SAvi Kivity #define addr_64 0x0000123456789abcULL
17*7d36db35SAvi Kivity 
18*7d36db35SAvi Kivity struct msr_info msr_info[] =
19*7d36db35SAvi Kivity {
20*7d36db35SAvi Kivity     { .index = 0x0000001b, .name = "MSR_IA32_APICBASE",
21*7d36db35SAvi Kivity       .val_pairs = {
22*7d36db35SAvi Kivity             { .valid = 1, .value = 0x0000000056789900, .expected = 0x0000000056789900},
23*7d36db35SAvi Kivity             { .valid = 1, .value = 0x0000000056789D01, .expected = 0x0000000056789D01},
24*7d36db35SAvi Kivity         }
25*7d36db35SAvi Kivity     },
26*7d36db35SAvi Kivity     { .index = 0x00000174, .name = "IA32_SYSENTER_CS",
27*7d36db35SAvi Kivity       .val_pairs = {{ .valid = 1, .value = 0x1234, .expected = 0x1234}}
28*7d36db35SAvi Kivity     },
29*7d36db35SAvi Kivity     { .index = 0x00000175, .name = "MSR_IA32_SYSENTER_ESP",
30*7d36db35SAvi Kivity       .val_pairs = {{ .valid = 1, .value = addr_64, .expected = addr_64}}
31*7d36db35SAvi Kivity     },
32*7d36db35SAvi Kivity     { .index = 0x00000176, .name = "IA32_SYSENTER_EIP",
33*7d36db35SAvi Kivity       .val_pairs = {{ .valid = 1, .value = addr_64, .expected = addr_64}}
34*7d36db35SAvi Kivity     },
35*7d36db35SAvi Kivity     { .index = 0x000001a0, .name = "MSR_IA32_MISC_ENABLE",
36*7d36db35SAvi Kivity       // reserved: 1:2, 4:6, 8:10, 13:15, 17, 19:21, 24:33, 35:63
37*7d36db35SAvi Kivity       .val_pairs = {{ .valid = 1, .value = 0x400c51889, .expected = 0x400c51889}}
38*7d36db35SAvi Kivity     },
39*7d36db35SAvi Kivity     { .index = 0x00000277, .name = "MSR_IA32_CR_PAT",
40*7d36db35SAvi Kivity       .val_pairs = {{ .valid = 1, .value = 0x07070707, .expected = 0x07070707}}
41*7d36db35SAvi Kivity     },
42*7d36db35SAvi Kivity     { .index = 0xc0000100, .name = "MSR_FS_BASE",
43*7d36db35SAvi Kivity       .val_pairs = {{ .valid = 1, .value = addr_64, .expected = addr_64}}
44*7d36db35SAvi Kivity     },
45*7d36db35SAvi Kivity     { .index = 0xc0000101, .name = "MSR_GS_BASE",
46*7d36db35SAvi Kivity       .val_pairs = {{ .valid = 1, .value = addr_64, .expected = addr_64}}
47*7d36db35SAvi Kivity     },
48*7d36db35SAvi Kivity     { .index = 0xc0000102, .name = "MSR_KERNEL_GS_BASE",
49*7d36db35SAvi Kivity       .val_pairs = {{ .valid = 1, .value = addr_64, .expected = addr_64}}
50*7d36db35SAvi Kivity     },
51*7d36db35SAvi Kivity     { .index = 0xc0000080, .name = "MSR_EFER",
52*7d36db35SAvi Kivity       .val_pairs = {{ .valid = 1, .value = 0xD00, .expected = 0xD00}}
53*7d36db35SAvi Kivity     },
54*7d36db35SAvi Kivity     { .index = 0xc0000082, .name = "MSR_LSTAR",
55*7d36db35SAvi Kivity       .val_pairs = {{ .valid = 1, .value = addr_64, .expected = addr_64}}
56*7d36db35SAvi Kivity     },
57*7d36db35SAvi Kivity     { .index = 0xc0000083, .name = "MSR_CSTAR",
58*7d36db35SAvi Kivity       .val_pairs = {{ .valid = 1, .value = addr_64, .expected = addr_64}}
59*7d36db35SAvi Kivity     },
60*7d36db35SAvi Kivity     { .index = 0xc0000084, .name = "MSR_SYSCALL_MASK",
61*7d36db35SAvi Kivity       .val_pairs = {{ .valid = 1, .value = 0xffffffff, .expected = 0xffffffff}}
62*7d36db35SAvi Kivity     },
63*7d36db35SAvi Kivity 
64*7d36db35SAvi Kivity //    MSR_IA32_DEBUGCTLMSR needs svm feature LBRV
65*7d36db35SAvi Kivity //    MSR_VM_HSAVE_PA only AMD host
66*7d36db35SAvi Kivity };
67*7d36db35SAvi Kivity 
68*7d36db35SAvi Kivity static int find_msr_info(int msr_index)
69*7d36db35SAvi Kivity {
70*7d36db35SAvi Kivity     int i;
71*7d36db35SAvi Kivity     for (i = 0; i < sizeof(msr_info)/sizeof(msr_info[0]) ; i++) {
72*7d36db35SAvi Kivity         if (msr_info[i].index == msr_index) {
73*7d36db35SAvi Kivity             return i;
74*7d36db35SAvi Kivity         }
75*7d36db35SAvi Kivity     }
76*7d36db35SAvi Kivity     return -1;
77*7d36db35SAvi Kivity }
78*7d36db35SAvi Kivity 
79*7d36db35SAvi Kivity 
80*7d36db35SAvi Kivity int nr_passed, nr_tests;
81*7d36db35SAvi Kivity 
82*7d36db35SAvi Kivity static void report(const char *name, int passed)
83*7d36db35SAvi Kivity {
84*7d36db35SAvi Kivity 	++nr_tests;
85*7d36db35SAvi Kivity 	if (passed)
86*7d36db35SAvi Kivity 		++nr_passed;
87*7d36db35SAvi Kivity 	printf("%s: %s\n", name, passed ? "PASS" : "FAIL");
88*7d36db35SAvi Kivity }
89*7d36db35SAvi Kivity 
90*7d36db35SAvi Kivity static void wrmsr(unsigned index, unsigned long long value)
91*7d36db35SAvi Kivity {
92*7d36db35SAvi Kivity 	unsigned a = value, d = value >> 32;
93*7d36db35SAvi Kivity 
94*7d36db35SAvi Kivity 	asm volatile("wrmsr" : : "a"(a), "d"(d), "c"(index));
95*7d36db35SAvi Kivity }
96*7d36db35SAvi Kivity 
97*7d36db35SAvi Kivity static unsigned long long rdmsr(unsigned index)
98*7d36db35SAvi Kivity {
99*7d36db35SAvi Kivity 	unsigned a, d;
100*7d36db35SAvi Kivity 
101*7d36db35SAvi Kivity 	asm volatile("rdmsr" : "=a"(a), "=d"(d) : "c"(index));
102*7d36db35SAvi Kivity 	return ((unsigned long long)d << 32) | a;
103*7d36db35SAvi Kivity }
104*7d36db35SAvi Kivity 
105*7d36db35SAvi Kivity static void test_msr_rw(int msr_index, unsigned long long input, unsigned long long expected)
106*7d36db35SAvi Kivity {
107*7d36db35SAvi Kivity     unsigned long long r = 0;
108*7d36db35SAvi Kivity     int index;
109*7d36db35SAvi Kivity     char *sptr;
110*7d36db35SAvi Kivity     if ((index = find_msr_info(msr_index)) != -1) {
111*7d36db35SAvi Kivity         sptr = msr_info[index].name;
112*7d36db35SAvi Kivity     } else {
113*7d36db35SAvi Kivity         printf("couldn't find name for msr # 0x%x, skipping\n", msr_index);
114*7d36db35SAvi Kivity         return;
115*7d36db35SAvi Kivity     }
116*7d36db35SAvi Kivity     wrmsr(msr_index, input);
117*7d36db35SAvi Kivity     r = rdmsr(msr_index);
118*7d36db35SAvi Kivity     if (expected != r) {
119*7d36db35SAvi Kivity         printf("testing %s: output = 0x%x:0x%x expected = 0x%x:0x%x\n", sptr, r >> 32, r, expected >> 32, expected);
120*7d36db35SAvi Kivity     }
121*7d36db35SAvi Kivity     report(sptr, expected == r);
122*7d36db35SAvi Kivity }
123*7d36db35SAvi Kivity 
124*7d36db35SAvi Kivity int main(int ac, char **av)
125*7d36db35SAvi Kivity {
126*7d36db35SAvi Kivity     int i, j;
127*7d36db35SAvi Kivity     for (i = 0 ; i < sizeof(msr_info) / sizeof(msr_info[0]); i++) {
128*7d36db35SAvi Kivity         for (j = 0; j < sizeof(msr_info[i].val_pairs) / sizeof(msr_info[i].val_pairs[0]); j++) {
129*7d36db35SAvi Kivity             if (msr_info[i].val_pairs[j].valid) {
130*7d36db35SAvi Kivity                 test_msr_rw(msr_info[i].index, msr_info[i].val_pairs[j].value, msr_info[i].val_pairs[j].expected);
131*7d36db35SAvi Kivity             } else {
132*7d36db35SAvi Kivity                 break;
133*7d36db35SAvi Kivity             }
134*7d36db35SAvi Kivity         }
135*7d36db35SAvi Kivity     }
136*7d36db35SAvi Kivity 
137*7d36db35SAvi Kivity     printf("%d tests, %d failures\n", nr_tests, nr_tests - nr_passed);
138*7d36db35SAvi Kivity 
139*7d36db35SAvi Kivity     return nr_passed == nr_tests ? 0 : 1;
140*7d36db35SAvi Kivity }
141*7d36db35SAvi Kivity 
142