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