drm/xe/huc: Prepare for 2-step HuC authentication
authorDaniele Ceraolo Spurio <daniele.ceraolospurio@intel.com>
Wed, 29 Nov 2023 01:17:18 +0000 (17:17 -0800)
committerRodrigo Vivi <rodrigo.vivi@intel.com>
Thu, 21 Dec 2023 16:45:24 +0000 (11:45 -0500)
Starting on MTL, the HuC is authenticated twice, once via GuC (same as
with older integrated platforms) and once via GSC; the first
authentication allows the HuC to be used for clear-media workloads,
while the second one unlocks support for protected content.
Ahead of adding the authentication flow via GSC, this patch adds support
for differentiating the 2 auth steps and checking if they're complete.

Signed-off-by: Daniele Ceraolo Spurio <daniele.ceraolospurio@intel.com>
Cc: Alan Previn <alan.previn.teres.alexis@intel.com>
Cc: John Harrison <John.C.Harrison@Intel.com>
Reviewed-by: Vivaik Balasubrawmanian <vivaik.balasubrawmanian@intel.com>
Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com>
drivers/gpu/drm/xe/regs/xe_gsc_regs.h
drivers/gpu/drm/xe/xe_huc.c
drivers/gpu/drm/xe/xe_huc.h
drivers/gpu/drm/xe/xe_uc.c

index 9a84b55d66eee1c9cba769df07bb050d56a4cd1d..9886ec9cb08e91cf26ff723ff70bbcb99846723e 100644 (file)
@@ -32,6 +32,8 @@
 #define   HECI1_FWSTS1_CURRENT_STATE_RESET             0
 #define   HECI1_FWSTS1_PROXY_STATE_NORMAL              5
 #define   HECI1_FWSTS1_INIT_COMPLETE                   REG_BIT(9)
+#define HECI_FWSTS5(base)                              XE_REG((base) + 0xc68)
+#define   HECI1_FWSTS5_HUC_AUTH_DONE                   REG_BIT(19)
 
 #define HECI_H_GS1(base)       XE_REG((base) + 0xc4c)
 #define   HECI_H_GS1_ER_PREP   REG_BIT(0)
index 2f176badab261230aa779f175b6d18bf66b3d610..9845165a819cdacaa0895b7eb37027f7f0e7b81a 100644 (file)
@@ -5,6 +5,7 @@
 
 #include "xe_huc.h"
 
+#include "regs/xe_gsc_regs.h"
 #include "regs/xe_guc_regs.h"
 #include "xe_assert.h"
 #include "xe_bo.h"
@@ -71,7 +72,25 @@ int xe_huc_upload(struct xe_huc *huc)
        return xe_uc_fw_upload(&huc->fw, 0, HUC_UKERNEL);
 }
 
