// SPDX-License-Identifier: GPL-2.0-only #include #include #include "kvm_util.h" #include "processor.h" /* Use HYPERVISOR for MSRs that are emulated unconditionally (as is HYPERVISOR). */ #define X86_FEATURE_NONE X86_FEATURE_HYPERVISOR struct kvm_msr { const struct kvm_x86_cpu_feature feature; const struct kvm_x86_cpu_feature feature2; const char *name; const u64 reset_val; const u64 write_val; const u64 rsvd_val; const u32 index; const bool is_kvm_defined; }; #define ____MSR_TEST(msr, str, val, rsvd, reset, feat, f2, is_kvm) \ { \ .index = msr, \ .name = str, \ .write_val = val, \ .rsvd_val = rsvd, \ .reset_val = reset, \ .feature = X86_FEATURE_ ##feat, \ .feature2 = X86_FEATURE_ ##f2, \ .is_kvm_defined = is_kvm, \ } #define __MSR_TEST(msr, str, val, rsvd, reset, feat) \ ____MSR_TEST(msr, str, val, rsvd, reset, feat, feat, false) #define MSR_TEST_NON_ZERO(msr, val, rsvd, reset, feat) \ __MSR_TEST(msr, #msr, val, rsvd, reset, feat) #define MSR_TEST(msr, val, rsvd, feat) \ __MSR_TEST(msr, #msr, val, rsvd, 0, feat) #define MSR_TEST2(msr, val, rsvd, feat, f2) \ ____MSR_TEST(msr, #msr, val, rsvd, 0, feat, f2, false) /* * Note, use a page aligned value for the canonical value so that the value * is compatible with MSRs that use bits 11:0 for things other than addresses. */ static const u64 canonical_val = 0x123456789000ull; /* * Arbitrary value with bits set in every byte, but not all bits set. This is * also a non-canonical value, but that's coincidental (any 64-bit value with * an alternating 0s/1s pattern will be non-canonical). */ static const u64 u64_val = 0xaaaa5555aaaa5555ull; #define MSR_TEST_CANONICAL(msr, feat) \ __MSR_TEST(msr, #msr, canonical_val, NONCANONICAL, 0, feat) #define MSR_TEST_KVM(msr, val, rsvd, feat) \ ____MSR_TEST(KVM_REG_ ##msr, #msr, val, rsvd, 0, feat, feat, true) /* * The main struct must be scoped to a function due to the use of structures to * define features. For the global structure, allocate enough space for the * foreseeable future without getting too ridiculous, to minimize maintenance * costs (bumping the array size every time an MSR is added is really annoying). */ static struct kvm_msr msrs[128]; static int idx; static bool ignore_unsupported_msrs; static u64 fixup_rdmsr_val(u32 msr, u64 want) { /* * AMD CPUs drop bits 63:32 on some MSRs that Intel CPUs support. KVM * is supposed to emulate that behavior based on guest vendor model * (which is the same as the host vendor model for this test). */ if (!host_cpu_is_amd) return want; switch (msr) { case MSR_IA32_SYSENTER_ESP: case MSR_IA32_SYSENTER_EIP: case MSR_TSC_AUX: return want & GENMASK_ULL(31, 0); default: return want; } } static void __rdmsr(u32 msr, u64 want) { u64 val; u8 vec; vec = rdmsr_safe(msr, &val); __GUEST_ASSERT(!vec, "Unexpected %s on RDMSR(0x%x)", ex_str(vec), msr); __GUEST_ASSERT(val == want, "Wanted 0x%lx from RDMSR(0x%x), got 0x%lx", want, msr, val); } static void __wrmsr(u32 msr, u64 val) { u8 vec; vec = wrmsr_safe(msr, val); __GUEST_ASSERT(!vec, "Unexpected %s on WRMSR(0x%x, 0x%lx)", ex_str(vec), msr, val); __rdmsr(msr, fixup_rdmsr_val(msr, val)); } static void guest_test_supported_msr(const struct kvm_msr *msr) { __rdmsr(msr->index, msr->reset_val); __wrmsr(msr->index, msr->write_val); GUEST_SYNC(fixup_rdmsr_val(msr->index, msr->write_val)); __rdmsr(msr->index, msr->reset_val); } static void guest_test_unsupported_msr(const struct kvm_msr *msr) { u64 val; u8 vec; /* * KVM's ABI with respect to ignore_msrs is a mess and largely beyond * repair, just skip the unsupported MSR tests. */ if (ignore_unsupported_msrs) goto skip_wrmsr_gp; /* * {S,U}_CET exist if IBT or SHSTK is supported, but with bits that are * writable only if their associated feature is supported. Skip the * RDMSR #GP test if the secondary feature is supported, but perform * the WRMSR #GP test as the to-be-written value is tied to the primary * feature. For all other MSRs, simply do nothing. */ if (this_cpu_has(msr->feature2)) { if (msr->index != MSR_IA32_U_CET && msr->index != MSR_IA32_S_CET) goto skip_wrmsr_gp; goto skip_rdmsr_gp; } vec = rdmsr_safe(msr->index, &val); __GUEST_ASSERT(vec == GP_VECTOR, "Wanted #GP on RDMSR(0x%x), got %s", msr->index, ex_str(vec)); skip_rdmsr_gp: vec = wrmsr_safe(msr->index, msr->write_val); __GUEST_ASSERT(vec == GP_VECTOR, "Wanted #GP on WRMSR(0x%x, 0x%lx), got %s", msr->index, msr->write_val, ex_str(vec)); skip_wrmsr_gp: GUEST_SYNC(0); } void guest_test_reserved_val(const struct kvm_msr *msr) { /* Skip reserved value checks as well, ignore_msrs is trully a mess. */ if (ignore_unsupported_msrs) return; /* * If the CPU will truncate the written value (e.g. SYSENTER on AMD), * expect success and a truncated value, not #GP. */ if (!this_cpu_has(msr->feature) || msr->rsvd_val == fixup_rdmsr_val(msr->index, msr->rsvd_val)) { u8 vec = wrmsr_safe(msr->index, msr->rsvd_val); __GUEST_ASSERT(vec == GP_VECTOR, "Wanted #GP on WRMSR(0x%x, 0x%lx), got %s", msr->index, msr->rsvd_val, ex_str(vec)); } else { __wrmsr(msr->index, msr->rsvd_val); __wrmsr(msr->index, msr->reset_val); } } static void guest_main(void) { for (;;) { const struct kvm_msr *msr = &msrs[READ_ONCE(idx)]; if (this_cpu_has(msr->feature)) guest_test_supported_msr(msr); else guest_test_unsupported_msr(msr); if (msr->rsvd_val) guest_test_reserved_val(msr); GUEST_SYNC(msr->reset_val); } } static bool has_one_reg; static bool use_one_reg; #define KVM_X86_MAX_NR_REGS 1 static bool vcpu_has_reg(struct kvm_vcpu *vcpu, u64 reg) { struct { struct kvm_reg_list list; u64 regs[KVM_X86_MAX_NR_REGS]; } regs = {}; int r, i; /* * If KVM_GET_REG_LIST succeeds with n=0, i.e. there are no supported * regs, then the vCPU obviously doesn't support the reg. */ r = __vcpu_ioctl(vcpu, KVM_GET_REG_LIST, ®s.list); if (!r) return false; TEST_ASSERT_EQ(errno, E2BIG); /* * KVM x86 is expected to support enumerating a relative small number * of regs. The majority of registers supported by KVM_{G,S}ET_ONE_REG * are enumerated via other ioctls, e.g. KVM_GET_MSR_INDEX_LIST. For * simplicity, hardcode the maximum number of regs and manually update * the test as necessary. */ TEST_ASSERT(regs.list.n <= KVM_X86_MAX_NR_REGS, "KVM reports %llu regs, test expects at most %u regs, stale test?", regs.list.n, KVM_X86_MAX_NR_REGS); vcpu_ioctl(vcpu, KVM_GET_REG_LIST, ®s.list); for (i = 0; i < regs.list.n; i++) { if (regs.regs[i] == reg) return true; } return false; } static void host_test_kvm_reg(struct kvm_vcpu *vcpu) { bool has_reg = vcpu_cpuid_has(vcpu, msrs[idx].feature); u64 reset_val = msrs[idx].reset_val; u64 write_val = msrs[idx].write_val; u64 rsvd_val = msrs[idx].rsvd_val; u32 reg = msrs[idx].index; u64 val; int r; if (!use_one_reg) return; TEST_ASSERT_EQ(vcpu_has_reg(vcpu, KVM_X86_REG_KVM(reg)), has_reg); if (!has_reg) { r = __vcpu_get_reg(vcpu, KVM_X86_REG_KVM(reg), &val); TEST_ASSERT(r && errno == EINVAL, "Expected failure on get_reg(0x%x)", reg); rsvd_val = 0; goto out; } val = vcpu_get_reg(vcpu, KVM_X86_REG_KVM(reg)); TEST_ASSERT(val == reset_val, "Wanted 0x%lx from get_reg(0x%x), got 0x%lx", reset_val, reg, val); vcpu_set_reg(vcpu, KVM_X86_REG_KVM(reg), write_val); val = vcpu_get_reg(vcpu, KVM_X86_REG_KVM(reg)); TEST_ASSERT(val == write_val, "Wanted 0x%lx from get_reg(0x%x), got 0x%lx", write_val, reg, val); out: r = __vcpu_set_reg(vcpu, KVM_X86_REG_KVM(reg), rsvd_val); TEST_ASSERT(r, "Expected failure on set_reg(0x%x, 0x%lx)", reg, rsvd_val); } static void host_test_msr(struct kvm_vcpu *vcpu, u64 guest_val) { u64 reset_val = msrs[idx].reset_val; u32 msr = msrs[idx].index; u64 val; if (!kvm_cpu_has(msrs[idx].feature)) return; val = vcpu_get_msr(vcpu, msr); TEST_ASSERT(val == guest_val, "Wanted 0x%lx from get_msr(0x%x), got 0x%lx", guest_val, msr, val); if (use_one_reg) vcpu_set_reg(vcpu, KVM_X86_REG_MSR(msr), reset_val); else vcpu_set_msr(vcpu, msr, reset_val); val = vcpu_get_msr(vcpu, msr); TEST_ASSERT(val == reset_val, "Wanted 0x%lx from get_msr(0x%x), got 0x%lx", reset_val, msr, val); if (!has_one_reg) return; val = vcpu_get_reg(vcpu, KVM_X86_REG_MSR(msr)); TEST_ASSERT(val == reset_val, "Wanted 0x%lx from get_reg(0x%x), got 0x%lx", reset_val, msr, val); } static void do_vcpu_run(struct kvm_vcpu *vcpu) { struct ucall uc; for (;;) { vcpu_run(vcpu); switch (get_ucall(vcpu, &uc)) { case UCALL_SYNC: host_test_msr(vcpu, uc.args[1]); return; case UCALL_PRINTF: pr_info("%s", uc.buffer); break; case UCALL_ABORT: REPORT_GUEST_ASSERT(uc); case UCALL_DONE: TEST_FAIL("Unexpected UCALL_DONE"); default: TEST_FAIL("Unexpected ucall: %lu", uc.cmd); } } } static void vcpus_run(struct kvm_vcpu **vcpus, const int NR_VCPUS) { int i; for (i = 0; i < NR_VCPUS; i++) do_vcpu_run(vcpus[i]); } #define MISC_ENABLES_RESET_VAL (MSR_IA32_MISC_ENABLE_PEBS_UNAVAIL | MSR_IA32_MISC_ENABLE_BTS_UNAVAIL) static void test_msrs(void) { const struct kvm_msr __msrs[] = { MSR_TEST_NON_ZERO(MSR_IA32_MISC_ENABLE, MISC_ENABLES_RESET_VAL | MSR_IA32_MISC_ENABLE_FAST_STRING, MSR_IA32_MISC_ENABLE_FAST_STRING, MISC_ENABLES_RESET_VAL, NONE), MSR_TEST_NON_ZERO(MSR_IA32_CR_PAT, 0x07070707, 0, 0x7040600070406, NONE), /* * TSC_AUX is supported if RDTSCP *or* RDPID is supported. Add * entries for each features so that TSC_AUX doesn't exists for * the "unsupported" vCPU, and obviously to test both cases. */ MSR_TEST2(MSR_TSC_AUX, 0x12345678, u64_val, RDTSCP, RDPID), MSR_TEST2(MSR_TSC_AUX, 0x12345678, u64_val, RDPID, RDTSCP), MSR_TEST(MSR_IA32_SYSENTER_CS, 0x1234, 0, NONE), /* * SYSENTER_{ESP,EIP} are technically non-canonical on Intel, * but KVM doesn't emulate that behavior on emulated writes, * i.e. this test will observe different behavior if the MSR * writes are handed by hardware vs. KVM. KVM's behavior is * intended (though far from ideal), so don't bother testing * non-canonical values. */ MSR_TEST(MSR_IA32_SYSENTER_ESP, canonical_val, 0, NONE), MSR_TEST(MSR_IA32_SYSENTER_EIP, canonical_val, 0, NONE), MSR_TEST_CANONICAL(MSR_FS_BASE, LM), MSR_TEST_CANONICAL(MSR_GS_BASE, LM), MSR_TEST_CANONICAL(MSR_KERNEL_GS_BASE, LM), MSR_TEST_CANONICAL(MSR_LSTAR, LM), MSR_TEST_CANONICAL(MSR_CSTAR, LM), MSR_TEST(MSR_SYSCALL_MASK, 0xffffffff, 0, LM), MSR_TEST2(MSR_IA32_S_CET, CET_SHSTK_EN, CET_RESERVED, SHSTK, IBT), MSR_TEST2(MSR_IA32_S_CET, CET_ENDBR_EN, CET_RESERVED, IBT, SHSTK), MSR_TEST2(MSR_IA32_U_CET, CET_SHSTK_EN, CET_RESERVED, SHSTK, IBT), MSR_TEST2(MSR_IA32_U_CET, CET_ENDBR_EN, CET_RESERVED, IBT, SHSTK), MSR_TEST_CANONICAL(MSR_IA32_PL0_SSP, SHSTK), MSR_TEST(MSR_IA32_PL0_SSP, canonical_val, canonical_val | 1, SHSTK), MSR_TEST_CANONICAL(MSR_IA32_PL1_SSP, SHSTK), MSR_TEST(MSR_IA32_PL1_SSP, canonical_val, canonical_val | 1, SHSTK), MSR_TEST_CANONICAL(MSR_IA32_PL2_SSP, SHSTK), MSR_TEST(MSR_IA32_PL2_SSP, canonical_val, canonical_val | 1, SHSTK), MSR_TEST_CANONICAL(MSR_IA32_PL3_SSP, SHSTK), MSR_TEST(MSR_IA32_PL3_SSP, canonical_val, canonical_val | 1, SHSTK), MSR_TEST_KVM(GUEST_SSP, canonical_val, NONCANONICAL, SHSTK), }; const struct kvm_x86_cpu_feature feat_none = X86_FEATURE_NONE; const struct kvm_x86_cpu_feature feat_lm = X86_FEATURE_LM; /* * Create three vCPUs, but run them on the same task, to validate KVM's * context switching of MSR state. Don't pin the task to a pCPU to * also validate KVM's handling of cross-pCPU migration. Use the full * set of features for the first two vCPUs, but clear all features in * third vCPU in order to test both positive and negative paths. */ const int NR_VCPUS = 3; struct kvm_vcpu *vcpus[NR_VCPUS]; struct kvm_vm *vm; int i; kvm_static_assert(sizeof(__msrs) <= sizeof(msrs)); kvm_static_assert(ARRAY_SIZE(__msrs) <= ARRAY_SIZE(msrs)); memcpy(msrs, __msrs, sizeof(__msrs)); ignore_unsupported_msrs = kvm_is_ignore_msrs(); vm = vm_create_with_vcpus(NR_VCPUS, guest_main, vcpus); sync_global_to_guest(vm, msrs); sync_global_to_guest(vm, ignore_unsupported_msrs); /* * Clear features in the "unsupported features" vCPU. This needs to be * done before the first vCPU run as KVM's ABI is that guest CPUID is * immutable once the vCPU has been run. */ for (idx = 0; idx < ARRAY_SIZE(__msrs); idx++) { /* * Don't clear LM; selftests are 64-bit only, and KVM doesn't * honor LM=0 for MSRs that are supposed to exist if and only * if the vCPU is a 64-bit model. Ditto for NONE; clearing a * fake feature flag will result in false failures. */ if (memcmp(&msrs[idx].feature, &feat_lm, sizeof(feat_lm)) && memcmp(&msrs[idx].feature, &feat_none, sizeof(feat_none))) vcpu_clear_cpuid_feature(vcpus[2], msrs[idx].feature); } for (idx = 0; idx < ARRAY_SIZE(__msrs); idx++) { struct kvm_msr *msr = &msrs[idx]; if (msr->is_kvm_defined) { for (i = 0; i < NR_VCPUS; i++) host_test_kvm_reg(vcpus[i]); continue; } /* * Verify KVM_GET_SUPPORTED_CPUID and KVM_GET_MSR_INDEX_LIST * are consistent with respect to MSRs whose existence is * enumerated via CPUID. Skip the check for FS/GS.base MSRs, * as they aren't reported in the save/restore list since their * state is managed via SREGS. */ TEST_ASSERT(msr->index == MSR_FS_BASE || msr->index == MSR_GS_BASE || kvm_msr_is_in_save_restore_list(msr->index) == (kvm_cpu_has(msr->feature) || kvm_cpu_has(msr->feature2)), "%s %s in save/restore list, but %s according to CPUID", msr->name, kvm_msr_is_in_save_restore_list(msr->index) ? "is" : "isn't", (kvm_cpu_has(msr->feature) || kvm_cpu_has(msr->feature2)) ? "supported" : "unsupported"); sync_global_to_guest(vm, idx); vcpus_run(vcpus, NR_VCPUS); vcpus_run(vcpus, NR_VCPUS); } kvm_vm_free(vm); } int main(void) { has_one_reg = kvm_has_cap(KVM_CAP_ONE_REG); test_msrs(); if (has_one_reg) { use_one_reg = true; test_msrs(); } }