1 /* msr tests */ 2 3 #include "libcflat.h" 4 #include "processor.h" 5 #include "msr.h" 6 #include <stdlib.h> 7 8 /** 9 * This test allows two modes: 10 * 1. Default: the `msr_info' array contains the default test configurations 11 * 2. Custom: by providing command line arguments it is possible to test any MSR and value 12 * Parameters order: 13 * 1. msr index as a base 16 number 14 * 2. value as a base 16 number 15 */ 16 17 struct msr_info { 18 int index; 19 bool is_64bit_only; 20 const char *name; 21 unsigned long long value; 22 unsigned long long keep; 23 }; 24 25 26 #define addr_64 0x0000123456789abcULL 27 #define addr_ul (unsigned long)addr_64 28 29 #define MSR_TEST(msr, val, ro) \ 30 { .index = msr, .name = #msr, .value = val, .is_64bit_only = false, .keep = ro } 31 #define MSR_TEST_ONLY64(msr, val, ro) \ 32 { .index = msr, .name = #msr, .value = val, .is_64bit_only = true, .keep = ro } 33 34 struct msr_info msr_info[] = 35 { 36 MSR_TEST(MSR_IA32_SYSENTER_CS, 0x1234, 0), 37 MSR_TEST(MSR_IA32_SYSENTER_ESP, addr_ul, 0), 38 MSR_TEST(MSR_IA32_SYSENTER_EIP, addr_ul, 0), 39 // reserved: 1:2, 4:6, 8:10, 13:15, 17, 19:21, 24:33, 35:63 40 // read-only: 7, 11, 12 41 MSR_TEST(MSR_IA32_MISC_ENABLE, 0x400c50809, 0x1880), 42 MSR_TEST(MSR_IA32_CR_PAT, 0x07070707, 0), 43 MSR_TEST_ONLY64(MSR_FS_BASE, addr_64, 0), 44 MSR_TEST_ONLY64(MSR_GS_BASE, addr_64, 0), 45 MSR_TEST_ONLY64(MSR_KERNEL_GS_BASE, addr_64, 0), 46 MSR_TEST(MSR_EFER, EFER_SCE, 0), 47 MSR_TEST_ONLY64(MSR_LSTAR, addr_64, 0), 48 MSR_TEST_ONLY64(MSR_CSTAR, addr_64, 0), 49 MSR_TEST_ONLY64(MSR_SYSCALL_MASK, 0xffffffff, 0), 50 // MSR_IA32_DEBUGCTLMSR needs svm feature LBRV 51 // MSR_VM_HSAVE_PA only AMD host 52 }; 53 54 static void test_msr_rw(struct msr_info *msr, unsigned long long val) 55 { 56 unsigned long long r, orig; 57 58 orig = rdmsr(msr->index); 59 /* 60 * Special case EFER since clearing LME/LMA is not allowed in 64-bit mode, 61 * and conversely setting those bits on 32-bit CPUs is not allowed. Treat 62 * the desired value as extra bits to set. 63 */ 64 if (msr->index == MSR_EFER) 65 val |= orig; 66 else 67 val = (val & ~msr->keep) | (orig & msr->keep); 68 wrmsr(msr->index, val); 69 r = rdmsr(msr->index); 70 wrmsr(msr->index, orig); 71 if (r != val) { 72 printf("testing %s: output = %#" PRIx32 ":%#" PRIx32 73 " expected = %#" PRIx32 ":%#" PRIx32 "\n", msr->name, 74 (u32)(r >> 32), (u32)r, (u32)(val >> 32), (u32)val); 75 } 76 report(val == r, "%s", msr->name); 77 } 78 79 static void test_wrmsr_fault(struct msr_info *msr, unsigned long long val) 80 { 81 unsigned char vector = wrmsr_checking(msr->index, val); 82 83 report(vector == GP_VECTOR, 84 "Expected #GP on WRSMR(%s, 0x%llx), got vector %d", 85 msr->name, val, vector); 86 } 87 88 static void test_rdmsr_fault(struct msr_info *msr) 89 { 90 unsigned char vector = rdmsr_checking(msr->index); 91 92 report(vector == GP_VECTOR, 93 "Expected #GP on RDSMR(%s), got vector %d", msr->name, vector); 94 } 95 96 static void test_msr(struct msr_info *msr, bool is_64bit_host) 97 { 98 if (is_64bit_host || !msr->is_64bit_only) { 99 test_msr_rw(msr, msr->value); 100 101 /* 102 * The 64-bit only MSRs that take an address always perform 103 * canonical checks on both Intel and AMD. 104 */ 105 if (msr->is_64bit_only && 106 msr->value == addr_64) 107 test_wrmsr_fault(msr, NONCANONICAL); 108 } else { 109 test_wrmsr_fault(msr, msr->value); 110 test_rdmsr_fault(msr); 111 } 112 } 113 114 int main(int ac, char **av) 115 { 116 bool is_64bit_host = this_cpu_has(X86_FEATURE_LM); 117 int i; 118 119 if (ac == 3) { 120 char msr_name[16]; 121 int index = strtoul(av[1], NULL, 0x10); 122 snprintf(msr_name, sizeof(msr_name), "MSR:0x%x", index); 123 124 struct msr_info msr = { 125 .index = index, 126 .name = msr_name, 127 .value = strtoull(av[2], NULL, 0x10) 128 }; 129 test_msr(&msr, is_64bit_host); 130 } else { 131 for (i = 0 ; i < ARRAY_SIZE(msr_info); i++) { 132 test_msr(&msr_info[i], is_64bit_host); 133 } 134 } 135 136 return report_summary(); 137 } 138