Skip to content
/ linux Public

Commit d3e2196

Browse files
sean-jcgregkh
authored andcommitted
KVM: x86: Quirk initialization of feature MSRs to KVM's max configuration
[ Upstream commit dcb988c ] Add a quirk to control KVM's misguided initialization of select feature MSRs to KVM's max configuration, as enabling features by default violates KVM's approach of letting userspace own the vCPU model, and is actively problematic for MSRs that are conditionally supported, as the vCPU will end up with an MSR value that userspace can't restore. E.g. if the vCPU is configured with PDCM=0, userspace will save and attempt to restore a non-zero PERF_CAPABILITIES, thanks to KVM's meddling. Link: https://lore.kernel.org/r/20240802185511.305849-4-seanjc@google.com Signed-off-by: Sean Christopherson <seanjc@google.com> Stable-dep-of: e2ffe85 ("KVM: x86: Introduce KVM_X86_QUIRK_VMCS12_ALLOW_FREEZE_IN_SMM") Signed-off-by: Sasha Levin <sashal@kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent 715b07a commit d3e2196

File tree

6 files changed

+39
-8
lines changed

6 files changed

+39
-8
lines changed

Documentation/virt/kvm/api.rst

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8107,6 +8107,28 @@ KVM_X86_QUIRK_SLOT_ZAP_ALL By default, for KVM_X86_DEFAULT_VM VMs, KVM
81078107
or moved memslot isn't reachable, i.e KVM
81088108
_may_ invalidate only SPTEs related to the
81098109
memslot.
8110+
8111+
KVM_X86_QUIRK_STUFF_FEATURE_MSRS By default, at vCPU creation, KVM sets the
8112+
vCPU's MSR_IA32_PERF_CAPABILITIES (0x345),
8113+
MSR_IA32_ARCH_CAPABILITIES (0x10a),
8114+
MSR_PLATFORM_INFO (0xce), and all VMX MSRs
8115+
(0x480..0x492) to the maximal capabilities
8116+
supported by KVM. KVM also sets
8117+
MSR_IA32_UCODE_REV (0x8b) to an arbitrary
8118+
value (which is different for Intel vs.
8119+
AMD). Lastly, when guest CPUID is set (by
8120+
userspace), KVM modifies select VMX MSR
8121+
fields to force consistency between guest
8122+
CPUID and L2's effective ISA. When this
8123+
quirk is disabled, KVM zeroes the vCPU's MSR
8124+
values (with two exceptions, see below),
8125+
i.e. treats the feature MSRs like CPUID
8126+
leaves and gives userspace full control of
8127+
the vCPU model definition. This quirk does
8128+
not affect VMX MSRs CR0/CR4_FIXED1 (0x487
8129+
and 0x489), as KVM does now allow them to
8130+
be set by userspace (KVM sets them based on
8131+
guest CPUID, for safety purposes).
81108132
=================================== ============================================
81118133

81128134
7.32 KVM_CAP_MAX_VCPU_ID

arch/x86/include/asm/kvm_host.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2385,7 +2385,8 @@ int memslot_rmap_alloc(struct kvm_memory_slot *slot, unsigned long npages);
23852385
KVM_X86_QUIRK_MISC_ENABLE_NO_MWAIT | \
23862386
KVM_X86_QUIRK_FIX_HYPERCALL_INSN | \
23872387
KVM_X86_QUIRK_MWAIT_NEVER_UD_FAULTS | \
2388-
KVM_X86_QUIRK_SLOT_ZAP_ALL)
2388+
KVM_X86_QUIRK_SLOT_ZAP_ALL | \
2389+
KVM_X86_QUIRK_STUFF_FEATURE_MSRS)
23892390

