Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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: 296d5a17e793 ("KVM: SEV-ES: Use V_TSC_AUX if available instead of RDTSC/MSR_TSC_AUX intercepts")
Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
Message-Id: <4137fbcb9008951ab5f0befa74a0399d2cce809a.1694811272.git.thomas.lendacky@amd.com>
Cc: stable@vger.kernel.org
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>

authored by

Tom Lendacky and committed by
Paolo Bonzini
e0096d01 e8d93d5d

+29 -12
+26 -5
arch/x86/kvm/svm/sev.c
··· 2962 count, in); 2963 } 2964 2965 static void sev_es_init_vmcb(struct vcpu_svm *svm) 2966 { 2967 struct vmcb *vmcb = svm->vmcb01.ptr; ··· 3050 set_msr_interception(vcpu, svm->msrpm, MSR_IA32_LASTBRANCHTOIP, 1, 1); 3051 set_msr_interception(vcpu, svm->msrpm, MSR_IA32_LASTINTFROMIP, 1, 1); 3052 set_msr_interception(vcpu, svm->msrpm, MSR_IA32_LASTINTTOIP, 1, 1); 3053 - 3054 - if (boot_cpu_has(X86_FEATURE_V_TSC_AUX) && 3055 - (guest_cpuid_has(&svm->vcpu, X86_FEATURE_RDTSCP) || 3056 - guest_cpuid_has(&svm->vcpu, X86_FEATURE_RDPID))) 3057 - set_msr_interception(vcpu, svm->msrpm, MSR_TSC_AUX, 1, 1); 3058 } 3059 3060 void sev_init_vmcb(struct vcpu_svm *svm)
··· 2962 count, in); 2963 } 2964 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 + 2991 static void sev_es_init_vmcb(struct vcpu_svm *svm) 2992 { 2993 struct vmcb *vmcb = svm->vmcb01.ptr; ··· 3024 set_msr_interception(vcpu, svm->msrpm, MSR_IA32_LASTBRANCHTOIP, 1, 1); 3025 set_msr_interception(vcpu, svm->msrpm, MSR_IA32_LASTINTFROMIP, 1, 1); 3026 set_msr_interception(vcpu, svm->msrpm, MSR_IA32_LASTINTTOIP, 1, 1); 3027 } 3028 3029 void sev_init_vmcb(struct vcpu_svm *svm)
+2 -7
arch/x86/kvm/svm/svm.c
··· 4284 static void svm_vcpu_after_set_cpuid(struct kvm_vcpu *vcpu) 4285 { 4286 struct vcpu_svm *svm = to_svm(vcpu); 4287 - struct kvm_cpuid_entry2 *best; 4288 4289 /* 4290 * SVM doesn't provide a way to disable just XSAVES in the guest, KVM ··· 4327 set_msr_interception(vcpu, svm->msrpm, MSR_IA32_FLUSH_CMD, 0, 4328 !!guest_cpuid_has(vcpu, X86_FEATURE_FLUSH_L1D)); 4329 4330 - /* For sev guests, the memory encryption bit is not reserved in CR3. */ 4331 - if (sev_guest(vcpu->kvm)) { 4332 - best = kvm_find_cpuid_entry(vcpu, 0x8000001F); 4333 - if (best) 4334 - vcpu->arch.reserved_gpa_bits &= ~(1UL << (best->ebx & 0x3f)); 4335 - } 4336 4337 init_vmcb_after_set_cpuid(vcpu); 4338 }
··· 4284 static void svm_vcpu_after_set_cpuid(struct kvm_vcpu *vcpu) 4285 { 4286 struct vcpu_svm *svm = to_svm(vcpu); 4287 4288 /* 4289 * SVM doesn't provide a way to disable just XSAVES in the guest, KVM ··· 4328 set_msr_interception(vcpu, svm->msrpm, MSR_IA32_FLUSH_CMD, 0, 4329 !!guest_cpuid_has(vcpu, X86_FEATURE_FLUSH_L1D)); 4330 4331 + if (sev_guest(vcpu->kvm)) 4332 + sev_vcpu_after_set_cpuid(svm); 4333 4334 init_vmcb_after_set_cpuid(vcpu); 4335 }
+1
arch/x86/kvm/svm/svm.h
··· 684 void sev_hardware_unsetup(void); 685 int sev_cpu_init(struct svm_cpu_data *sd); 686 void sev_init_vmcb(struct vcpu_svm *svm); 687 void sev_free_vcpu(struct kvm_vcpu *vcpu); 688 int sev_handle_vmgexit(struct kvm_vcpu *vcpu); 689 int sev_es_string_io(struct vcpu_svm *svm, int size, unsigned int port, int in);
··· 684 void sev_hardware_unsetup(void); 685 int sev_cpu_init(struct svm_cpu_data *sd); 686 void sev_init_vmcb(struct vcpu_svm *svm); 687 + void sev_vcpu_after_set_cpuid(struct vcpu_svm *svm); 688 void sev_free_vcpu(struct kvm_vcpu *vcpu); 689 int sev_handle_vmgexit(struct kvm_vcpu *vcpu); 690 int sev_es_string_io(struct vcpu_svm *svm, int size, unsigned int port, int in);