Skip to content

Commit 9934d7e

Browse files
yamahatabonzini
authored andcommitted
KVM: TDX: Don't offline the last cpu of one package when there's TDX guest
Destroying TDX guest requires there's at least one cpu online for each package, because reclaiming the TDX KeyID of the guest (as part of the teardown process) requires to call some SEAMCALL (on any cpu) on all packages. Do not offline the last cpu of one package when there's any TDX guest running, otherwise KVM may not be able to teardown TDX guest resulting in leaking of TDX KeyID and other resources like TDX guest control structure pages. Implement the TDX version 'offline_cpu()' to prevent the cpu from going offline if it is the last cpu on the package. Co-developed-by: Kai Huang <kai.huang@intel.com> Signed-off-by: Kai Huang <kai.huang@intel.com> Suggested-by: Sean Christopherson <seanjc@google.com> Signed-off-by: Isaku Yamahata <isaku.yamahata@intel.com> Signed-off-by: Rick Edgecombe <rick.p.edgecombe@intel.com> Reviewed-by: Binbin Wu <binbin.wu@linux.intel.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
1 parent ffb6fc8 commit 9934d7e

File tree

1 file changed

+42
-1
lines changed

1 file changed

+42
-1
lines changed

arch/x86/kvm/vmx/tdx.c

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,10 +131,13 @@ static int init_kvm_tdx_caps(const struct tdx_sys_info_td_conf *td_conf,
131131
*/
132132
static DEFINE_MUTEX(tdx_lock);
133133

134+
static atomic_t nr_configured_hkid;
135+
134136
static inline void tdx_hkid_free(struct kvm_tdx *kvm_tdx)
135137
{
136138
tdx_guest_keyid_free(kvm_tdx->hkid);
137139
kvm_tdx->hkid = -1;
140+
atomic_dec(&nr_configured_hkid);
138141
}
139142

140143
static inline bool is_hkid_assigned(struct kvm_tdx *kvm_tdx)
@@ -603,6 +606,8 @@ static int __tdx_td_init(struct kvm *kvm, struct td_params *td_params,
603606

604607
ret = -ENOMEM;
605608

609+
atomic_inc(&nr_configured_hkid);
610+
606611
tdr_page = alloc_page(GFP_KERNEL);
607612
if (!tdr_page)
608613
goto free_hkid;
@@ -900,6 +905,42 @@ static int tdx_online_cpu(unsigned int cpu)
900905
return r;
901906
}
902907

908+
static int tdx_offline_cpu(unsigned int cpu)
909+
{
910+
int i;
911+
912+
/* No TD is running. Allow any cpu to be offline. */
913+
if (!atomic_read(&nr_configured_hkid))
914+
return 0;
915+
916+
/*
917+
* In order to reclaim TDX HKID, (i.e. when deleting guest TD), need to
918+
* call TDH.PHYMEM.PAGE.WBINVD on all packages to program all memory
919+
* controller with pconfig. If we have active TDX HKID, refuse to
920+
* offline the last online cpu.
921+
*/
922+
for_each_online_cpu(i) {
923+
/*
924+
* Found another online cpu on the same package.
925+
* Allow to offline.
926+
*/
927+
if (i != cpu && topology_physical_package_id(i) ==
928+
topology_physical_package_id(cpu))
929+
return 0;
930+
}
931+
932+
/*
933+
* This is the last cpu of this package. Don't offline it.
934+
*
935+
* Because it's hard for human operator to understand the
936+
* reason, warn it.
937+
*/
938+
#define MSG_ALLPKG_ONLINE \
939+
"TDX requires all packages to have an online CPU. Delete all TDs in order to offline all CPUs of a package.\n"
940+
pr_warn_ratelimited(MSG_ALLPKG_ONLINE);
941+
return -EBUSY;
942+
}
943+
903944
static void __do_tdx_cleanup(void)
904945
{
905946
/*
@@ -932,7 +973,7 @@ static int __init __do_tdx_bringup(void)
932973
*/
933974
r = cpuhp_setup_state_cpuslocked(CPUHP_AP_ONLINE_DYN,
934975
"kvm/cpu/tdx:online",
935-
tdx_online_cpu, NULL);
976+
tdx_online_cpu, tdx_offline_cpu);
936977
if (r < 0)
937978
return r;
938979

0 commit comments

Comments
 (0)