23902391
/*
23912392
* KVM previously used a u32 field in kvm_run to indicate the hypercall was

arch/x86/include/uapi/asm/kvm.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -440,6 +440,7 @@ struct kvm_sync_regs {
440440
#define KVM_X86_QUIRK_FIX_HYPERCALL_INSN (1 << 5)
441441
#define KVM_X86_QUIRK_MWAIT_NEVER_UD_FAULTS (1 << 6)
442442
#define KVM_X86_QUIRK_SLOT_ZAP_ALL (1 << 7)
443+
#define KVM_X86_QUIRK_STUFF_FEATURE_MSRS (1 << 8)
443444

444445
#define KVM_STATE_NESTED_FORMAT_VMX 0
445446
#define KVM_STATE_NESTED_FORMAT_SVM 1

arch/x86/kvm/svm/svm.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1389,7 +1389,9 @@ static void __svm_vcpu_reset(struct kvm_vcpu *vcpu)
13891389
svm_vcpu_init_msrpm(vcpu, svm->msrpm);
13901390

13911391
svm_init_osvw(vcpu);
1392-
vcpu->arch.microcode_version = 0x01000065;
1392+
1393+
if (kvm_check_has_quirk(vcpu->kvm, KVM_X86_QUIRK_STUFF_FEATURE_MSRS))
1394+
vcpu->arch.microcode_version = 0x01000065;
13931395
svm->tsc_ratio_msr = kvm_caps.default_tsc_scaling_ratio;
13941396

13951397
svm->nmi_masked = false;

arch/x86/kvm/vmx/vmx.c

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4562,7 +4562,8 @@ vmx_adjust_secondary_exec_control(struct vcpu_vmx *vmx, u32 *exec_control,
45624562
* Update the nested MSR settings so that a nested VMM can/can't set
45634563
* controls for features that are/aren't exposed to the guest.
45644564
*/
4565-
if (nested) {
4565+
if (nested &&
4566+
kvm_check_has_quirk(vmx->vcpu.kvm, KVM_X86_QUIRK_STUFF_FEATURE_MSRS)) {
45664567
/*
45674568
* All features that can be added or removed to VMX MSRs must
45684569
* be supported in the first place for nested virtualization.
@@ -4853,7 +4854,8 @@ static void __vmx_vcpu_reset(struct kvm_vcpu *vcpu)
48534854

48544855
init_vmcs(vmx);
48554856

4856-
if (nested)
4857+
if (nested &&
4858+
kvm_check_has_quirk(vcpu->kvm, KVM_X86_QUIRK_STUFF_FEATURE_MSRS))
48574859
memcpy(&vmx->nested.msrs, &vmcs_config.nested, sizeof(vmx->nested.msrs));
48584860

48594861
vcpu_setup_sgx_lepubkeyhash(vcpu);
@@ -4866,7 +4868,8 @@ static void __vmx_vcpu_reset(struct kvm_vcpu *vcpu)
48664868
vmx->nested.hv_evmcs_vmptr = EVMPTR_INVALID;
48674869
#endif
48684870

4869-
vcpu->arch.microcode_version = 0x100000000ULL;
4871+
if (kvm_check_has_quirk(vcpu->kvm, KVM_X86_QUIRK_STUFF_FEATURE_MSRS))
4872+
vcpu->arch.microcode_version = 0x100000000ULL;
48704873
vmx->msr_ia32_feature_control_valid_bits = FEAT_CTL_LOCKED;
48714874

48724875
/*

arch/x86/kvm/x86.c

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12383,9 +12383,11 @@ int kvm_arch_vcpu_create(struct kvm_vcpu *vcpu)
1238312383

1238412384
kvm_async_pf_hash_reset(vcpu);
1238512385

12386-
vcpu->arch.arch_capabilities = kvm_get_arch_capabilities();
12387-
vcpu->arch.msr_platform_info = MSR_PLATFORM_INFO_CPUID_FAULT;
12388-
vcpu->arch.perf_capabilities = kvm_caps.supported_perf_cap;
12386+
if (kvm_check_has_quirk(vcpu->kvm, KVM_X86_QUIRK_STUFF_FEATURE_MSRS)) {
12387+
vcpu->arch.arch_capabilities = kvm_get_arch_capabilities();
12388+
vcpu->arch.msr_platform_info = MSR_PLATFORM_INFO_CPUID_FAULT;
12389+
vcpu->arch.perf_capabilities = kvm_caps.supported_perf_cap;
12390+
}
1238912391
kvm_pmu_init(vcpu);
1239012392

1239112393
vcpu->arch.pending_external_vector = -1;

0 commit comments

Comments
 (0)