-int xe_huc_auth(struct xe_huc *huc)
+static const struct {
+       const char *name;
+       struct xe_reg reg;
+       u32 val;
+} huc_auth_modes[XE_HUC_AUTH_TYPES_COUNT] = {
+       [XE_HUC_AUTH_VIA_GUC] = { "GuC",
+                                 HUC_KERNEL_LOAD_INFO,
+                                 HUC_LOAD_SUCCESSFUL },
+       [XE_HUC_AUTH_VIA_GSC] = { "GSC",
+                                 HECI_FWSTS5(MTL_GSC_HECI1_BASE),
+                                 HECI1_FWSTS5_HUC_AUTH_DONE },
+};
+
+static bool huc_is_authenticated(struct xe_gt *gt, enum xe_huc_auth_types type)
+{
+       return xe_mmio_read32(gt, huc_auth_modes[type].reg) & huc_auth_modes[type].val;
+}
+
+int xe_huc_auth(struct xe_huc *huc, enum xe_huc_auth_types type)
 {
        struct xe_device *xe = huc_to_xe(huc);
        struct xe_gt *gt = huc_to_gt(huc);
@@ -84,7 +103,7 @@ int xe_huc_auth(struct xe_huc *huc)
        xe_assert(xe, !xe_uc_fw_is_running(&huc->fw));
 
        /* On newer platforms the HuC survives reset, so no need to re-auth */
-       if (xe_mmio_read32(gt, HUC_KERNEL_LOAD_INFO) & HUC_LOAD_SUCCESSFUL) {
+       if (huc_is_authenticated(gt, type)) {
                xe_uc_fw_change_status(&huc->fw, XE_UC_FIRMWARE_RUNNING);
                return 0;
        }
@@ -92,28 +111,36 @@ int xe_huc_auth(struct xe_huc *huc)
        if (!xe_uc_fw_is_loaded(&huc->fw))
                return -ENOEXEC;
 
-       ret = xe_guc_auth_huc(guc, xe_bo_ggtt_addr(huc->fw.bo) +
-                             xe_uc_fw_rsa_offset(&huc->fw));
+       switch (type) {
+       case XE_HUC_AUTH_VIA_GUC:
+               ret = xe_guc_auth_huc(guc, xe_bo_ggtt_addr(huc->fw.bo) +
+                                     xe_uc_fw_rsa_offset(&huc->fw));
+               break;
+       default:
+               XE_WARN_ON(type);
+               return -EINVAL;
+       }
        if (ret) {
-               drm_err(&xe->drm, "HuC: GuC did not ack Auth request %d\n",
-                       ret);
+               drm_err(&xe->drm, "Failed to trigger HuC auth via %s: %d\n",
+                       huc_auth_modes[type].name, ret);
                goto fail;
        }
 
-       ret = xe_mmio_wait32(gt, HUC_KERNEL_LOAD_INFO, HUC_LOAD_SUCCESSFUL,
-                            HUC_LOAD_SUCCESSFUL, 100000, NULL, false);
+       ret = xe_mmio_wait32(gt, huc_auth_modes[type].reg, huc_auth_modes[type].val,
+                            huc_auth_modes[type].val, 100000, NULL, false);
        if (ret) {
                drm_err(&xe->drm, "HuC: Firmware not verified %d\n", ret);
                goto fail;
        }
 
        xe_uc_fw_change_status(&huc->fw, XE_UC_FIRMWARE_RUNNING);
-       drm_dbg(&xe->drm, "HuC authenticated\n");
+       drm_dbg(&xe->drm, "HuC authenticated via %s\n", huc_auth_modes[type].name);
 
        return 0;
 
 fail:
-       drm_err(&xe->drm, "HuC authentication failed %d\n", ret);
+       drm_err(&xe->drm, "HuC: Auth via %s failed: %d\n",
+               huc_auth_modes[type].name, ret);
        xe_uc_fw_change_status(&huc->fw, XE_UC_FIRMWARE_LOAD_FAIL);
 
        return ret;
index 5802c43b6ce21d67fd36980ca0138351da3413ba..b8c387f14b8ef51568ece524100d3245239fa9f2 100644 (file)
 
 struct drm_printer;
 
+enum xe_huc_auth_types {
+       XE_HUC_AUTH_VIA_GUC = 0,
+       XE_HUC_AUTH_VIA_GSC,
+       XE_HUC_AUTH_TYPES_COUNT
+};
+
 int xe_huc_init(struct xe_huc *huc);
 int xe_huc_upload(struct xe_huc *huc);
-int xe_huc_auth(struct xe_huc *huc);
+int xe_huc_auth(struct xe_huc *huc, enum xe_huc_auth_types type);
 void xe_huc_sanitize(struct xe_huc *huc);
 void xe_huc_print_info(struct xe_huc *huc, struct drm_printer *p);
 
index 72a7b3c2577ddb0d799c7f2de116075383089764..25e1ddfd2f86a79936e9be747bc2ce7071d26698 100644 (file)
@@ -176,7 +176,7 @@ int xe_uc_init_hw(struct xe_uc *uc)
                return ret;
 
        /* We don't fail the driver load if HuC fails to auth, but let's warn */
-       ret = xe_huc_auth(&uc->huc);
+       ret = xe_huc_auth(&uc->huc, XE_HUC_AUTH_VIA_GUC);
        xe_gt_assert(uc_to_gt(uc), !ret);
 
        /* GSC load is async */