Skip the built-in MSR testcases if the user provides a custom MSR+value to test. If the user is asking to test a specific MSR+value, they likely don't want to wait for the test to burn though a pile of MCE MSRs. Fixes: 039d9207 ("x86: msr: Add tests for MCE bank MSRs") Signed-off-by: Sean Christopherson <seanjc@xxxxxxxxxx> --- x86/msr.c | 170 ++++++++++++++++++++++++++++++------------------------ 1 file changed, 96 insertions(+), 74 deletions(-) diff --git a/x86/msr.c b/x86/msr.c index 69e81475..f97f0c51 100644 --- a/x86/msr.c +++ b/x86/msr.c @@ -120,88 +120,110 @@ static void test_msr(struct msr_info *msr, bool is_64bit_host) } } -int main(int ac, char **av) +static void test_custom_msr(int ac, char **av) +{ + bool is_64bit_host = this_cpu_has(X86_FEATURE_LM); + char msr_name[32]; + int index = strtoul(av[1], NULL, 0x10); + snprintf(msr_name, sizeof(msr_name), "MSR:0x%x", index); + + struct msr_info msr = { + .index = index, + .name = msr_name, + .value = strtoull(av[2], NULL, 0x10) + }; + test_msr(&msr, is_64bit_host); +} + +static void test_misc_msrs(void) +{ + bool is_64bit_host = this_cpu_has(X86_FEATURE_LM); + int i; + + for (i = 0 ; i < ARRAY_SIZE(msr_info); i++) + test_msr(&msr_info[i], is_64bit_host); +} + +static void test_mce_msrs(void) { bool is_64bit_host = this_cpu_has(X86_FEATURE_LM); unsigned int nr_mce_banks; char msr_name[32]; int i; + nr_mce_banks = rdmsr(MSR_IA32_MCG_CAP) & 0xff; + for (i = 0; i < nr_mce_banks; i++) { + snprintf(msr_name, sizeof(msr_name), "MSR_IA32_MC%u_CTL", i); + test_msr_rw(MSR_IA32_MCx_CTL(i), msr_name, 0); + test_msr_rw(MSR_IA32_MCx_CTL(i), msr_name, -1ull); + test_wrmsr_fault(MSR_IA32_MCx_CTL(i), msr_name, NONCANONICAL); + + snprintf(msr_name, sizeof(msr_name), "MSR_IA32_MC%u_STATUS", i); + test_msr_rw(MSR_IA32_MCx_STATUS(i), msr_name, 0); + /* + * STATUS MSRs can only be written with '0' (to clear the MSR), + * except on AMD-based systems with bit 18 set in MSR_K7_HWCR. + * That bit is not architectural and should not be set by + * default by KVM or by the VMM (though this might fail if run + * on bare metal). + */ + test_wrmsr_fault(MSR_IA32_MCx_STATUS(i), msr_name, 1); + + snprintf(msr_name, sizeof(msr_name), "MSR_IA32_MC%u_ADDR", i); + test_msr_rw(MSR_IA32_MCx_ADDR(i), msr_name, 0); + test_msr_rw(MSR_IA32_MCx_ADDR(i), msr_name, -1ull); + /* + * The ADDR is a physical address, and all bits are writable on + * 64-bit hosts. Don't test the negative case, as KVM doesn't + * enforce checks on bits 63:36 for 32-bit hosts. The behavior + * depends on the underlying hardware, e.g. a 32-bit guest on a + * 64-bit host may observe 64-bit values in the ADDR MSRs. + */ + if (is_64bit_host) + test_msr_rw(MSR_IA32_MCx_ADDR(i), msr_name, NONCANONICAL); + + snprintf(msr_name, sizeof(msr_name), "MSR_IA32_MC%u_MISC", i); + test_msr_rw(MSR_IA32_MCx_MISC(i), msr_name, 0); + test_msr_rw(MSR_IA32_MCx_MISC(i), msr_name, -1ull); + test_msr_rw(MSR_IA32_MCx_MISC(i), msr_name, NONCANONICAL); + } + + /* + * The theoretical maximum number of MCE banks is 32 (on Intel CPUs, + * without jumping to a new base address), as the last unclaimed MSR is + * 0x479; 0x480 begins the VMX MSRs. Verify accesses to theoretically + * legal, unsupported MSRs fault. + */ + for (i = nr_mce_banks; i < 32; i++) { + snprintf(msr_name, sizeof(msr_name), "MSR_IA32_MC%u_CTL", i); + test_rdmsr_fault(MSR_IA32_MCx_CTL(i), msr_name); + test_wrmsr_fault(MSR_IA32_MCx_CTL(i), msr_name, 0); + + snprintf(msr_name, sizeof(msr_name), "MSR_IA32_MC%u_STATUS", i); + test_rdmsr_fault(MSR_IA32_MCx_STATUS(i), msr_name); + test_wrmsr_fault(MSR_IA32_MCx_STATUS(i), msr_name, 0); + + snprintf(msr_name, sizeof(msr_name), "MSR_IA32_MC%u_ADDR", i); + test_rdmsr_fault(MSR_IA32_MCx_ADDR(i), msr_name); + test_wrmsr_fault(MSR_IA32_MCx_ADDR(i), msr_name, 0); + + snprintf(msr_name, sizeof(msr_name), "MSR_IA32_MC%u_MISC", i); + test_rdmsr_fault(MSR_IA32_MCx_MISC(i), msr_name); + test_wrmsr_fault(MSR_IA32_MCx_MISC(i), msr_name, 0); + } +} + +int main(int ac, char **av) +{ + /* + * If the user provided an MSR+value, test exactly that and skip all + * built-in testcases. + */ if (ac == 3) { - int index = strtoul(av[1], NULL, 0x10); - snprintf(msr_name, sizeof(msr_name), "MSR:0x%x", index); - - struct msr_info msr = { - .index = index, - .name = msr_name, - .value = strtoull(av[2], NULL, 0x10) - }; - test_msr(&msr, is_64bit_host); + test_custom_msr(ac, av); } else { - for (i = 0 ; i < ARRAY_SIZE(msr_info); i++) - test_msr(&msr_info[i], is_64bit_host); - - nr_mce_banks = rdmsr(MSR_IA32_MCG_CAP) & 0xff; - for (i = 0; i < nr_mce_banks; i++) { - snprintf(msr_name, sizeof(msr_name), "MSR_IA32_MC%u_CTL", i); - test_msr_rw(MSR_IA32_MCx_CTL(i), msr_name, 0); - test_msr_rw(MSR_IA32_MCx_CTL(i), msr_name, -1ull); - test_wrmsr_fault(MSR_IA32_MCx_CTL(i), msr_name, NONCANONICAL); - - snprintf(msr_name, sizeof(msr_name), "MSR_IA32_MC%u_STATUS", i); - test_msr_rw(MSR_IA32_MCx_STATUS(i), msr_name, 0); - /* - * STATUS MSRs can only be written with '0' (to clear - * the MSR), except on AMD-based systems with bit 18 - * set in MSR_K7_HWCR. That bit is not architectural - * and should not be set by default by KVM or by the - * VMM (though this might fail if run on bare metal). - */ - test_wrmsr_fault(MSR_IA32_MCx_STATUS(i), msr_name, 1); - - snprintf(msr_name, sizeof(msr_name), "MSR_IA32_MC%u_ADDR", i); - test_msr_rw(MSR_IA32_MCx_ADDR(i), msr_name, 0); - test_msr_rw(MSR_IA32_MCx_ADDR(i), msr_name, -1ull); - /* - * The ADDR is a physical address, and all bits are - * writable on 64-bit hosts. Don't test the negative - * case, as KVM doesn't enforce checks on bits 63:36 - * for 32-bit hosts. The behavior depends on the - * underlying hardware, e.g. a 32-bit guest on a 64-bit - * host may observe 64-bit values in the ADDR MSRs. - */ - if (is_64bit_host) - test_msr_rw(MSR_IA32_MCx_ADDR(i), msr_name, NONCANONICAL); - - snprintf(msr_name, sizeof(msr_name), "MSR_IA32_MC%u_MISC", i); - test_msr_rw(MSR_IA32_MCx_MISC(i), msr_name, 0); - test_msr_rw(MSR_IA32_MCx_MISC(i), msr_name, -1ull); - test_msr_rw(MSR_IA32_MCx_MISC(i), msr_name, NONCANONICAL); - } - - /* - * The theoretical maximum number of MCE banks is 32 (on Intel - * CPUs, without jumping to a new base address), as the last - * unclaimed MSR is 0x479; 0x480 begins the VMX MSRs. Verify - * accesses to theoretically legal, unsupported MSRs fault. - */ - for (i = nr_mce_banks; i < 32; i++) { - snprintf(msr_name, sizeof(msr_name), "MSR_IA32_MC%u_CTL", i); - test_rdmsr_fault(MSR_IA32_MCx_CTL(i), msr_name); - test_wrmsr_fault(MSR_IA32_MCx_CTL(i), msr_name, 0); - - snprintf(msr_name, sizeof(msr_name), "MSR_IA32_MC%u_STATUS", i); - test_rdmsr_fault(MSR_IA32_MCx_STATUS(i), msr_name); - test_wrmsr_fault(MSR_IA32_MCx_STATUS(i), msr_name, 0); - - snprintf(msr_name, sizeof(msr_name), "MSR_IA32_MC%u_ADDR", i); - test_rdmsr_fault(MSR_IA32_MCx_ADDR(i), msr_name); - test_wrmsr_fault(MSR_IA32_MCx_ADDR(i), msr_name, 0); - - snprintf(msr_name, sizeof(msr_name), "MSR_IA32_MC%u_MISC", i); - test_rdmsr_fault(MSR_IA32_MCx_MISC(i), msr_name); - test_wrmsr_fault(MSR_IA32_MCx_MISC(i), msr_name, 0); - } + test_misc_msrs(); + test_mce_msrs(); } return report_summary(); -- 2.39.0.314.g84b9a713c41-goog