Skip to content

Commit e0b4f31

Browse files
yamahatabonzini
authored andcommitted
KVM: TDX: restore user ret MSRs
Several MSRs are clobbered on TD exit that are not used by Linux while in ring 0. Ensure the cached value of the MSR is updated on vcpu_put, and the MSRs themselves before returning to ring 3. Co-developed-by: Tony Lindgren <tony.lindgren@linux.intel.com> Signed-off-by: Tony Lindgren <tony.lindgren@linux.intel.com> Signed-off-by: Isaku Yamahata <isaku.yamahata@intel.com> Signed-off-by: Adrian Hunter <adrian.hunter@intel.com> Reviewed-by: Paolo Bonzini <pbonzini@redhat.com> Message-ID: <20250129095902.16391-10-adrian.hunter@intel.com> Reviewed-by: Xiayao Li <xiaoyao.li@intel.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
1 parent d3a6b6c commit e0b4f31

File tree

2 files changed

+51
-1
lines changed

2 files changed

+51
-1
lines changed

arch/x86/kvm/vmx/tdx.c

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -651,16 +651,44 @@ void tdx_prepare_switch_to_guest(struct kvm_vcpu *vcpu)
651651
vt->guest_state_loaded = true;
652652
}
653653

654+
struct tdx_uret_msr {
655+
u32 msr;
656+
unsigned int slot;
657+
u64 defval;
658+
};
659+
660+
static struct tdx_uret_msr tdx_uret_msrs[] = {
661+
{.msr = MSR_SYSCALL_MASK, .defval = 0x20200 },
662+
{.msr = MSR_STAR,},
663+
{.msr = MSR_LSTAR,},
664+
{.msr = MSR_TSC_AUX,},
665+
};
666+
667+
static void tdx_user_return_msr_update_cache(void)
668+
{
669+
int i;
670+
671+
for (i = 0; i < ARRAY_SIZE(tdx_uret_msrs); i++)
672+
kvm_user_return_msr_update_cache(tdx_uret_msrs[i].slot,
673+
tdx_uret_msrs[i].defval);
674+
}
675+
654676
static void tdx_prepare_switch_to_host(struct kvm_vcpu *vcpu)
655677
{
656678
struct vcpu_vt *vt = to_vt(vcpu);
679+
struct vcpu_tdx *tdx = to_tdx(vcpu);
657680

658681
if (!vt->guest_state_loaded)
659682
return;
660683

661684
++vcpu->stat.host_state_reload;
662685
wrmsrl(MSR_KERNEL_GS_BASE, vt->msr_host_kernel_gs_base);
663686

687+
if (tdx->guest_entered) {
688+
tdx_user_return_msr_update_cache();
689+
tdx->guest_entered = false;
690+
}
691+
664692
vt->guest_state_loaded = false;
665693
}
666694

@@ -767,6 +795,8 @@ EXPORT_SYMBOL_GPL(kvm_load_host_xsave_state);
767795

768796
fastpath_t tdx_vcpu_run(struct kvm_vcpu *vcpu, bool force_immediate_exit)
769797
{
798+
struct vcpu_tdx *tdx = to_tdx(vcpu);
799+
770800
/*
771801
* force_immediate_exit requires vCPU entering for events injection with
772802
* an immediately exit followed. But The TDX module doesn't guarantee
@@ -782,6 +812,7 @@ fastpath_t tdx_vcpu_run(struct kvm_vcpu *vcpu, bool force_immediate_exit)
782812
tdx_vcpu_enter_exit(vcpu);
783813

784814
tdx_load_host_xsave_state(vcpu);
815+
tdx->guest_entered = true;
785816

786817
vcpu->arch.regs_avail &= TDX_REGS_AVAIL_SET;
787818

@@ -2242,7 +2273,25 @@ static int __init __do_tdx_bringup(void)
22422273
static int __init __tdx_bringup(void)
22432274
{
22442275
const struct tdx_sys_info_td_conf *td_conf;
2245-
int r;
2276+
int r, i;
2277+
2278+
for (i = 0; i < ARRAY_SIZE(tdx_uret_msrs); i++) {
2279+
/*
2280+
* Check if MSRs (tdx_uret_msrs) can be saved/restored
2281+
* before returning to user space.
2282+
*
2283+
* this_cpu_ptr(user_return_msrs)->registered isn't checked
2284+
* because the registration is done at vcpu runtime by
2285+
* tdx_user_return_msr_update_cache().
2286+
*/
2287+
tdx_uret_msrs[i].slot = kvm_find_user_return_msr(tdx_uret_msrs[i].msr);
2288+
if (tdx_uret_msrs[i].slot == -1) {
2289+
/* If any MSR isn't supported, it is a KVM bug */
2290+
pr_err("MSR %x isn't included by kvm_find_user_return_msr\n",
2291+
tdx_uret_msrs[i].msr);
2292+
return -EIO;
2293+
}
2294+
}
22462295

22472296
/*
22482297
* Enabling TDX requires enabling hardware virtualization first,

arch/x86/kvm/vmx/tdx.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ struct vcpu_tdx {
5757
u64 vp_enter_ret;
5858

5959
enum vcpu_tdx_state state;
60+
bool guest_entered;
6061
};
6162

6263
void tdh_vp_rd_failed(struct vcpu_tdx *tdx, char *uclass, u32 field, u64 err);

0 commit comments

Comments
 (0)