17d36db35SAvi Kivity /* msr tests */ 27d36db35SAvi Kivity 37d36db35SAvi Kivity #include "libcflat.h" 4850479e3SJason Wang #include "processor.h" 5d1bdd07cSAvi Kivity #include "msr.h" 6*5b4855b3SDaniele Ahmed #include <stdlib.h> 7*5b4855b3SDaniele Ahmed 8*5b4855b3SDaniele Ahmed /** 9*5b4855b3SDaniele Ahmed * This test allows two modes: 10*5b4855b3SDaniele Ahmed * 1. Default: the `msr_info' array contains the default test configurations 11*5b4855b3SDaniele Ahmed * 2. Custom: by providing command line arguments it is possible to test any MSR and value 12*5b4855b3SDaniele Ahmed * Parameters order: 13*5b4855b3SDaniele Ahmed * 1. msr index as a base 16 number 14*5b4855b3SDaniele Ahmed * 2. value as a base 16 number 15*5b4855b3SDaniele 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; 227d36db35SAvi Kivity }; 237d36db35SAvi Kivity 247d36db35SAvi Kivity 257d36db35SAvi Kivity #define addr_64 0x0000123456789abcULL 268feb8cfbSSean Christopherson #define addr_ul (unsigned long)addr_64 277d36db35SAvi Kivity 28142ff635SSean Christopherson #define MSR_TEST(msr, val, only64) \ 29142ff635SSean Christopherson { .index = msr, .name = #msr, .value = val, .is_64bit_only = only64 } 3064662079SSean Christopherson 317d36db35SAvi Kivity struct msr_info msr_info[] = 327d36db35SAvi Kivity { 33142ff635SSean Christopherson MSR_TEST(MSR_IA32_SYSENTER_CS, 0x1234, false), 34142ff635SSean Christopherson MSR_TEST(MSR_IA32_SYSENTER_ESP, addr_ul, false), 35142ff635SSean Christopherson MSR_TEST(MSR_IA32_SYSENTER_EIP, addr_ul, false), 367d36db35SAvi Kivity // reserved: 1:2, 4:6, 8:10, 13:15, 17, 19:21, 24:33, 35:63 37142ff635SSean Christopherson MSR_TEST(MSR_IA32_MISC_ENABLE, 0x400c51889, false), 38142ff635SSean Christopherson MSR_TEST(MSR_IA32_CR_PAT, 0x07070707, false), 39142ff635SSean Christopherson MSR_TEST(MSR_FS_BASE, addr_64, true), 40142ff635SSean Christopherson MSR_TEST(MSR_GS_BASE, addr_64, true), 41142ff635SSean Christopherson MSR_TEST(MSR_KERNEL_GS_BASE, addr_64, true), 42dcae8d5fSSean Christopherson MSR_TEST(MSR_EFER, EFER_SCE, false), 43142ff635SSean Christopherson MSR_TEST(MSR_LSTAR, addr_64, true), 44142ff635SSean Christopherson MSR_TEST(MSR_CSTAR, addr_64, true), 45142ff635SSean Christopherson MSR_TEST(MSR_SYSCALL_MASK, 0xffffffff, true), 467d36db35SAvi Kivity // MSR_IA32_DEBUGCTLMSR needs svm feature LBRV 477d36db35SAvi Kivity // MSR_VM_HSAVE_PA only AMD host 487d36db35SAvi Kivity }; 497d36db35SAvi Kivity 503e788d91SSean Christopherson static void test_msr_rw(struct msr_info *msr, unsigned long long val) 517d36db35SAvi Kivity { 52a73d6ae4SSean Christopherson unsigned long long r, orig; 5350273266SSean Christopherson 543e788d91SSean Christopherson orig = rdmsr(msr->index); 55dcae8d5fSSean Christopherson /* 56dcae8d5fSSean Christopherson * Special case EFER since clearing LME/LMA is not allowed in 64-bit mode, 57dcae8d5fSSean Christopherson * and conversely setting those bits on 32-bit CPUs is not allowed. Treat 58dcae8d5fSSean Christopherson * the desired value as extra bits to set. 59dcae8d5fSSean Christopherson */ 60dcae8d5fSSean Christopherson if (msr->index == MSR_EFER) 61dcae8d5fSSean Christopherson val |= orig; 623e788d91SSean Christopherson wrmsr(msr->index, val); 633e788d91SSean Christopherson r = rdmsr(msr->index); 643e788d91SSean Christopherson wrmsr(msr->index, orig); 659295327cSSean Christopherson if (r != val) { 66d26193a0SRoman Bolshakov printf("testing %s: output = %#" PRIx32 ":%#" PRIx32 673e788d91SSean Christopherson " expected = %#" PRIx32 ":%#" PRIx32 "\n", msr->name, 689295327cSSean Christopherson (u32)(r >> 32), (u32)r, (u32)(val >> 32), (u32)val); 697d36db35SAvi Kivity } 703e788d91SSean Christopherson report(val == r, "%s", msr->name); 717d36db35SAvi Kivity } 727d36db35SAvi Kivity 73142ff635SSean Christopherson static void test_wrmsr_fault(struct msr_info *msr, unsigned long long val) 74142ff635SSean Christopherson { 75142ff635SSean Christopherson unsigned char vector = wrmsr_checking(msr->index, val); 76142ff635SSean Christopherson 77142ff635SSean Christopherson report(vector == GP_VECTOR, 78142ff635SSean Christopherson "Expected #GP on WRSMR(%s, 0x%llx), got vector %d", 79142ff635SSean Christopherson msr->name, val, vector); 80142ff635SSean Christopherson } 81142ff635SSean Christopherson 82142ff635SSean Christopherson static void test_rdmsr_fault(struct msr_info *msr) 83142ff635SSean Christopherson { 84142ff635SSean Christopherson unsigned char vector = rdmsr_checking(msr->index); 85142ff635SSean Christopherson 86142ff635SSean Christopherson report(vector == GP_VECTOR, 87142ff635SSean Christopherson "Expected #GP on RDSMR(%s), got vector %d", msr->name, vector); 88142ff635SSean Christopherson } 89142ff635SSean Christopherson 909e8ecb28SDaniele Ahmed static void test_msr(struct msr_info *msr, bool is_64bit_host) 919e8ecb28SDaniele Ahmed { 929e8ecb28SDaniele Ahmed if (is_64bit_host || !msr->is_64bit_only) { 939e8ecb28SDaniele Ahmed test_msr_rw(msr, msr->value); 949e8ecb28SDaniele Ahmed 959e8ecb28SDaniele Ahmed /* 969e8ecb28SDaniele Ahmed * The 64-bit only MSRs that take an address always perform 979e8ecb28SDaniele Ahmed * canonical checks on both Intel and AMD. 989e8ecb28SDaniele Ahmed */ 999e8ecb28SDaniele Ahmed if (msr->is_64bit_only && 1009e8ecb28SDaniele Ahmed msr->value == addr_64) 1019e8ecb28SDaniele Ahmed test_wrmsr_fault(msr, NONCANONICAL); 1029e8ecb28SDaniele Ahmed } else { 1039e8ecb28SDaniele Ahmed test_wrmsr_fault(msr, msr->value); 1049e8ecb28SDaniele Ahmed test_rdmsr_fault(msr); 1059e8ecb28SDaniele Ahmed } 1069e8ecb28SDaniele Ahmed } 1079e8ecb28SDaniele Ahmed 1087d36db35SAvi Kivity int main(int ac, char **av) 1097d36db35SAvi Kivity { 110142ff635SSean Christopherson bool is_64bit_host = this_cpu_has(X86_FEATURE_LM); 11164662079SSean Christopherson int i; 11264662079SSean Christopherson 113*5b4855b3SDaniele Ahmed if (ac == 3) { 114*5b4855b3SDaniele Ahmed char msr_name[16]; 115*5b4855b3SDaniele Ahmed int index = strtoul(av[1], NULL, 0x10); 116*5b4855b3SDaniele Ahmed snprintf(msr_name, sizeof(msr_name), "MSR:0x%x", index); 117*5b4855b3SDaniele Ahmed 118*5b4855b3SDaniele Ahmed struct msr_info msr = { 119*5b4855b3SDaniele Ahmed .index = index, 120*5b4855b3SDaniele Ahmed .name = msr_name, 121*5b4855b3SDaniele Ahmed .value = strtoull(av[2], NULL, 0x10) 122*5b4855b3SDaniele Ahmed }; 123*5b4855b3SDaniele Ahmed test_msr(&msr, is_64bit_host); 124*5b4855b3SDaniele Ahmed } else { 125142ff635SSean Christopherson for (i = 0 ; i < ARRAY_SIZE(msr_info); i++) { 1269e8ecb28SDaniele Ahmed test_msr(&msr_info[i], is_64bit_host); 127142ff635SSean Christopherson } 128*5b4855b3SDaniele Ahmed } 1297d36db35SAvi Kivity 130f3cdd159SJan Kiszka return report_summary(); 1317d36db35SAvi Kivity } 132