Skip to content

Commit 0581dfb

Browse files
committed
KVM: selftests: Add a testcase for disabling feature MSRs init quirk
Expand and rename the feature MSRs test to verify KVM's ABI and quirk for initializing feature MSRs. Exempt VM_CR{0,4}_FIXED1 from most tests as KVM intentionally takes full control of the MSRs, e.g. to prevent L1 from running L2 with bogus CR0 and/or CR4 values. Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Sean Christopherson <[email protected]>
1 parent b799e3e commit 0581dfb

File tree

3 files changed

+114
-36
lines changed

3 files changed

+114
-36
lines changed

tools/testing/selftests/kvm/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ TEST_PROGS_x86_64 += x86_64/nx_huge_pages_test.sh
6767
TEST_GEN_PROGS_x86_64 = x86_64/cpuid_test
6868
TEST_GEN_PROGS_x86_64 += x86_64/cr4_cpuid_sync_test
6969
TEST_GEN_PROGS_x86_64 += x86_64/dirty_log_page_splitting_test
70-
TEST_GEN_PROGS_x86_64 += x86_64/get_msr_index_features
70+
TEST_GEN_PROGS_x86_64 += x86_64/feature_msrs_test
7171
TEST_GEN_PROGS_x86_64 += x86_64/exit_on_emulation_failure_test
7272
TEST_GEN_PROGS_x86_64 += x86_64/fix_hypercall_test
7373
TEST_GEN_PROGS_x86_64 += x86_64/hwcr_msr_test
Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
/*
3+
* Copyright (C) 2020, Red Hat, Inc.
4+
*/
5+
#include <fcntl.h>
6+
#include <stdio.h>
7+
#include <stdlib.h>
8+
#include <string.h>
9+
#include <sys/ioctl.h>
10+
11+
#include "test_util.h"
12+
#include "kvm_util.h"
13+
#include "processor.h"
14+
15+
static bool is_kvm_controlled_msr(uint32_t msr)
16+
{
17+
return msr == MSR_IA32_VMX_CR0_FIXED1 || msr == MSR_IA32_VMX_CR4_FIXED1;
18+
}
19+
20+
/*
21+
* For VMX MSRs with a "true" variant, KVM requires userspace to set the "true"
22+
* MSR, and doesn't allow setting the hidden version.
23+
*/
24+
static bool is_hidden_vmx_msr(uint32_t msr)
25+
{
26+
switch (msr) {
27+
case MSR_IA32_VMX_PINBASED_CTLS:
28+
case MSR_IA32_VMX_PROCBASED_CTLS:
29+
case MSR_IA32_VMX_EXIT_CTLS:
30+
case MSR_IA32_VMX_ENTRY_CTLS:
31+
return true;
32+
default:
33+
return false;
34+
}
35+
}
36+
37+
static bool is_quirked_msr(uint32_t msr)
38+
{
39+
return msr != MSR_AMD64_DE_CFG;
40+
}
41+
42+
static void test_feature_msr(uint32_t msr)
43+
{
44+
const uint64_t supported_mask = kvm_get_feature_msr(msr);
45+
uint64_t reset_value = is_quirked_msr(msr) ? supported_mask : 0;
46+
struct kvm_vcpu *vcpu;
47+
struct kvm_vm *vm;
48+
49+
/*
50+
* Don't bother testing KVM-controlled MSRs beyond verifying that the
51+
* MSR can be read from userspace. Any value is effectively legal, as
52+
* KVM is bound by x86 architecture, not by ABI.
53+
*/
54+
if (is_kvm_controlled_msr(msr))
55+
return;
56+
57+
/*
58+
* More goofy behavior. KVM reports the host CPU's actual revision ID,
59+
* but initializes the vCPU's revision ID to an arbitrary value.
60+
*/
61+
if (msr == MSR_IA32_UCODE_REV)
62+
reset_value = host_cpu_is_intel ? 0x100000000ULL : 0x01000065;
63+
64+
/*
65+
* For quirked MSRs, KVM's ABI is to initialize the vCPU's value to the
66+
* full set of features supported by KVM. For non-quirked MSRs, and
67+
* when the quirk is disabled, KVM must zero-initialize the MSR and let
68+
* userspace do the configuration.
69+
*/
70+
vm = vm_create_with_one_vcpu(&vcpu, NULL);
71+
TEST_ASSERT(vcpu_get_msr(vcpu, msr) == reset_value,
72+
"Wanted 0x%lx for %squirked MSR 0x%x, got 0x%lx",
73+
reset_value, is_quirked_msr(msr) ? "" : "non-", msr,
74+
vcpu_get_msr(vcpu, msr));
75+
if (!is_hidden_vmx_msr(msr))
76+
vcpu_set_msr(vcpu, msr, supported_mask);
77+
kvm_vm_free(vm);
78+
79+
if (is_hidden_vmx_msr(msr))
80+
return;
81+
82+
if (!kvm_has_cap(KVM_CAP_DISABLE_QUIRKS2) ||
83+
!(kvm_check_cap(KVM_CAP_DISABLE_QUIRKS2) & KVM_X86_QUIRK_STUFF_FEATURE_MSRS))
84+
return;
85+
86+
vm = vm_create(1);
87+
vm_enable_cap(vm, KVM_CAP_DISABLE_QUIRKS2, KVM_X86_QUIRK_STUFF_FEATURE_MSRS);
88+
89+
vcpu = vm_vcpu_add(vm, 0, NULL);
90+
TEST_ASSERT(!vcpu_get_msr(vcpu, msr),
91+
"Quirk disabled, wanted '0' for MSR 0x%x, got 0x%lx",
92+
msr, vcpu_get_msr(vcpu, msr));
93+
kvm_vm_free(vm);
94+
}
95+
96+
int main(int argc, char *argv[])
97+
{
98+
const struct kvm_msr_list *feature_list;
99+
int i;
100+
101+
/*
102+
* Skip the entire test if MSR_FEATURES isn't supported, other tests
103+
* will cover the "regular" list of MSRs, the coverage here is purely
104+
* opportunistic and not interesting on its own.
105+
*/
106+
TEST_REQUIRE(kvm_has_cap(KVM_CAP_GET_MSR_FEATURES));
107+
108+
(void)kvm_get_msr_index_list();
109+
110+
feature_list = kvm_get_feature_msr_index_list();
111+
for (i = 0; i < feature_list->nmsrs; i++)
112+
test_feature_msr(feature_list->indices[i]);
113+
}

tools/testing/selftests/kvm/x86_64/get_msr_index_features.c

Lines changed: 0 additions & 35 deletions
This file was deleted.

0 commit comments

Comments
 (0)