Skip to content

Commit

Permalink
drm/xe/huc: Prepare for 2-step HuC authentication
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Daniele Ceraolo Spurio authored and Rodrigo Vivi committed Dec 21, 2023
1 parent 2a70bbe commit 7ce5716
Show file tree
Hide file tree
Showing 4 changed files with 47 additions and 12 deletions.
2 changes: 2 additions & 0 deletions drivers/gpu/drm/xe/regs/xe_gsc_regs.h
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
47 changes: 37 additions & 10 deletions drivers/gpu/drm/xe/xe_huc.c
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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);
Expand All @@ -84,36 +103,44 @@ 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;
}

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;
Expand Down
8 changes: 7 additions & 1 deletion drivers/gpu/drm/xe/xe_huc.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,15 @@

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);

Expand Down
2 changes: 1 addition & 1 deletion drivers/gpu/drm/xe/xe_uc.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand Down

0 comments on commit 7ce5716

Please sign in to comment.