Skip to content

Commit 98d2722

Browse files
committed
drm/i915/huc: differentiate the 2 steps of the MTL HuC auth flow
Before we add the second step of the MTL HuC auth (via GSC), we need to have the ability to differentiate between them. To do so, the huc authentication check is duplicated for GuC and GSC auth, with GSC-enabled binaries being considered fully authenticated only after the GSC auth step. To report the difference between the 2 auth steps, a new case is added to the HuC getparam. This way, the clear media driver can start submitting before full auth, as partial auth is enough for those workloads. v2: fix authentication status check for DG2 v3: add a better comment at the top of the HuC file to explain the different approaches to load and auth (John) v4: update call to intel_huc_is_authenticated in the pxp code to check for GSC authentication v5: drop references to meu and esclamation mark in huc_auth print (John) 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: Alan Previn <alan.previn.teres.alexis@intel.com> #v2 Reviewed-by: John Harrison <John.C.Harrison@Intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20230531235415.1467475-5-daniele.ceraolospurio@intel.com
1 parent 6a9b6c4 commit 98d2722

6 files changed

Lines changed: 104 additions & 35 deletions

File tree

drivers/gpu/drm/i915/gt/uc/intel_huc.c

Lines changed: 84 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include "intel_huc.h"
1111
#include "intel_huc_print.h"
1212
#include "i915_drv.h"
13+
#include "i915_reg.h"
1314

