Message ID | 20240812224820.34826-17-rick.p.edgecombe@intel.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | TDX vCPU/VM creation | expand |
On 8/13/2024 6:48 AM, Rick Edgecombe wrote: > From: Isaku Yamahata <isaku.yamahata@intel.com> > > 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. > > Add a tdx_arch_offline_cpu() and call it in kvm_offline_cpu() to provide > a placeholder for TDX specific check. The default __weak version simply > returns 0 (allow to offline) so other ARCHs are not impacted. Implement > the x86 version, which calls a new 'kvm_x86_ops::offline_cpu()' callback. > Implement the TDX version 'offline_cpu()' to prevent the cpu from going > offline if it is the last cpu on the package. This part is stale. Now, it's using TDX's own hotplug state callbacks instead of hooking into KVM's. > [...] > + > static void __do_tdx_cleanup(void) > { > /* > @@ -946,7 +982,7 @@ static int __init __do_tdx_bringup(void) > */ > r = cpuhp_setup_state_cpuslocked(CPUHP_AP_ONLINE_DYN, > "kvm/cpu/tdx:online", > - tdx_online_cpu, NULL); > + tdx_online_cpu, tdx_offline_cpu); > if (r < 0) > return r; >
diff --git a/arch/x86/kvm/vmx/tdx.c b/arch/x86/kvm/vmx/tdx.c index a6c711715a4a..531e87983b90 100644 --- a/arch/x86/kvm/vmx/tdx.c +++ b/arch/x86/kvm/vmx/tdx.c @@ -921,6 +921,42 @@ static int tdx_online_cpu(unsigned int cpu) return r; } +static int tdx_offline_cpu(unsigned int cpu) +{ + int i; + + /* No TD is running. Allow any cpu to be offline. */ + if (ida_is_empty(&tdx_guest_keyid_pool)) + return 0; + + /* + * In order to reclaim TDX HKID, (i.e. when deleting guest TD), need to + * call TDH.PHYMEM.PAGE.WBINVD on all packages to program all memory + * controller with pconfig. If we have active TDX HKID, refuse to + * offline the last online cpu. + */ + for_each_online_cpu(i) { + /* + * Found another online cpu on the same package. + * Allow to offline. + */ + if (i != cpu && topology_physical_package_id(i) == + topology_physical_package_id(cpu)) + return 0; + } + + /* + * This is the last cpu of this package. Don't offline it. + * + * Because it's hard for human operator to understand the + * reason, warn it. + */ +#define MSG_ALLPKG_ONLINE \ + "TDX requires all packages to have an online CPU. Delete all TDs in order to offline all CPUs of a package.\n" + pr_warn_ratelimited(MSG_ALLPKG_ONLINE); + return -EBUSY; +} + static void __do_tdx_cleanup(void) { /* @@ -946,7 +982,7 @@ static int __init __do_tdx_bringup(void) */ r = cpuhp_setup_state_cpuslocked(CPUHP_AP_ONLINE_DYN, "kvm/cpu/tdx:online", - tdx_online_cpu, NULL); + tdx_online_cpu, tdx_offline_cpu); if (r < 0) return r;