KVM: TDX: Register TDX host key IDs to cgroup misc controller
authorZhiming Hu <zhiming.hu@intel.com>
Wed, 19 Feb 2025 14:02:51 +0000 (09:02 -0500)
committerPaolo Bonzini <pbonzini@redhat.com>
Fri, 14 Mar 2025 18:20:51 +0000 (14:20 -0400)
TDX host key IDs (HKID) are limit resources in a machine, and the misc
cgroup lets the machine owner track their usage and limits the possibility
of abusing them outside the owner's control.

The cgroup v2 miscellaneous subsystem was introduced to control the
resource of AMD SEV & SEV-ES ASIDs.  Likewise introduce HKIDs as a misc
resource.

Signed-off-by: Zhiming Hu <zhiming.hu@intel.com>
Signed-off-by: Isaku Yamahata <isaku.yamahata@intel.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
arch/x86/include/asm/tdx.h
arch/x86/kvm/vmx/tdx.c
arch/x86/kvm/vmx/tdx.h
arch/x86/virt/vmx/tdx/tdx.c
include/linux/misc_cgroup.h
kernel/cgroup/misc.c

index 1a8c687603aaefc7353c28d4055d202f75cb9601..2879fc518a325068642fd8cf706b793bb8753d7e 100644 (file)
@@ -125,6 +125,7 @@ const char *tdx_dump_mce_info(struct mce *m);
 const struct tdx_sys_info *tdx_get_sysinfo(void);
 
 int tdx_guest_keyid_alloc(void);
+u32 tdx_get_nr_guest_keyids(void);
 void tdx_guest_keyid_free(unsigned int keyid);
 
 struct tdx_td {
@@ -180,6 +181,7 @@ u64 tdh_phymem_page_wbinvd_tdr(struct tdx_td *td);
 static inline void tdx_init(void) { }
 static inline int tdx_cpu_enable(void) { return -ENODEV; }
 static inline int tdx_enable(void)  { return -ENODEV; }
+static inline u32 tdx_get_nr_guest_keyids(void) { return 0; }
 static inline const char *tdx_dump_mce_info(struct mce *m) { return NULL; }
 static inline const struct tdx_sys_info *tdx_get_sysinfo(void) { return NULL; }
 #endif /* CONFIG_INTEL_TDX_HOST */
index 2ac925ecccd56890f7db3f9838c448f18daf8b15..01166cb8f2e6d7d937ba610821e24dc0907aa4dd 100644 (file)
@@ -1,6 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0
 #include <linux/cpu.h>
 #include <asm/cpufeature.h>
+#include <linux/misc_cgroup.h>
 #include <asm/tdx.h>
 #include "capabilities.h"
 #include "mmu.h"
@@ -140,6 +141,9 @@ 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);
+       misc_cg_uncharge(MISC_CG_RES_TDX, kvm_tdx->misc_cg, 1);
+       put_misc_cg(kvm_tdx->misc_cg);
+       kvm_tdx->misc_cg = NULL;
 }
 
 static inline bool is_hkid_assigned(struct kvm_tdx *kvm_tdx)
@@ -675,6 +679,10 @@ static int __tdx_td_init(struct kvm *kvm, struct td_params *td_params,
        if (ret < 0)
                return ret;
        kvm_tdx->hkid = ret;
+       kvm_tdx->misc_cg = get_current_misc_cg();
+       ret = misc_cg_try_charge(MISC_CG_RES_TDX, kvm_tdx->misc_cg, 1);
+       if (ret)
+               goto free_hkid;
 
        ret = -ENOMEM;
 
@@ -1459,6 +1467,11 @@ static int __init __tdx_bringup(void)
                goto get_sysinfo_err;
        }
 
+       if (misc_cg_set_capacity(MISC_CG_RES_TDX, tdx_get_nr_guest_keyids())) {
+               r = -EINVAL;
+               goto get_sysinfo_err;
+       }
+
        /*
         * Leave hardware virtualization enabled after TDX is enabled
         * successfully.  TDX CPU hotplug depends on this.
@@ -1475,6 +1488,7 @@ tdx_bringup_err:
 void tdx_cleanup(void)
 {
        if (enable_tdx) {
+               misc_cg_set_capacity(MISC_CG_RES_TDX, 0);
                __tdx_cleanup();
                kvm_disable_virtualization();
        }
index 6ec7ac1d91e3c591c6ca6a737fe67bf3e4671956..0559126c8f9da3f1fbb9a4c45825db4cad6299f4 100644 (file)
@@ -21,6 +21,7 @@ enum kvm_tdx_state {
 struct kvm_tdx {
        struct kvm kvm;
 
+       struct misc_cg *misc_cg;
        int hkid;
        enum kvm_tdx_state state;
 
index 9f0c482c1a0377da07b932d5de7908abb23d6b36..3a272e9ff2ca1340e2dd565b608df4f611afef3e 100644 (file)
@@ -1476,6 +1476,12 @@ const struct tdx_sys_info *tdx_get_sysinfo(void)
 }
 EXPORT_SYMBOL_GPL(tdx_get_sysinfo);
 
+u32 tdx_get_nr_guest_keyids(void)
+{
+       return tdx_nr_guest_keyids;
+}
+EXPORT_SYMBOL_GPL(tdx_get_nr_guest_keyids);
+
 int tdx_guest_keyid_alloc(void)
 {
        return ida_alloc_range(&tdx_guest_keyid_pool, tdx_guest_keyid_start,
index 49eef10c8e5972b4a8130f13fe2f02704009704b..8c0e4f4d71bebbf672e75dcbbd653e12ebfc1b07 100644 (file)
@@ -17,6 +17,10 @@ enum misc_res_type {
        MISC_CG_RES_SEV,
        /** @MISC_CG_RES_SEV_ES: AMD SEV-ES ASIDs resource */
        MISC_CG_RES_SEV_ES,
+#endif
+#ifdef CONFIG_INTEL_TDX_HOST
+       /* Intel TDX HKIDs resource */
+       MISC_CG_RES_TDX,
 #endif
        /** @MISC_CG_RES_TYPES: count of enum misc_res_type constants */
        MISC_CG_RES_TYPES
index 0e26068995a6cec9319d95be8d4c77ea49f4f06e..264aad22c967450017078e04602b9ca504b415a6 100644 (file)
@@ -24,6 +24,10 @@ static const char *const misc_res_name[] = {
        /* AMD SEV-ES ASIDs resource */
        "sev_es",
 #endif
+#ifdef CONFIG_INTEL_TDX_HOST
+       /* Intel TDX HKIDs resource */
+       "tdx",
+#endif
 };
 
 /* Root misc cgroup */