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>
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 */
494536int 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
516570static 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}
0 commit comments