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