*/
 static DEFINE_MUTEX(tdx_lock);
 
+static atomic_t nr_configured_hkid;
+
 static inline void tdx_hkid_free(struct kvm_tdx *kvm_tdx)
 {
        tdx_guest_keyid_free(kvm_tdx->hkid);
        kvm_tdx->hkid = -1;
+       atomic_dec(&nr_configured_hkid);
 }
 
 static inline bool is_hkid_assigned(struct kvm_tdx *kvm_tdx)
 
        ret = -ENOMEM;
 
+       atomic_inc(&nr_configured_hkid);
+
        tdr_page = alloc_page(GFP_KERNEL);
        if (!tdr_page)
                goto free_hkid;
        return r;
 }
 
+static int tdx_offline_cpu(unsigned int cpu)
+{
+       int i;
+
+       /* No TD is running.  Allow any cpu to be offline. */
+       if (!atomic_read(&nr_configured_hkid))
+               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)
 {
        /*
         */
        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;