17d36db35SAvi Kivity /* msr tests */ 27d36db35SAvi Kivity 37d36db35SAvi Kivity #include "libcflat.h" 4850479e3SJason Wang #include "processor.h" 5d1bdd07cSAvi Kivity #include "msr.h" 65b4855b3SDaniele Ahmed #include <stdlib.h> 75b4855b3SDaniele Ahmed 85b4855b3SDaniele Ahmed /** 95b4855b3SDaniele Ahmed * This test allows two modes: 105b4855b3SDaniele Ahmed * 1. Default: the `msr_info' array contains the default test configurations 115b4855b3SDaniele Ahmed * 2. Custom: by providing command line arguments it is possible to test any MSR and value 125b4855b3SDaniele Ahmed * Parameters order: 135b4855b3SDaniele Ahmed * 1. msr index as a base 16 number 145b4855b3SDaniele Ahmed * 2. value as a base 16 number 155b4855b3SDaniele Ahmed */ 167d36db35SAvi Kivity 177d36db35SAvi Kivity struct msr_info { 187d36db35SAvi Kivity int index; 19142ff635SSean Christopherson bool is_64bit_only; 20797d79a2SThomas Huth const char *name; 217d36db35SAvi Kivity unsigned long long value; 22bab19cadSPaolo Bonzini unsigned long long keep; 237d36db35SAvi Kivity }; 247d36db35SAvi Kivity 257d36db35SAvi Kivity 267d36db35SAvi Kivity #define addr_64 0x0000123456789abcULL 278feb8cfbSSean Christopherson #define addr_ul (unsigned long)addr_64 287d36db35SAvi Kivity 29ca85dda2SSean Christopherson #define MSR_TEST(msr, val, ro) \ 30ca85dda2SSean Christopherson { .index = msr, .name = #msr, .value = val, .is_64bit_only = false, .keep = ro } 31ca85dda2SSean Christopherson #define MSR_TEST_ONLY64(msr, val, ro) \ 32ca85dda2SSean Christopherson { .index = msr, .name = #msr, .value = val, .is_64bit_only = true, .keep = ro } 3364662079SSean Christopherson 347d36db35SAvi Kivity struct msr_info msr_info[] = 357d36db35SAvi Kivity { 36ca85dda2SSean Christopherson MSR_TEST(MSR_IA32_SYSENTER_CS, 0x1234, 0), 37ca85dda2SSean Christopherson MSR_TEST(MSR_IA32_SYSENTER_ESP, addr_ul, 0), 38ca85dda2SSean Christopherson MSR_TEST(MSR_IA32_SYSENTER_EIP, addr_ul, 0), 397d36db35SAvi Kivity // reserved: 1:2, 4:6, 8:10, 13:15, 17, 19:21, 24:33, 35:63 40bab19cadSPaolo Bonzini // read-only: 7, 11, 12 41ca85dda2SSean Christopherson MSR_TEST(MSR_IA32_MISC_ENABLE, 0x400c50809, 0x1880), 42ca85dda2SSean Christopherson MSR_TEST(MSR_IA32_CR_PAT, 0x07070707, 0), 43ca85dda2SSean Christopherson MSR_TEST_ONLY64(MSR_FS_BASE, addr_64, 0), 44ca85dda2SSean Christopherson MSR_TEST_ONLY64(MSR_GS_BASE, addr_64, 0), 45ca85dda2SSean Christopherson MSR_TEST_ONLY64(MSR_KERNEL_GS_BASE, addr_64, 0), 46ca85dda2SSean Christopherson MSR_TEST(MSR_EFER, EFER_SCE, 0), 47ca85dda2SSean Christopherson MSR_TEST_ONLY64(MSR_LSTAR, addr_64, 0), 48ca85dda2SSean Christopherson MSR_TEST_ONLY64(MSR_CSTAR, addr_64, 0), 49ca85dda2SSean Christopherson MSR_TEST_ONLY64(MSR_SYSCALL_MASK, 0xffffffff, 0), 507d36db35SAvi Kivity // MSR_IA32_DEBUGCTLMSR needs svm feature LBRV 517d36db35SAvi Kivity // MSR_VM_HSAVE_PA only AMD host 527d36db35SAvi Kivity }; 537d36db35SAvi Kivity 54039d9207SSean Christopherson static void __test_msr_rw(u32 msr, const char *name, unsigned long long val, 55fb0d9894SSean Christopherson unsigned long long keep_mask) 567d36db35SAvi Kivity { 57a73d6ae4SSean Christopherson unsigned long long r, orig; 5850273266SSean Christopherson 59fb0d9894SSean Christopherson orig = rdmsr(msr); 60dcae8d5fSSean Christopherson /* 61dcae8d5fSSean Christopherson * Special case EFER since clearing LME/LMA is not allowed in 64-bit mode, 62dcae8d5fSSean Christopherson * and conversely setting those bits on 32-bit CPUs is not allowed. Treat 63dcae8d5fSSean Christopherson * the desired value as extra bits to set. 64dcae8d5fSSean Christopherson */ 65fb0d9894SSean Christopherson if (msr == MSR_EFER) 66dcae8d5fSSean Christopherson val |= orig; 67bab19cadSPaolo Bonzini else 68fb0d9894SSean Christopherson val = (val & ~keep_mask) | (orig & keep_mask); 69fb0d9894SSean Christopherson 70fb0d9894SSean Christopherson wrmsr(msr, val); 71fb0d9894SSean Christopherson r = rdmsr(msr); 72fb0d9894SSean Christopherson wrmsr(msr, orig); 73fb0d9894SSean Christopherson 749295327cSSean Christopherson if (r != val) { 75d26193a0SRoman Bolshakov printf("testing %s: output = %#" PRIx32 ":%#" PRIx32 76fb0d9894SSean Christopherson " expected = %#" PRIx32 ":%#" PRIx32 "\n", name, 779295327cSSean Christopherson (u32)(r >> 32), (u32)r, (u32)(val >> 32), (u32)val); 787d36db35SAvi Kivity } 79fb0d9894SSean Christopherson report(val == r, "%s", name); 807d36db35SAvi Kivity } 817d36db35SAvi Kivity 82039d9207SSean Christopherson static void test_msr_rw(u32 msr, const char *name, unsigned long long val) 83039d9207SSean Christopherson { 84039d9207SSean Christopherson __test_msr_rw(msr, name, val, 0); 85039d9207SSean Christopherson } 86039d9207SSean Christopherson 87fb0d9894SSean Christopherson static void test_wrmsr_fault(u32 msr, const char *name, unsigned long long val) 88142ff635SSean Christopherson { 894143fbfdSSean Christopherson unsigned char vector = wrmsr_safe(msr, val); 90142ff635SSean Christopherson 91142ff635SSean Christopherson report(vector == GP_VECTOR, 92142ff635SSean Christopherson "Expected #GP on WRSMR(%s, 0x%llx), got vector %d", 93fb0d9894SSean Christopherson name, val, vector); 94142ff635SSean Christopherson } 95142ff635SSean Christopherson 96fb0d9894SSean Christopherson static void test_rdmsr_fault(u32 msr, const char *name) 97142ff635SSean Christopherson { 980a4d8626SSean Christopherson uint64_t ignored; 990a4d8626SSean Christopherson unsigned char vector = rdmsr_safe(msr, &ignored); 100142ff635SSean Christopherson 101142ff635SSean Christopherson report(vector == GP_VECTOR, 102fb0d9894SSean Christopherson "Expected #GP on RDSMR(%s), got vector %d", name, vector); 103142ff635SSean Christopherson } 104142ff635SSean Christopherson 1059e8ecb28SDaniele Ahmed static void test_msr(struct msr_info *msr, bool is_64bit_host) 1069e8ecb28SDaniele Ahmed { 1079e8ecb28SDaniele Ahmed if (is_64bit_host || !msr->is_64bit_only) { 108039d9207SSean Christopherson __test_msr_rw(msr->index, msr->name, msr->value, msr->keep); 1099e8ecb28SDaniele Ahmed 1109e8ecb28SDaniele Ahmed /* 1119e8ecb28SDaniele Ahmed * The 64-bit only MSRs that take an address always perform 1129e8ecb28SDaniele Ahmed * canonical checks on both Intel and AMD. 1139e8ecb28SDaniele Ahmed */ 1149e8ecb28SDaniele Ahmed if (msr->is_64bit_only && 1159e8ecb28SDaniele Ahmed msr->value == addr_64) 116fb0d9894SSean Christopherson test_wrmsr_fault(msr->index, msr->name, NONCANONICAL); 1179e8ecb28SDaniele Ahmed } else { 118fb0d9894SSean Christopherson test_wrmsr_fault(msr->index, msr->name, msr->value); 119fb0d9894SSean Christopherson test_rdmsr_fault(msr->index, msr->name); 1209e8ecb28SDaniele Ahmed } 1219e8ecb28SDaniele Ahmed } 1229e8ecb28SDaniele Ahmed 123*65096195SSean Christopherson static void test_custom_msr(int ac, char **av) 1247d36db35SAvi Kivity { 125142ff635SSean Christopherson bool is_64bit_host = this_cpu_has(X86_FEATURE_LM); 126039d9207SSean Christopherson char msr_name[32]; 1275b4855b3SDaniele Ahmed int index = strtoul(av[1], NULL, 0x10); 1285b4855b3SDaniele Ahmed snprintf(msr_name, sizeof(msr_name), "MSR:0x%x", index); 1295b4855b3SDaniele Ahmed 1305b4855b3SDaniele Ahmed struct msr_info msr = { 1315b4855b3SDaniele Ahmed .index = index, 1325b4855b3SDaniele Ahmed .name = msr_name, 1335b4855b3SDaniele Ahmed .value = strtoull(av[2], NULL, 0x10) 1345b4855b3SDaniele Ahmed }; 1355b4855b3SDaniele Ahmed test_msr(&msr, is_64bit_host); 136*65096195SSean Christopherson } 137*65096195SSean Christopherson 138*65096195SSean Christopherson static void test_misc_msrs(void) 139*65096195SSean Christopherson { 140*65096195SSean Christopherson bool is_64bit_host = this_cpu_has(X86_FEATURE_LM); 141*65096195SSean Christopherson int i; 142*65096195SSean Christopherson 143039d9207SSean Christopherson for (i = 0 ; i < ARRAY_SIZE(msr_info); i++) 1449e8ecb28SDaniele Ahmed test_msr(&msr_info[i], is_64bit_host); 145*65096195SSean Christopherson } 146*65096195SSean Christopherson 147*65096195SSean Christopherson static void test_mce_msrs(void) 148*65096195SSean Christopherson { 149*65096195SSean Christopherson bool is_64bit_host = this_cpu_has(X86_FEATURE_LM); 150*65096195SSean Christopherson unsigned int nr_mce_banks; 151*65096195SSean Christopherson char msr_name[32]; 152*65096195SSean Christopherson int i; 153039d9207SSean Christopherson 154039d9207SSean Christopherson nr_mce_banks = rdmsr(MSR_IA32_MCG_CAP) & 0xff; 155039d9207SSean Christopherson for (i = 0; i < nr_mce_banks; i++) { 156039d9207SSean Christopherson snprintf(msr_name, sizeof(msr_name), "MSR_IA32_MC%u_CTL", i); 157039d9207SSean Christopherson test_msr_rw(MSR_IA32_MCx_CTL(i), msr_name, 0); 158039d9207SSean Christopherson test_msr_rw(MSR_IA32_MCx_CTL(i), msr_name, -1ull); 159039d9207SSean Christopherson test_wrmsr_fault(MSR_IA32_MCx_CTL(i), msr_name, NONCANONICAL); 160039d9207SSean Christopherson 161039d9207SSean Christopherson snprintf(msr_name, sizeof(msr_name), "MSR_IA32_MC%u_STATUS", i); 162039d9207SSean Christopherson test_msr_rw(MSR_IA32_MCx_STATUS(i), msr_name, 0); 163039d9207SSean Christopherson /* 164*65096195SSean Christopherson * STATUS MSRs can only be written with '0' (to clear the MSR), 165*65096195SSean Christopherson * except on AMD-based systems with bit 18 set in MSR_K7_HWCR. 166*65096195SSean Christopherson * That bit is not architectural and should not be set by 167*65096195SSean Christopherson * default by KVM or by the VMM (though this might fail if run 168*65096195SSean Christopherson * on bare metal). 169039d9207SSean Christopherson */ 170039d9207SSean Christopherson test_wrmsr_fault(MSR_IA32_MCx_STATUS(i), msr_name, 1); 171039d9207SSean Christopherson 172039d9207SSean Christopherson snprintf(msr_name, sizeof(msr_name), "MSR_IA32_MC%u_ADDR", i); 173039d9207SSean Christopherson test_msr_rw(MSR_IA32_MCx_ADDR(i), msr_name, 0); 174039d9207SSean Christopherson test_msr_rw(MSR_IA32_MCx_ADDR(i), msr_name, -1ull); 175039d9207SSean Christopherson /* 176*65096195SSean Christopherson * The ADDR is a physical address, and all bits are writable on 177*65096195SSean Christopherson * 64-bit hosts. Don't test the negative case, as KVM doesn't 178*65096195SSean Christopherson * enforce checks on bits 63:36 for 32-bit hosts. The behavior 179*65096195SSean Christopherson * depends on the underlying hardware, e.g. a 32-bit guest on a 180*65096195SSean Christopherson * 64-bit host may observe 64-bit values in the ADDR MSRs. 181039d9207SSean Christopherson */ 182039d9207SSean Christopherson if (is_64bit_host) 183039d9207SSean Christopherson test_msr_rw(MSR_IA32_MCx_ADDR(i), msr_name, NONCANONICAL); 184039d9207SSean Christopherson 185039d9207SSean Christopherson snprintf(msr_name, sizeof(msr_name), "MSR_IA32_MC%u_MISC", i); 186039d9207SSean Christopherson test_msr_rw(MSR_IA32_MCx_MISC(i), msr_name, 0); 187039d9207SSean Christopherson test_msr_rw(MSR_IA32_MCx_MISC(i), msr_name, -1ull); 188039d9207SSean Christopherson test_msr_rw(MSR_IA32_MCx_MISC(i), msr_name, NONCANONICAL); 189039d9207SSean Christopherson } 190039d9207SSean Christopherson 191039d9207SSean Christopherson /* 192*65096195SSean Christopherson * The theoretical maximum number of MCE banks is 32 (on Intel CPUs, 193*65096195SSean Christopherson * without jumping to a new base address), as the last unclaimed MSR is 194*65096195SSean Christopherson * 0x479; 0x480 begins the VMX MSRs. Verify accesses to theoretically 195*65096195SSean Christopherson * legal, unsupported MSRs fault. 196039d9207SSean Christopherson */ 197039d9207SSean Christopherson for (i = nr_mce_banks; i < 32; i++) { 198039d9207SSean Christopherson snprintf(msr_name, sizeof(msr_name), "MSR_IA32_MC%u_CTL", i); 199039d9207SSean Christopherson test_rdmsr_fault(MSR_IA32_MCx_CTL(i), msr_name); 200039d9207SSean Christopherson test_wrmsr_fault(MSR_IA32_MCx_CTL(i), msr_name, 0); 201039d9207SSean Christopherson 202039d9207SSean Christopherson snprintf(msr_name, sizeof(msr_name), "MSR_IA32_MC%u_STATUS", i); 203039d9207SSean Christopherson test_rdmsr_fault(MSR_IA32_MCx_STATUS(i), msr_name); 204039d9207SSean Christopherson test_wrmsr_fault(MSR_IA32_MCx_STATUS(i), msr_name, 0); 205039d9207SSean Christopherson 206039d9207SSean Christopherson snprintf(msr_name, sizeof(msr_name), "MSR_IA32_MC%u_ADDR", i); 207039d9207SSean Christopherson test_rdmsr_fault(MSR_IA32_MCx_ADDR(i), msr_name); 208039d9207SSean Christopherson test_wrmsr_fault(MSR_IA32_MCx_ADDR(i), msr_name, 0); 209039d9207SSean Christopherson 210039d9207SSean Christopherson snprintf(msr_name, sizeof(msr_name), "MSR_IA32_MC%u_MISC", i); 211039d9207SSean Christopherson test_rdmsr_fault(MSR_IA32_MCx_MISC(i), msr_name); 212039d9207SSean Christopherson test_wrmsr_fault(MSR_IA32_MCx_MISC(i), msr_name, 0); 213142ff635SSean Christopherson } 2145b4855b3SDaniele Ahmed } 2157d36db35SAvi Kivity 216*65096195SSean Christopherson int main(int ac, char **av) 217*65096195SSean Christopherson { 218*65096195SSean Christopherson /* 219*65096195SSean Christopherson * If the user provided an MSR+value, test exactly that and skip all 220*65096195SSean Christopherson * built-in testcases. 221*65096195SSean Christopherson */ 222*65096195SSean Christopherson if (ac == 3) { 223*65096195SSean Christopherson test_custom_msr(ac, av); 224*65096195SSean Christopherson } else { 225*65096195SSean Christopherson test_misc_msrs(); 226*65096195SSean Christopherson test_mce_msrs(); 227*65096195SSean Christopherson } 228*65096195SSean Christopherson 229f3cdd159SJan Kiszka return report_summary(); 2307d36db35SAvi Kivity } 231