1415
#include <linux/device/bus.h>
1516
#include <linux/mei_aux.h>
@@ -22,15 +23,23 @@
2223
* capabilities by adding HuC specific commands to batch buffers.
2324
*
2425
* The kernel driver is only responsible for loading the HuC firmware and
25-
* triggering its security authentication, which is performed by the GuC on
26-
* older platforms and by the GSC on newer ones. For the GuC to correctly
27-
* perform the authentication, the HuC binary must be loaded before the GuC one.
26+
* triggering its security authentication. This is done differently depending
27+
* on the platform:
28+
* - older platforms (from Gen9 to most Gen12s): the load is performed via DMA
29+
* and the authentication via GuC
30+
* - DG2: load and authentication are both performed via GSC.
31+
* - MTL and newer platforms: the load is performed via DMA (same as with
32+
* not-DG2 older platforms), while the authentication is done in 2-steps,
33+
* a first auth for clear-media workloads via GuC and a second one for all
34+
* workloads via GSC.
35+
* On platforms where the GuC does the authentication, to correctly do so the
36+
* HuC binary must be loaded before the GuC one.
2837
* Loading the HuC is optional; however, not using the HuC might negatively
2938
* impact power usage and/or performance of media workloads, depending on the
3039
* use-cases.
3140
* HuC must be reloaded on events that cause the WOPCM to lose its contents
32-
* (S3/S4, FLR); GuC-authenticated HuC must also be reloaded on GuC/GT reset,
33-
* while GSC-managed HuC will survive that.
41+
* (S3/S4, FLR); on older platforms the HuC must also be reloaded on GuC/GT
42+
* reset, while on newer ones it will survive that.
3443
*
3544
* See https://github.com/intel/media-driver for the latest details on HuC
3645
* functionality.
@@ -106,7 +115,7 @@ static enum hrtimer_restart huc_delayed_load_timer_callback(struct hrtimer *hrti
106115
{
107116
struct intel_huc *huc = container_of(hrtimer, struct intel_huc, delayed_load.timer);
108117

109-
if (!intel_huc_is_authenticated(huc)) {
118+
if (!intel_huc_is_authenticated(huc, INTEL_HUC_AUTH_BY_GSC)) {
110119
if (huc->delayed_load.status == INTEL_HUC_WAITING_ON_GSC)
111120
huc_notice(huc, "timed out waiting for MEI GSC\n");
112121
else if (huc->delayed_load.status == INTEL_HUC_WAITING_ON_PXP)
@@ -124,7 +133,7 @@ static void huc_delayed_load_start(struct intel_huc *huc)
124133
{
125134
ktime_t delay;
126135

127-
GEM_BUG_ON(intel_huc_is_authenticated(huc));
136+
GEM_BUG_ON(intel_huc_is_authenticated(huc, INTEL_HUC_AUTH_BY_GSC));
128137

129138
/*
130139
* On resume we don't have to wait for MEI-GSC to be re-probed, but we
@@ -284,13 +293,23 @@ void intel_huc_init_early(struct intel_huc *huc)
284293
}
285294

286295
if (GRAPHICS_VER(i915) >= 11) {
287-
huc->status.reg = GEN11_HUC_KERNEL_LOAD_INFO;
288-
huc->status.mask = HUC_LOAD_SUCCESSFUL;
289-
huc->status.value = HUC_LOAD_SUCCESSFUL;
296+
huc->status[INTEL_HUC_AUTH_BY_GUC].reg = GEN11_HUC_KERNEL_LOAD_INFO;
297+
huc->status[INTEL_HUC_AUTH_BY_GUC].mask = HUC_LOAD_SUCCESSFUL;
298+
huc->status[INTEL_HUC_AUTH_BY_GUC].value = HUC_LOAD_SUCCESSFUL;
290299
} else {
291-
huc->status.reg = HUC_STATUS2;
292-
huc->status.mask = HUC_FW_VERIFIED;
293-
huc->status.value = HUC_FW_VERIFIED;
300+
huc->status[INTEL_HUC_AUTH_BY_GUC].reg = HUC_STATUS2;
301+
huc->status[INTEL_HUC_AUTH_BY_GUC].mask = HUC_FW_VERIFIED;
302+
huc->status[INTEL_HUC_AUTH_BY_GUC].value = HUC_FW_VERIFIED;
303+
}
304+
305+
if (IS_DG2(i915)) {
306+
huc->status[INTEL_HUC_AUTH_BY_GSC].reg = GEN11_HUC_KERNEL_LOAD_INFO;
307+
huc->status[INTEL_HUC_AUTH_BY_GSC].mask = HUC_LOAD_SUCCESSFUL;
308+
huc->status[INTEL_HUC_AUTH_BY_GSC].value = HUC_LOAD_SUCCESSFUL;
309+
} else {
310+
huc->status[INTEL_HUC_AUTH_BY_GSC].reg = HECI_FWSTS5(MTL_GSC_HECI1_BASE);
311+
huc->status[INTEL_HUC_AUTH_BY_GSC].mask = HECI_FWSTS5_HUC_AUTH_DONE;
312+
huc->status[INTEL_HUC_AUTH_BY_GSC].value = HECI_FWSTS5_HUC_AUTH_DONE;
294313
}
295314
}
296315

@@ -397,28 +416,38 @@ void intel_huc_suspend(struct intel_huc *huc)
397416
delayed_huc_load_complete(huc);
398417
}
399418

400-
int intel_huc_wait_for_auth_complete(struct intel_huc *huc)
419+
static const char *auth_mode_string(struct intel_huc *huc,
420+
enum intel_huc_authentication_type type)
421+
{
422+
bool partial = huc->fw.has_gsc_headers && type == INTEL_HUC_AUTH_BY_GUC;
423+
424+
return partial ? "clear media" : "all workloads";
425+
}
426+
427+
int intel_huc_wait_for_auth_complete(struct intel_huc *huc,
428+
enum intel_huc_authentication_type type)
401429
{
402430
struct intel_gt *gt = huc_to_gt(huc);
403431
int ret;
404432

405433
ret = __intel_wait_for_register(gt->uncore,
406-
huc->status.reg,
407-
huc->status.mask,
408-
huc->status.value,
434+
huc->status[type].reg,
435+
huc->status[type].mask,
436+
huc->status[type].value,
409437
2, 50, NULL);
410438

411439
/* mark the load process as complete even if the wait failed */
412440
delayed_huc_load_complete(huc);
413441

414442
if (ret) {
415-
huc_err(huc, "firmware not verified %pe\n", ERR_PTR(ret));
443+
huc_err(huc, "firmware not verified for %s: %pe\n",
444+
auth_mode_string(huc, type), ERR_PTR(ret));
416445
intel_uc_fw_change_status(&huc->fw, INTEL_UC_FIRMWARE_LOAD_FAIL);
417446
return ret;
418447
}
419448

420449
intel_uc_fw_change_status(&huc->fw, INTEL_UC_FIRMWARE_RUNNING);
421-
huc_info(huc, "authenticated!\n");
450+
huc_info(huc, "authenticated for %s\n", auth_mode_string(huc, type));
422451
return 0;
423452
}
424453

@@ -458,7 +487,7 @@ int intel_huc_auth(struct intel_huc *huc)
458487
}
459488

460489
/* Check authentication status, it should be done by now */
461-
ret = intel_huc_wait_for_auth_complete(huc);
490+
ret = intel_huc_wait_for_auth_complete(huc, INTEL_HUC_AUTH_BY_GUC);
462491
if (ret)
463492
goto fail;
464493

@@ -469,16 +498,29 @@ int intel_huc_auth(struct intel_huc *huc)
469498
return ret;
470499
}
471500

472-
bool intel_huc_is_authenticated(struct intel_huc *huc)
501+
bool intel_huc_is_authenticated(struct intel_huc *huc,
502+
enum intel_huc_authentication_type type)
473503
{
474504
struct intel_gt *gt = huc_to_gt(huc);
475505
intel_wakeref_t wakeref;
476506
u32 status = 0;
477507

478508
with_intel_runtime_pm(gt->uncore->rpm, wakeref)
479-
status = intel_uncore_read(gt->uncore, huc->status.reg);
509+
status = intel_uncore_read(gt->uncore, huc->status[type].reg);
480510

481-
return (status & huc->status.mask) == huc->status.value;
511+
return (status & huc->status[type].mask) == huc->status[type].value;
512+
}
513+
514+
static bool huc_is_fully_authenticated(struct intel_huc *huc)
515+
{
516+
struct intel_uc_fw *huc_fw = &huc->fw;
517+
518+
if (!huc_fw->has_gsc_headers)
519+
return intel_huc_is_authenticated(huc, INTEL_HUC_AUTH_BY_GUC);
520+
else if (intel_huc_is_loaded_by_gsc(huc) || HAS_ENGINE(huc_to_gt(huc), GSC0))
521+
return intel_huc_is_authenticated(huc, INTEL_HUC_AUTH_BY_GSC);
522+
else
523+
return false;
482524
}
483525

484526
/**
@@ -493,7 +535,9 @@ bool intel_huc_is_authenticated(struct intel_huc *huc)
493535
*/
494536
int intel_huc_check_status(struct intel_huc *huc)
495537
{
496-
switch (__intel_uc_fw_status(&huc->fw)) {
538+
struct intel_uc_fw *huc_fw = &huc->fw;
539+
540+
switch (__intel_uc_fw_status(huc_fw)) {
497541
case INTEL_UC_FIRMWARE_NOT_SUPPORTED:
498542
return -ENODEV;
499543
case INTEL_UC_FIRMWARE_DISABLED:
@@ -510,7 +554,17 @@ int intel_huc_check_status(struct intel_huc *huc)
510554
break;
511555
}
512556

513-
return intel_huc_is_authenticated(huc);
557+
/*
558+
* GSC-enabled binaries loaded via DMA are first partially
559+
* authenticated by GuC and then fully authenticated by GSC
560+
*/
561+
if (huc_is_fully_authenticated(huc))
562+
return 1; /* full auth */
563+
else if (huc_fw->has_gsc_headers && !intel_huc_is_loaded_by_gsc(huc) &&
564+
intel_huc_is_authenticated(huc, INTEL_HUC_AUTH_BY_GUC))
565+
return 2; /* clear media only */
566+
else
567+
return 0;
514568
}
515569

516570
static bool huc_has_delayed_load(struct intel_huc *huc)
@@ -524,7 +578,10 @@ void intel_huc_update_auth_status(struct intel_huc *huc)
524578
if (!intel_uc_fw_is_loadable(&huc->fw))
525579
return;
526580

527-
if (intel_huc_is_authenticated(huc))
581+
if (!huc->fw.has_gsc_headers)
582+
return;
583+
584+
if (huc_is_fully_authenticated(huc))
528585
intel_uc_fw_change_status(&huc->fw,
529586
INTEL_UC_FIRMWARE_RUNNING);
530587
else if (huc_has_delayed_load(huc))
@@ -557,5 +614,5 @@ void intel_huc_load_status(struct intel_huc *huc, struct drm_printer *p)
557614

558615
with_intel_runtime_pm(gt->uncore->rpm, wakeref)
559616
drm_printf(p, "HuC status: 0x%08x\n",
560-
intel_uncore_read(gt->uncore, huc->status.reg));
617+
intel_uncore_read(gt->uncore, huc->status[INTEL_HUC_AUTH_BY_GUC].reg));
561618
}

drivers/gpu/drm/i915/gt/uc/intel_huc.h

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,12 @@ enum intel_huc_delayed_load_status {
2222
INTEL_HUC_DELAYED_LOAD_ERROR,
2323
};
2424

25+
enum intel_huc_authentication_type {
26+
INTEL_HUC_AUTH_BY_GUC = 0,
27+
INTEL_HUC_AUTH_BY_GSC,
28+
INTEL_HUC_AUTH_MAX_MODES
29+
};
30+
2531
struct intel_huc {
2632
/* Generic uC firmware management */
2733
struct intel_uc_fw fw;
@@ -31,7 +37,7 @@ struct intel_huc {
3137
i915_reg_t reg;
3238
u32 mask;
3339
u32 value;
34-
} status;
40+
} status[INTEL_HUC_AUTH_MAX_MODES];
3541

3642
struct {
3743
struct i915_sw_fence fence;
@@ -49,10 +55,12 @@ int intel_huc_init(struct intel_huc *huc);
4955
void intel_huc_fini(struct intel_huc *huc);
5056
void intel_huc_suspend(struct intel_huc *huc);
5157
int intel_huc_auth(struct intel_huc *huc);
52-
int intel_huc_wait_for_auth_complete(struct intel_huc *huc);
58+
int intel_huc_wait_for_auth_complete(struct intel_huc *huc,
59+
enum intel_huc_authentication_type type);
60+
bool intel_huc_is_authenticated(struct intel_huc *huc,
61+
enum intel_huc_authentication_type type);
5362
int intel_huc_check_status(struct intel_huc *huc);
5463
void intel_huc_update_auth_status(struct intel_huc *huc);
55-
bool intel_huc_is_authenticated(struct intel_huc *huc);
5664

5765
void intel_huc_register_gsc_notifier(struct intel_huc *huc, const struct bus_type *bus);
5866
void intel_huc_unregister_gsc_notifier(struct intel_huc *huc, const struct bus_type *bus);
@@ -81,7 +89,7 @@ static inline bool intel_huc_is_loaded_by_gsc(const struct intel_huc *huc)
8189
static inline bool intel_huc_wait_required(struct intel_huc *huc)
8290
{
8391
return intel_huc_is_used(huc) && intel_huc_is_loaded_by_gsc(huc) &&
84-
!intel_huc_is_authenticated(huc);
92+
!intel_huc_is_authenticated(huc, INTEL_HUC_AUTH_BY_GSC);
8593
}
8694

8795
void intel_huc_load_status(struct intel_huc *huc, struct drm_printer *p);

drivers/gpu/drm/i915/gt/uc/intel_huc_fw.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,7 @@ int intel_huc_fw_load_and_auth_via_gsc(struct intel_huc *huc)
161161
* component gets re-bound and this function called again. If so, just
162162
* mark the HuC as loaded.
163163
*/
164-
if (intel_huc_is_authenticated(huc)) {
164+
if (intel_huc_is_authenticated(huc, INTEL_HUC_AUTH_BY_GSC)) {
165165
intel_uc_fw_change_status(&huc->fw, INTEL_UC_FIRMWARE_RUNNING);
166166
return 0;
167167
}
@@ -174,7 +174,7 @@ int intel_huc_fw_load_and_auth_via_gsc(struct intel_huc *huc)
174174

175175
intel_uc_fw_change_status(&huc->fw, INTEL_UC_FIRMWARE_TRANSFERRED);
176176

177-
return intel_huc_wait_for_auth_complete(huc);
177+
return intel_huc_wait_for_auth_complete(huc, INTEL_HUC_AUTH_BY_GSC);
178178
}
179179

180180
/**

drivers/gpu/drm/i915/i915_reg.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -941,6 +941,9 @@
941941
#define HECI_H_GS1(base) _MMIO((base) + 0xc4c)
942942
#define HECI_H_GS1_ER_PREP REG_BIT(0)
943943

944+
#define HECI_FWSTS5(base) _MMIO((base) + 0xc68)
945+
#define HECI_FWSTS5_HUC_AUTH_DONE (1 << 19)
946+
944947
#define HSW_GTT_CACHE_EN _MMIO(0x4024)
945948
#define GTT_CACHE_EN_ALL 0xF0007FFF
946949
#define GEN7_WR_WATERMARK _MMIO(0x4028)

drivers/gpu/drm/i915/pxp/intel_pxp_gsccs.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -196,7 +196,7 @@ bool intel_pxp_gsccs_is_ready_for_sessions(struct intel_pxp *pxp)
196196
* gsc-proxy init flow (the last set of dependencies that
197197
* are out of order) will suffice.
198198
*/
199-
if (intel_huc_is_authenticated(&pxp->ctrl_gt->uc.huc) &&
199+
if (intel_huc_is_authenticated(&pxp->ctrl_gt->uc.huc, INTEL_HUC_AUTH_BY_GSC) &&
200200
intel_gsc_uc_fw_proxy_init_done(&pxp->ctrl_gt->uc.gsc))
201201
return true;
202202

include/uapi/drm/i915_drm.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -674,7 +674,8 @@ typedef struct drm_i915_irq_wait {
674674
* If the IOCTL is successful, the returned parameter will be set to one of the
675675
* following values:
676676
* * 0 if HuC firmware load is not complete,
677-
* * 1 if HuC firmware is authenticated and running.
677+
* * 1 if HuC firmware is loaded and fully authenticated,
678+
* * 2 if HuC firmware is loaded and authenticated for clear media only
678679
*/
679680
#define I915_PARAM_HUC_STATUS 42
680681

0 commit comments

Comments
 (0)