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