Skip to content

Commit e0096d0

Browse files
tlendackybonzini
authored andcommitted
KVM: SVM: Fix TSC_AUX virtualization setup
The checks for virtualizing TSC_AUX occur during the vCPU reset processing path. However, at the time of initial vCPU reset processing, when the vCPU is first created, not all of the guest CPUID information has been set. In this case the RDTSCP and RDPID feature support for the guest is not in place and so TSC_AUX virtualization is not established. This continues for each vCPU created for the guest. On the first boot of an AP, vCPU reset processing is executed as a result of an APIC INIT event, this time with all of the guest CPUID information set, resulting in TSC_AUX virtualization being enabled, but only for the APs. The BSP always sees a TSC_AUX value of 0 which probably went unnoticed because, at least for Linux, the BSP TSC_AUX value is 0. Move the TSC_AUX virtualization enablement out of the init_vmcb() path and into the vcpu_after_set_cpuid() path to allow for proper initialization of the support after the guest CPUID information has been set. With the TSC_AUX virtualization support now in the vcpu_set_after_cpuid() path, the intercepts must be either cleared or set based on the guest CPUID input. Fixes: 296d5a1 ("KVM: SEV-ES: Use V_TSC_AUX if available instead of RDTSC/MSR_TSC_AUX intercepts") Signed-off-by: Tom Lendacky <[email protected]> Message-Id: <4137fbcb9008951ab5f0befa74a0399d2cce809a.1694811272.git.thomas.lendacky@amd.com> Cc: [email protected] Signed-off-by: Paolo Bonzini <[email protected]>
1 parent e8d93d5 commit e0096d0

File tree

3 files changed

+29
-12
lines changed

3 files changed

+29
-12
lines changed

arch/x86/kvm/svm/sev.c

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2962,6 +2962,32 @@ int sev_es_string_io(struct vcpu_svm *svm, int size, unsigned int port, int in)
29622962
count, in);
29632963
}
29642964

2965+
static void sev_es_vcpu_after_set_cpuid(struct vcpu_svm *svm)
2966+
{
2967+
struct kvm_vcpu *vcpu = &svm->vcpu;
2968+
2969+
if (boot_cpu_has(X86_FEATURE_V_TSC_AUX)) {
2970+
bool v_tsc_aux = guest_cpuid_has(vcpu, X86_FEATURE_RDTSCP) ||
2971+
guest_cpuid_has(vcpu, X86_FEATURE_RDPID);
2972+
2973+
set_msr_interception(vcpu, svm->msrpm, MSR_TSC_AUX, v_tsc_aux, v_tsc_aux);
2974+
}
2975+
}
2976+
2977+
void sev_vcpu_after_set_cpuid(struct vcpu_svm *svm)
2978+
{
2979+
struct kvm_vcpu *vcpu = &svm->vcpu;
2980+
struct kvm_cpuid_entry2 *best;
2981+
2982+
/* For sev guests, the memory encryption bit is not reserved in CR3. */
2983+
best = kvm_find_cpuid_entry(vcpu, 0x8000001F);
2984+
if (best)
2985+
vcpu->arch.reserved_gpa_bits &= ~(1UL << (best->ebx & 0x3f));
2986+
2987+
if (sev_es_guest(svm->vcpu.kvm))
2988+
sev_es_vcpu_after_set_cpuid(svm);
2989+
}
2990+
29652991
static void sev_es_init_vmcb(struct vcpu_svm *svm)
29662992
{
29672993
struct vmcb *vmcb = svm->vmcb01.ptr;
@@ -3024,11 +3050,6 @@ static void sev_es_init_vmcb(struct vcpu_svm *svm)
30243050
set_msr_interception(vcpu, svm->msrpm, MSR_IA32_LASTBRANCHTOIP, 1, 1);
30253051
set_msr_interception(vcpu, svm->msrpm, MSR_IA32_LASTINTFROMIP, 1, 1);
30263052
set_msr_interception(vcpu, svm->msrpm, MSR_IA32_LASTINTTOIP, 1, 1);
3027-
3028-
if (boot_cpu_has(X86_FEATURE_V_TSC_AUX) &&
3029-
(guest_cpuid_has(&svm->vcpu, X86_FEATURE_RDTSCP) ||
3030-
guest_cpuid_has(&svm->vcpu, X86_FEATURE_RDPID)))
3031-
set_msr_interception(vcpu, svm->msrpm, MSR_TSC_AUX, 1, 1);
30323053
}
30333054

30343055
void sev_init_vmcb(struct vcpu_svm *svm)

arch/x86/kvm/svm/svm.c

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4284,7 +4284,6 @@ static bool svm_has_emulated_msr(struct kvm *kvm, u32 index)
42844284
static void svm_vcpu_after_set_cpuid(struct kvm_vcpu *vcpu)
42854285
{
42864286
struct vcpu_svm *svm = to_svm(vcpu);
4287-
struct kvm_cpuid_entry2 *best;
42884287

42894288
/*
42904289
* SVM doesn't provide a way to disable just XSAVES in the guest, KVM
@@ -4328,12 +4327,8 @@ static void svm_vcpu_after_set_cpuid(struct kvm_vcpu *vcpu)
43284327
set_msr_interception(vcpu, svm->msrpm, MSR_IA32_FLUSH_CMD, 0,
43294328
!!guest_cpuid_has(vcpu, X86_FEATURE_FLUSH_L1D));
43304329

4331-
/* For sev guests, the memory encryption bit is not reserved in CR3. */
4332-
if (sev_guest(vcpu->kvm)) {
4333-
best = kvm_find_cpuid_entry(vcpu, 0x8000001F);
4334-
if (best)
4335-
vcpu->arch.reserved_gpa_bits &= ~(1UL << (best->ebx & 0x3f));
4336-
}
4330+
if (sev_guest(vcpu->kvm))
4331+
sev_vcpu_after_set_cpuid(svm);
43374332

43384333
init_vmcb_after_set_cpuid(vcpu);
43394334
}

arch/x86/kvm/svm/svm.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -684,6 +684,7 @@ void __init sev_hardware_setup(void);
684684
void sev_hardware_unsetup(void);
685685
int sev_cpu_init(struct svm_cpu_data *sd);
686686
void sev_init_vmcb(struct vcpu_svm *svm);
687+
void sev_vcpu_after_set_cpuid(struct vcpu_svm *svm);
687688
void sev_free_vcpu(struct kvm_vcpu *vcpu);
688689
int sev_handle_vmgexit(struct kvm_vcpu *vcpu);
689690
int sev_es_string_io(struct vcpu_svm *svm, int size, unsigned int port, int in);

0 commit comments

Comments
 (0)