xref: /kvm-unit-tests/x86/msr.c (revision d3db85a3a3dae3bf4998d06daa0e17f0c427e21c)
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;
97d36db35SAvi Kivity     char *name;
107d36db35SAvi Kivity     struct tc {
117d36db35SAvi Kivity         int valid;
127d36db35SAvi Kivity         unsigned long long value;
137d36db35SAvi Kivity         unsigned long long expected;
147d36db35SAvi Kivity     } val_pairs[20];
157d36db35SAvi Kivity };
167d36db35SAvi Kivity 
177d36db35SAvi Kivity 
187d36db35SAvi Kivity #define addr_64 0x0000123456789abcULL
197d36db35SAvi Kivity 
207d36db35SAvi Kivity struct msr_info msr_info[] =
217d36db35SAvi Kivity {
227d36db35SAvi Kivity     { .index = 0x0000001b, .name = "MSR_IA32_APICBASE",
237d36db35SAvi Kivity       .val_pairs = {
247d36db35SAvi Kivity             { .valid = 1, .value = 0x0000000056789900, .expected = 0x0000000056789900},
257d36db35SAvi Kivity             { .valid = 1, .value = 0x0000000056789D01, .expected = 0x0000000056789D01},
267d36db35SAvi Kivity         }
277d36db35SAvi Kivity     },
287d36db35SAvi Kivity     { .index = 0x00000174, .name = "IA32_SYSENTER_CS",
297d36db35SAvi Kivity       .val_pairs = {{ .valid = 1, .value = 0x1234, .expected = 0x1234}}
307d36db35SAvi Kivity     },
317d36db35SAvi Kivity     { .index = 0x00000175, .name = "MSR_IA32_SYSENTER_ESP",
327d36db35SAvi Kivity       .val_pairs = {{ .valid = 1, .value = addr_64, .expected = addr_64}}
337d36db35SAvi Kivity     },
347d36db35SAvi Kivity     { .index = 0x00000176, .name = "IA32_SYSENTER_EIP",
357d36db35SAvi Kivity       .val_pairs = {{ .valid = 1, .value = addr_64, .expected = addr_64}}
367d36db35SAvi Kivity     },
377d36db35SAvi Kivity     { .index = 0x000001a0, .name = "MSR_IA32_MISC_ENABLE",
387d36db35SAvi Kivity       // reserved: 1:2, 4:6, 8:10, 13:15, 17, 19:21, 24:33, 35:63
397d36db35SAvi Kivity       .val_pairs = {{ .valid = 1, .value = 0x400c51889, .expected = 0x400c51889}}
407d36db35SAvi Kivity     },
417d36db35SAvi Kivity     { .index = 0x00000277, .name = "MSR_IA32_CR_PAT",
427d36db35SAvi Kivity       .val_pairs = {{ .valid = 1, .value = 0x07070707, .expected = 0x07070707}}
437d36db35SAvi Kivity     },
447d36db35SAvi Kivity     { .index = 0xc0000100, .name = "MSR_FS_BASE",
457d36db35SAvi Kivity       .val_pairs = {{ .valid = 1, .value = addr_64, .expected = addr_64}}
467d36db35SAvi Kivity     },
477d36db35SAvi Kivity     { .index = 0xc0000101, .name = "MSR_GS_BASE",
487d36db35SAvi Kivity       .val_pairs = {{ .valid = 1, .value = addr_64, .expected = addr_64}}
497d36db35SAvi Kivity     },
507d36db35SAvi Kivity     { .index = 0xc0000102, .name = "MSR_KERNEL_GS_BASE",
517d36db35SAvi Kivity       .val_pairs = {{ .valid = 1, .value = addr_64, .expected = addr_64}}
527d36db35SAvi Kivity     },
531389b749SJason Wang #ifdef __x86_64__
547d36db35SAvi Kivity     { .index = 0xc0000080, .name = "MSR_EFER",
557d36db35SAvi Kivity       .val_pairs = {{ .valid = 1, .value = 0xD00, .expected = 0xD00}}
567d36db35SAvi Kivity     },
571389b749SJason Wang #endif
587d36db35SAvi Kivity     { .index = 0xc0000082, .name = "MSR_LSTAR",
597d36db35SAvi Kivity       .val_pairs = {{ .valid = 1, .value = addr_64, .expected = addr_64}}
607d36db35SAvi Kivity     },
617d36db35SAvi Kivity     { .index = 0xc0000083, .name = "MSR_CSTAR",
627d36db35SAvi Kivity       .val_pairs = {{ .valid = 1, .value = addr_64, .expected = addr_64}}
637d36db35SAvi Kivity     },
647d36db35SAvi Kivity     { .index = 0xc0000084, .name = "MSR_SYSCALL_MASK",
657d36db35SAvi Kivity       .val_pairs = {{ .valid = 1, .value = 0xffffffff, .expected = 0xffffffff}}
667d36db35SAvi Kivity     },
677d36db35SAvi Kivity 
687d36db35SAvi Kivity //    MSR_IA32_DEBUGCTLMSR needs svm feature LBRV
697d36db35SAvi Kivity //    MSR_VM_HSAVE_PA only AMD host
707d36db35SAvi Kivity };
717d36db35SAvi Kivity 
727d36db35SAvi Kivity static int find_msr_info(int msr_index)
737d36db35SAvi Kivity {
747d36db35SAvi Kivity     int i;
757d36db35SAvi Kivity     for (i = 0; i < sizeof(msr_info)/sizeof(msr_info[0]) ; i++) {
767d36db35SAvi Kivity         if (msr_info[i].index == msr_index) {
777d36db35SAvi Kivity             return i;
787d36db35SAvi Kivity         }
797d36db35SAvi Kivity     }
807d36db35SAvi Kivity     return -1;
817d36db35SAvi Kivity }
827d36db35SAvi Kivity 
837d36db35SAvi Kivity 
847d36db35SAvi Kivity int nr_passed, nr_tests;
857d36db35SAvi Kivity 
867d36db35SAvi Kivity static void report(const char *name, int passed)
877d36db35SAvi Kivity {
887d36db35SAvi Kivity 	++nr_tests;
897d36db35SAvi Kivity 	if (passed)
907d36db35SAvi Kivity 		++nr_passed;
917d36db35SAvi Kivity 	printf("%s: %s\n", name, passed ? "PASS" : "FAIL");
927d36db35SAvi Kivity }
937d36db35SAvi Kivity 
947d36db35SAvi Kivity static void test_msr_rw(int msr_index, unsigned long long input, unsigned long long expected)
957d36db35SAvi Kivity {
967d36db35SAvi Kivity     unsigned long long r = 0;
977d36db35SAvi Kivity     int index;
987d36db35SAvi Kivity     char *sptr;
997d36db35SAvi Kivity     if ((index = find_msr_info(msr_index)) != -1) {
1007d36db35SAvi Kivity         sptr = msr_info[index].name;
1017d36db35SAvi Kivity     } else {
1027d36db35SAvi Kivity         printf("couldn't find name for msr # 0x%x, skipping\n", msr_index);
1037d36db35SAvi Kivity         return;
1047d36db35SAvi Kivity     }
1057d36db35SAvi Kivity     wrmsr(msr_index, input);
1067d36db35SAvi Kivity     r = rdmsr(msr_index);
1077d36db35SAvi Kivity     if (expected != r) {
1087d36db35SAvi Kivity         printf("testing %s: output = 0x%x:0x%x expected = 0x%x:0x%x\n", sptr, r >> 32, r, expected >> 32, expected);
1097d36db35SAvi Kivity     }
1107d36db35SAvi Kivity     report(sptr, expected == r);
1117d36db35SAvi Kivity }
1127d36db35SAvi Kivity 
113d1bdd07cSAvi Kivity static void test_syscall_lazy_load(void)
114d1bdd07cSAvi Kivity {
115*d3db85a3SMichael S. Tsirkin #ifdef __x86_64__
116d1bdd07cSAvi Kivity     extern void syscall_target();
117d1bdd07cSAvi Kivity     u16 cs = read_cs(), ss = read_ss();
118d1bdd07cSAvi Kivity     ulong tmp;
119d1bdd07cSAvi Kivity 
120d1bdd07cSAvi Kivity     wrmsr(MSR_EFER, rdmsr(MSR_EFER) | EFER_SCE);
121d1bdd07cSAvi Kivity     wrmsr(MSR_LSTAR, (ulong)syscall_target);
122d1bdd07cSAvi Kivity     wrmsr(MSR_STAR, (uint64_t)cs << 32);
123d1bdd07cSAvi Kivity     asm volatile("pushf; syscall; syscall_target: popf" : "=c"(tmp) : : "r11");
124d1bdd07cSAvi Kivity     write_ss(ss);
125d1bdd07cSAvi Kivity     // will crash horribly if broken
126d1bdd07cSAvi Kivity     report("MSR_*STAR eager loading", true);
127*d3db85a3SMichael S. Tsirkin #endif
128d1bdd07cSAvi Kivity }
129d1bdd07cSAvi Kivity 
1307d36db35SAvi Kivity int main(int ac, char **av)
1317d36db35SAvi Kivity {
1327d36db35SAvi Kivity     int i, j;
1337d36db35SAvi Kivity     for (i = 0 ; i < sizeof(msr_info) / sizeof(msr_info[0]); i++) {
1347d36db35SAvi Kivity         for (j = 0; j < sizeof(msr_info[i].val_pairs) / sizeof(msr_info[i].val_pairs[0]); j++) {
1357d36db35SAvi Kivity             if (msr_info[i].val_pairs[j].valid) {
1367d36db35SAvi Kivity                 test_msr_rw(msr_info[i].index, msr_info[i].val_pairs[j].value, msr_info[i].val_pairs[j].expected);
1377d36db35SAvi Kivity             } else {
1387d36db35SAvi Kivity                 break;
1397d36db35SAvi Kivity             }
1407d36db35SAvi Kivity         }
1417d36db35SAvi Kivity     }
1427d36db35SAvi Kivity 
143d1bdd07cSAvi Kivity     test_syscall_lazy_load();
144d1bdd07cSAvi Kivity 
1457d36db35SAvi Kivity     printf("%d tests, %d failures\n", nr_tests, nr_tests - nr_passed);
1467d36db35SAvi Kivity 
1477d36db35SAvi Kivity     return nr_passed == nr_tests ? 0 : 1;
1487d36db35SAvi Kivity }
1497d36db35SAvi Kivity 
150