diff --git a/arch/x86/kvm/svm/sev.c b/arch/x86/kvm/svm/sev.c
index 565c9de87c6d..1bbaae2fed96 100644
--- a/arch/x86/kvm/svm/sev.c
+++ b/arch/x86/kvm/svm/sev.c
@@ -2969,6 +2969,7 @@ static void sev_es_init_vmcb_after_set_cpuid(struct vcpu_svm *svm)
 	if (boot_cpu_has(X86_FEATURE_V_TSC_AUX) &&
 	    (guest_cpuid_has(vcpu, X86_FEATURE_RDTSCP) ||
 	     guest_cpuid_has(vcpu, X86_FEATURE_RDPID))) {
+		svm->v_tsc_aux = true;
 		set_msr_interception(vcpu, svm->msrpm, MSR_TSC_AUX, 1, 1);
 		if (guest_cpuid_has(vcpu, X86_FEATURE_RDTSCP))
 			svm_clr_intercept(svm, INTERCEPT_RDTSCP);
@@ -3071,8 +3072,10 @@ void sev_es_vcpu_reset(struct vcpu_svm *svm)
 					    sev_enc_bit));
 }
 
-void sev_es_prepare_switch_to_guest(struct sev_es_save_area *hostsa)
+void sev_es_prepare_switch_to_guest(struct vcpu_svm *svm, struct sev_es_save_area *hostsa)
 {
+	u32 msr_hi;
+
 	/*
 	 * All host state for SEV-ES guests is categorized into three swap types
 	 * based on how it is handled by hardware during a world switch:
@@ -3109,6 +3112,15 @@ void sev_es_prepare_switch_to_guest(struct sev_es_save_area *hostsa)
 		hostsa->dr2_addr_mask = amd_get_dr_addr_mask(2);
 		hostsa->dr3_addr_mask = amd_get_dr_addr_mask(3);
 	}
+
+	/*
+	 * If TSC_AUX virtualization is enabled, MSR_TSC_AUX is loaded but NOT
+	 * saved by the CPU (Type-B). If TSC_AUX is not virtualized, the user
+	 * return MSR support takes care of restoring MSR_TSC_AUX. This
+	 * exchanges two WRMSRs for one RDMSR.
+	 */
+	if (svm->v_tsc_aux)
+		rdmsr(MSR_TSC_AUX, hostsa->tsc_aux, msr_hi);
 }
 
 void sev_vcpu_deliver_sipi_vector(struct kvm_vcpu *vcpu, u8 vector)
diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c
index c58d5632e74a..905b1a2664ed 100644
--- a/arch/x86/kvm/svm/svm.c
+++ b/arch/x86/kvm/svm/svm.c
@@ -1529,13 +1529,13 @@ static void svm_prepare_switch_to_guest(struct kvm_vcpu *vcpu)
 		struct sev_es_save_area *hostsa;
 		hostsa = (struct sev_es_save_area *)(page_address(sd->save_area) + 0x400);
 
-		sev_es_prepare_switch_to_guest(hostsa);
+		sev_es_prepare_switch_to_guest(svm, hostsa);
 	}
 
 	if (tsc_scaling)
 		__svm_write_tsc_multiplier(vcpu->arch.tsc_scaling_ratio);
 
-	if (likely(tsc_aux_uret_slot >= 0))
+	if (likely(tsc_aux_uret_slot >= 0) && !svm->v_tsc_aux)
 		kvm_set_user_return_msr(tsc_aux_uret_slot, svm->tsc_aux, -1ull);
 
 	svm->guest_state_loaded = true;
@@ -3090,15 +3090,21 @@ static int svm_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr)
 		break;
 	case MSR_TSC_AUX:
 		/*
-		 * TSC_AUX is usually changed only during boot and never read
-		 * directly.  Intercept TSC_AUX instead of exposing it to the
-		 * guest via direct_access_msrs, and switch it via user return.
+		 * If TSC_AUX is being virtualized, do not use the user return
+		 * MSR support because TSC_AUX is restored on #VMEXIT.
 		 */
-		preempt_disable();
-		ret = kvm_set_user_return_msr(tsc_aux_uret_slot, data, -1ull);
-		preempt_enable();
-		if (ret)
-			break;
+		if (!svm->v_tsc_aux) {
+			/*
+			 * TSC_AUX is usually changed only during boot and never read
+			 * directly.  Intercept TSC_AUX instead of exposing it to the
+			 * guest via direct_access_msrs, and switch it via user return.
+			 */
+			preempt_disable();
+			ret = kvm_set_user_return_msr(tsc_aux_uret_slot, data, -1ull);
+			preempt_enable();
+			if (ret)
+				break;
+		}
 
 		svm->tsc_aux = data;
 		break;
diff --git a/arch/x86/kvm/svm/svm.h b/arch/x86/kvm/svm/svm.h
index c0d17da46fae..49427858474e 100644
--- a/arch/x86/kvm/svm/svm.h
+++ b/arch/x86/kvm/svm/svm.h
@@ -213,6 +213,8 @@ struct vcpu_svm {
 	u32 asid;
 	u32 sysenter_esp_hi;
 	u32 sysenter_eip_hi;
+
+	bool v_tsc_aux;
 	uint64_t tsc_aux;
 
 	u64 msr_decfg;
@@ -690,7 +692,7 @@ int sev_handle_vmgexit(struct kvm_vcpu *vcpu);
 int sev_es_string_io(struct vcpu_svm *svm, int size, unsigned int port, int in);
 void sev_es_vcpu_reset(struct vcpu_svm *svm);
 void sev_vcpu_deliver_sipi_vector(struct kvm_vcpu *vcpu, u8 vector);
-void sev_es_prepare_switch_to_guest(struct sev_es_save_area *hostsa);
+void sev_es_prepare_switch_to_guest(struct vcpu_svm *svm, struct sev_es_save_area *hostsa);
 void sev_es_unmap_ghcb(struct vcpu_svm *svm);
 
 /* vmenter.S */
