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; 9142ff635SSean Christopherson bool is_64bit_only; 10797d79a2SThomas Huth const char *name; 117d36db35SAvi Kivity unsigned long long value; 127d36db35SAvi Kivity }; 137d36db35SAvi Kivity 147d36db35SAvi Kivity 157d36db35SAvi Kivity #define addr_64 0x0000123456789abcULL 168feb8cfbSSean Christopherson #define addr_ul (unsigned long)addr_64 177d36db35SAvi Kivity 18142ff635SSean Christopherson #define MSR_TEST(msr, val, only64) \ 19142ff635SSean Christopherson { .index = msr, .name = #msr, .value = val, .is_64bit_only = only64 } 2064662079SSean Christopherson 217d36db35SAvi Kivity struct msr_info msr_info[] = 227d36db35SAvi Kivity { 23142ff635SSean Christopherson MSR_TEST(MSR_IA32_SYSENTER_CS, 0x1234, false), 24142ff635SSean Christopherson MSR_TEST(MSR_IA32_SYSENTER_ESP, addr_ul, false), 25142ff635SSean Christopherson MSR_TEST(MSR_IA32_SYSENTER_EIP, addr_ul, false), 267d36db35SAvi Kivity // reserved: 1:2, 4:6, 8:10, 13:15, 17, 19:21, 24:33, 35:63 27142ff635SSean Christopherson MSR_TEST(MSR_IA32_MISC_ENABLE, 0x400c51889, false), 28142ff635SSean Christopherson MSR_TEST(MSR_IA32_CR_PAT, 0x07070707, false), 29142ff635SSean Christopherson MSR_TEST(MSR_FS_BASE, addr_64, true), 30142ff635SSean Christopherson MSR_TEST(MSR_GS_BASE, addr_64, true), 31142ff635SSean Christopherson MSR_TEST(MSR_KERNEL_GS_BASE, addr_64, true), 32*dcae8d5fSSean Christopherson MSR_TEST(MSR_EFER, EFER_SCE, false), 33142ff635SSean Christopherson MSR_TEST(MSR_LSTAR, addr_64, true), 34142ff635SSean Christopherson MSR_TEST(MSR_CSTAR, addr_64, true), 35142ff635SSean Christopherson MSR_TEST(MSR_SYSCALL_MASK, 0xffffffff, true), 367d36db35SAvi Kivity // MSR_IA32_DEBUGCTLMSR needs svm feature LBRV 377d36db35SAvi Kivity // MSR_VM_HSAVE_PA only AMD host 387d36db35SAvi Kivity }; 397d36db35SAvi Kivity 403e788d91SSean Christopherson static void test_msr_rw(struct msr_info *msr, unsigned long long val) 417d36db35SAvi Kivity { 42a73d6ae4SSean Christopherson unsigned long long r, orig; 4350273266SSean Christopherson 443e788d91SSean Christopherson orig = rdmsr(msr->index); 45*dcae8d5fSSean Christopherson /* 46*dcae8d5fSSean Christopherson * Special case EFER since clearing LME/LMA is not allowed in 64-bit mode, 47*dcae8d5fSSean Christopherson * and conversely setting those bits on 32-bit CPUs is not allowed. Treat 48*dcae8d5fSSean Christopherson * the desired value as extra bits to set. 49*dcae8d5fSSean Christopherson */ 50*dcae8d5fSSean Christopherson if (msr->index == MSR_EFER) 51*dcae8d5fSSean Christopherson val |= orig; 523e788d91SSean Christopherson wrmsr(msr->index, val); 533e788d91SSean Christopherson r = rdmsr(msr->index); 543e788d91SSean Christopherson wrmsr(msr->index, orig); 559295327cSSean Christopherson if (r != val) { 56d26193a0SRoman Bolshakov printf("testing %s: output = %#" PRIx32 ":%#" PRIx32 573e788d91SSean Christopherson " expected = %#" PRIx32 ":%#" PRIx32 "\n", msr->name, 589295327cSSean Christopherson (u32)(r >> 32), (u32)r, (u32)(val >> 32), (u32)val); 597d36db35SAvi Kivity } 603e788d91SSean Christopherson report(val == r, "%s", msr->name); 617d36db35SAvi Kivity } 627d36db35SAvi Kivity 63142ff635SSean Christopherson static void test_wrmsr_fault(struct msr_info *msr, unsigned long long val) 64142ff635SSean Christopherson { 65142ff635SSean Christopherson unsigned char vector = wrmsr_checking(msr->index, val); 66142ff635SSean Christopherson 67142ff635SSean Christopherson report(vector == GP_VECTOR, 68142ff635SSean Christopherson "Expected #GP on WRSMR(%s, 0x%llx), got vector %d", 69142ff635SSean Christopherson msr->name, val, vector); 70142ff635SSean Christopherson } 71142ff635SSean Christopherson 72142ff635SSean Christopherson static void test_rdmsr_fault(struct msr_info *msr) 73142ff635SSean Christopherson { 74142ff635SSean Christopherson unsigned char vector = rdmsr_checking(msr->index); 75142ff635SSean Christopherson 76142ff635SSean Christopherson report(vector == GP_VECTOR, 77142ff635SSean Christopherson "Expected #GP on RDSMR(%s), got vector %d", msr->name, vector); 78142ff635SSean Christopherson } 79142ff635SSean Christopherson 807d36db35SAvi Kivity int main(int ac, char **av) 817d36db35SAvi Kivity { 82142ff635SSean Christopherson bool is_64bit_host = this_cpu_has(X86_FEATURE_LM); 8364662079SSean Christopherson int i; 8464662079SSean Christopherson 85142ff635SSean Christopherson for (i = 0 ; i < ARRAY_SIZE(msr_info); i++) { 86142ff635SSean Christopherson if (is_64bit_host || !msr_info[i].is_64bit_only) { 873e788d91SSean Christopherson test_msr_rw(&msr_info[i], msr_info[i].value); 8888f0bb17SSean Christopherson 8988f0bb17SSean Christopherson /* 9088f0bb17SSean Christopherson * The 64-bit only MSRs that take an address always perform 9188f0bb17SSean Christopherson * canonical checks on both Intel and AMD. 9288f0bb17SSean Christopherson */ 9388f0bb17SSean Christopherson if (msr_info[i].is_64bit_only && 9488f0bb17SSean Christopherson msr_info[i].value == addr_64) 9588f0bb17SSean Christopherson test_wrmsr_fault(&msr_info[i], NONCANONICAL); 96142ff635SSean Christopherson } else { 97142ff635SSean Christopherson test_wrmsr_fault(&msr_info[i], msr_info[i].value); 98142ff635SSean Christopherson test_rdmsr_fault(&msr_info[i]); 99142ff635SSean Christopherson } 100142ff635SSean Christopherson } 1017d36db35SAvi Kivity 102f3cdd159SJan Kiszka return report_summary(); 1037d36db35SAvi Kivity } 104