Skip to content

Commit 08872cb

Browse files
committed
drm/i915/mtl/huc: auth HuC via GSC
The full authentication via the GSC requires an heci packet submission to the GSC FW via the GSC CS. The GSC has new PXP command for this (literally called NEW_HUC_AUTH). The intel_huc_auth function is also updated to handle both authentication types. v2: check that the GuC auth for clear media has completed before proceding with the full auth v3: use a define for the object size (Alan) Signed-off-by: Daniele Ceraolo Spurio <daniele.ceraolospurio@intel.com> Cc: Alan Previn <alan.previn.teres.alexis@intel.com> Reviewed-by: Alan Previn <alan.previn.teres.alexis@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20230531235415.1467475-6-daniele.ceraolospurio@intel.com
1 parent 98d2722 commit 08872cb

9 files changed

Lines changed: 183 additions & 22 deletions

File tree

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

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,13 +29,32 @@ static void gsc_work(struct work_struct *work)
2929

3030
if (actions & GSC_ACTION_FW_LOAD) {
3131
ret = intel_gsc_uc_fw_upload(gsc);
32-
if (ret == -EEXIST) /* skip proxy if not a new load */
33-
actions &= ~GSC_ACTION_FW_LOAD;
34-
else if (ret)
32+
if (!ret)
33+
/* setup proxy on a new load */
34+
actions |= GSC_ACTION_SW_PROXY;
35+
else if (ret != -EEXIST)
3536
goto out_put;
37+
38+
/*
39+
* The HuC auth can be done both before or after the proxy init;
40+
* if done after, a proxy request will be issued and must be
41+
* serviced before the authentication can complete.
42+
* Since this worker also handles proxy requests, we can't
43+
* perform an action that requires the proxy from within it and
44+
* then stall waiting for it, because we'd be blocking the
45+
* service path. Therefore, it is easier for us to load HuC
46+
* first and do proxy later. The GSC will ack the HuC auth and
47+
* then send the HuC proxy request as part of the proxy init
48+
* flow.
49+
* Note that we can only do the GSC auth if the GuC auth was
50+
* successful.
51+
*/
52+
if (intel_uc_uses_huc(&gt->uc) &&
53+
intel_huc_is_authenticated(&gt->uc.huc, INTEL_HUC_AUTH_BY_GUC))
54+
intel_huc_auth(&gt->uc.huc, INTEL_HUC_AUTH_BY_GSC);
3655
}
3756

38-
if (actions & (GSC_ACTION_FW_LOAD | GSC_ACTION_SW_PROXY)) {
57+
if (actions & GSC_ACTION_SW_PROXY) {
3958
if (!intel_gsc_uc_fw_init_done(gsc)) {
4059
gt_err(gt, "Proxy request received with GSC not loaded!\n");
4160
goto out_put;

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ void intel_gsc_uc_heci_cmd_emit_mtl_header(struct intel_gsc_mtl_header *header,
9999
u64 host_session_id)
100100
{
101101
host_session_id &= ~HOST_SESSION_MASK;
102-
if (heci_client_id == HECI_MEADDRESS_PXP)
102+
if (host_session_id && heci_client_id == HECI_MEADDRESS_PXP)
103103
host_session_id |= HOST_SESSION_PXP_SINGLE;
104104

105105
header->validity_marker = GSC_HECI_VALIDITY_MARKER;

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

Lines changed: 42 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include "intel_huc_print.h"
1212
#include "i915_drv.h"
1313
#include "i915_reg.h"
14+
#include "pxp/intel_pxp_cmd_interface_43.h"
1415

1516
#include <linux/device/bus.h>
1617
#include <linux/mei_aux.h>
@@ -371,20 +372,36 @@ static int check_huc_loading_mode(struct intel_huc *huc)
371372

372373
int intel_huc_init(struct intel_huc *huc)
373374
{
375+
struct intel_gt *gt = huc_to_gt(huc);
374376
int err;
375377

376378
err = check_huc_loading_mode(huc);
377379
if (err)
378380
goto out;
379381

382+
if (HAS_ENGINE(gt, GSC0)) {
383+
struct i915_vma *vma;
384+
385+
vma = intel_guc_allocate_vma(&gt->uc.guc, PXP43_HUC_AUTH_INOUT_SIZE * 2);
386+
if (IS_ERR(vma)) {
387+
huc_info(huc, "Failed to allocate heci pkt\n");
388+
goto out;
389+
}
390+
391+
huc->heci_pkt = vma;
392+
}
393+
380394
err = intel_uc_fw_init(&huc->fw);
381395
if (err)
382-
goto out;
396+
goto out_pkt;
383397

384398
intel_uc_fw_change_status(&huc->fw, INTEL_UC_FIRMWARE_LOADABLE);
385399

386400
return 0;
387401

402+
out_pkt:
403+
if (huc->heci_pkt)
404+
i915_vma_unpin_and_release(&huc->heci_pkt, 0);
388405
out:
389406
intel_uc_fw_change_status(&huc->fw, INTEL_UC_FIRMWARE_INIT_FAIL);
390407
huc_info(huc, "initialization failed %pe\n", ERR_PTR(err));
@@ -399,6 +416,9 @@ void intel_huc_fini(struct intel_huc *huc)
399416
*/
400417
delayed_huc_load_fini(huc);
401418

419+
if (huc->heci_pkt)
420+
i915_vma_unpin_and_release(&huc->heci_pkt, 0);
421+
402422
if (intel_uc_fw_is_loadable(&huc->fw))
403423
intel_uc_fw_fini(&huc->fw);
404424
}
@@ -454,14 +474,15 @@ int intel_huc_wait_for_auth_complete(struct intel_huc *huc,
454474
/**
455475
* intel_huc_auth() - Authenticate HuC uCode
456476
* @huc: intel_huc structure
477+
* @type: authentication type (via GuC or via GSC)
457478
*
458479
* Called after HuC and GuC firmware loading during intel_uc_init_hw().
459480
*
460481
* This function invokes the GuC action to authenticate the HuC firmware,
461482
* passing the offset of the RSA signature to intel_guc_auth_huc(). It then
462483
* waits for up to 50ms for firmware verification ACK.
463484
*/
464-
int intel_huc_auth(struct intel_huc *huc)
485+
int intel_huc_auth(struct intel_huc *huc, enum intel_huc_authentication_type type)
465486
{
466487
struct intel_gt *gt = huc_to_gt(huc);
467488
struct intel_guc *guc = &gt->uc.guc;
@@ -470,31 +491,41 @@ int intel_huc_auth(struct intel_huc *huc)
470491
if (!intel_uc_fw_is_loaded(&huc->fw))
471492
return -ENOEXEC;
472493

473-
/* GSC will do the auth */
494+
/* GSC will do the auth with the load */
474495
if (intel_huc_is_loaded_by_gsc(huc))
475496
return -ENODEV;
476497

498+
if (intel_huc_is_authenticated(huc, type))
499+
return -EEXIST;
500+
477501
ret = i915_inject_probe_error(gt->i915, -ENXIO);
478502
if (ret)
479503
goto fail;
480504

481-
GEM_BUG_ON(intel_uc_fw_is_running(&huc->fw));
482-
483-
ret = intel_guc_auth_huc(guc, intel_guc_ggtt_offset(guc, huc->fw.rsa_data));
484-
if (ret) {
485-
huc_err(huc, "authentication by GuC failed %pe\n", ERR_PTR(ret));
486-
goto fail;
505+
switch (type) {
506+
case INTEL_HUC_AUTH_BY_GUC:
507+
ret = intel_guc_auth_huc(guc, intel_guc_ggtt_offset(guc, huc->fw.rsa_data));
508+
break;
509+
case INTEL_HUC_AUTH_BY_GSC:
510+
ret = intel_huc_fw_auth_via_gsccs(huc);
511+
break;
512+
default:
513+
MISSING_CASE(type);
514+
ret = -EINVAL;
487515
}
516+
if (ret)
517+
goto fail;
488518

489519
/* Check authentication status, it should be done by now */
490-
ret = intel_huc_wait_for_auth_complete(huc, INTEL_HUC_AUTH_BY_GUC);
520+
ret = intel_huc_wait_for_auth_complete(huc, type);
491521
if (ret)
492522
goto fail;
493523

494524
return 0;
495525

496526
fail:
497-
huc_probe_error(huc, "authentication failed %pe\n", ERR_PTR(ret));
527+
huc_probe_error(huc, "%s authentication failed %pe\n",
528+
auth_mode_string(huc, type), ERR_PTR(ret));
498529
return ret;
499530
}
500531

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

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include <linux/hrtimer.h>
1616

1717
struct bus_type;
18+
struct i915_vma;
1819

1920
enum intel_huc_delayed_load_status {
2021
INTEL_HUC_WAITING_ON_GSC = 0,
@@ -46,6 +47,9 @@ struct intel_huc {
4647
enum intel_huc_delayed_load_status status;
4748
} delayed_load;
4849

50+
/* for load via GSCCS */
51+
struct i915_vma *heci_pkt;
52+
4953
bool loaded_via_gsc;
5054
};
5155

@@ -54,7 +58,7 @@ void intel_huc_init_early(struct intel_huc *huc);
5458
int intel_huc_init(struct intel_huc *huc);
5559
void intel_huc_fini(struct intel_huc *huc);
5660
void intel_huc_suspend(struct intel_huc *huc);
57-
int intel_huc_auth(struct intel_huc *huc);
61+
int intel_huc_auth(struct intel_huc *huc, enum intel_huc_authentication_type type);
5862
int intel_huc_wait_for_auth_complete(struct intel_huc *huc,
5963
enum intel_huc_authentication_type type);
6064
bool intel_huc_is_authenticated(struct intel_huc *huc,

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

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,106 @@
66
#include "gt/intel_gsc.h"
77
#include "gt/intel_gt.h"
88
#include "intel_gsc_binary_headers.h"
9+
#include "intel_gsc_uc_heci_cmd_submit.h"
910
#include "intel_huc.h"
1011
#include "intel_huc_fw.h"
1112
#include "intel_huc_print.h"
1213
#include "i915_drv.h"
1314
#include "pxp/intel_pxp_huc.h"
15+
#include "pxp/intel_pxp_cmd_interface_43.h"
16+
17+
struct mtl_huc_auth_msg_in {
18+
struct intel_gsc_mtl_header header;
19+
struct pxp43_new_huc_auth_in huc_in;
20+
} __packed;
21+
22+
struct mtl_huc_auth_msg_out {
23+
struct intel_gsc_mtl_header header;
24+
struct pxp43_huc_auth_out huc_out;
25+
} __packed;
26+
27+
int intel_huc_fw_auth_via_gsccs(struct intel_huc *huc)
28+
{
29+
struct intel_gt *gt = huc_to_gt(huc);
30+
struct drm_i915_private *i915 = gt->i915;
31+
struct drm_i915_gem_object *obj;
32+
struct mtl_huc_auth_msg_in *msg_in;
33+
struct mtl_huc_auth_msg_out *msg_out;
34+
void *pkt_vaddr;
35+
u64 pkt_offset;
36+
int retry = 5;
37+
int err = 0;
38+
39+
if (!huc->heci_pkt)
40+
return -ENODEV;
41+
42+
obj = huc->heci_pkt->obj;
43+
pkt_offset = i915_ggtt_offset(huc->heci_pkt);
44+
45+
pkt_vaddr = i915_gem_object_pin_map_unlocked(obj,
46+
i915_coherent_map_type(i915, obj, true));
47+
if (IS_ERR(pkt_vaddr))
48+
return PTR_ERR(pkt_vaddr);
49+
50+
msg_in = pkt_vaddr;
51+
msg_out = pkt_vaddr + PXP43_HUC_AUTH_INOUT_SIZE;
52+
53+
intel_gsc_uc_heci_cmd_emit_mtl_header(&msg_in->header,
54+
HECI_MEADDRESS_PXP,
55+
sizeof(*msg_in), 0);
56+
57+
msg_in->huc_in.header.api_version = PXP_APIVER(4, 3);
58+
msg_in->huc_in.header.command_id = PXP43_CMDID_NEW_HUC_AUTH;
59+
msg_in->huc_in.header.status = 0;
60+
msg_in->huc_in.header.buffer_len = sizeof(msg_in->huc_in) -
61+
sizeof(msg_in->huc_in.header);
62+
msg_in->huc_in.huc_base_address = huc->fw.vma_res.start;
63+
msg_in->huc_in.huc_size = huc->fw.obj->base.size;
64+
65+
do {
66+
err = intel_gsc_uc_heci_cmd_submit_packet(&gt->uc.gsc,
67+
pkt_offset, sizeof(*msg_in),
68+
pkt_offset + PXP43_HUC_AUTH_INOUT_SIZE,
69+
PXP43_HUC_AUTH_INOUT_SIZE);
70+
if (err) {
71+
huc_err(huc, "failed to submit GSC request to auth: %d\n", err);
72+
goto out_unpin;
73+
}
74+
75+
if (msg_out->header.flags & GSC_OUTFLAG_MSG_PENDING) {
76+
msg_in->header.gsc_message_handle = msg_out->header.gsc_message_handle;
77+
err = -EBUSY;
78+
msleep(50);
79+
}
80+
} while (--retry && err == -EBUSY);
81+
82+
if (err)
83+
goto out_unpin;
84+
85+
if (msg_out->header.message_size != sizeof(*msg_out)) {
86+
huc_err(huc, "invalid GSC reply length %u [expected %zu]\n",
87+
msg_out->header.message_size, sizeof(*msg_out));
88+
err = -EPROTO;
89+
goto out_unpin;
90+
}
91+
92+
/*
93+
* The GSC will return PXP_STATUS_OP_NOT_PERMITTED if the HuC is already
94+
* loaded. If the same error is ever returned with HuC not loaded we'll
95+
* still catch it when we check the authentication bit later.
96+
*/
97+
if (msg_out->huc_out.header.status != PXP_STATUS_SUCCESS &&
98+
msg_out->huc_out.header.status != PXP_STATUS_OP_NOT_PERMITTED) {
99+
huc_err(huc, "auth failed with GSC error = 0x%x\n",
100+
msg_out->huc_out.header.status);
101+
err = -EIO;
102+
goto out_unpin;
103+
}
104+
105+
out_unpin:
106+
i915_gem_object_unpin_map(obj);
107+
return err;
108+
}
14109

15110
static void get_version_from_gsc_manifest(struct intel_uc_fw_ver *ver, const void *data)
16111
{

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ struct intel_uc_fw;
1212
#include <linux/types.h>
1313

1414
int intel_huc_fw_load_and_auth_via_gsc(struct intel_huc *huc);
15+
int intel_huc_fw_auth_via_gsccs(struct intel_huc *huc);
1516
int intel_huc_fw_upload(struct intel_huc *huc);
1617
int intel_huc_fw_get_binary_info(struct intel_uc_fw *huc_fw, const void *data, size_t size);
1718
#endif

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -538,7 +538,7 @@ static int __uc_init_hw(struct intel_uc *uc)
538538
if (intel_huc_is_loaded_by_gsc(huc))
539539
intel_huc_update_auth_status(huc);
540540
else
541-
intel_huc_auth(huc);
541+
intel_huc_auth(huc, INTEL_HUC_AUTH_BY_GUC);
542542

543543
if (intel_uc_uses_guc_submission(uc)) {
544544
ret = intel_guc_submission_enable(guc);

drivers/gpu/drm/i915/pxp/intel_pxp_cmd_interface_43.h

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,19 +11,30 @@
1111

1212
/* PXP-Cmd-Op definitions */
1313
#define PXP43_CMDID_START_HUC_AUTH 0x0000003A
14+
#define PXP43_CMDID_NEW_HUC_AUTH 0x0000003F /* MTL+ */
1415
#define PXP43_CMDID_INIT_SESSION 0x00000036
1516

1617
/* PXP-Packet sizes for MTL's GSCCS-HECI instruction */
1718
#define PXP43_MAX_HECI_INOUT_SIZE (SZ_32K)
1819

19-
/* PXP-Input-Packet: HUC-Authentication */
20+
/* PXP-Packet size for MTL's NEW_HUC_AUTH instruction */
21+
#define PXP43_HUC_AUTH_INOUT_SIZE (SZ_4K)
22+
23+
/* PXP-Input-Packet: HUC Load and Authentication */
2024
struct pxp43_start_huc_auth_in {
2125
struct pxp_cmd_header header;
2226
__le64 huc_base_address;
2327
} __packed;
2428

25-
/* PXP-Output-Packet: HUC-Authentication */
26-
struct pxp43_start_huc_auth_out {
29+
/* PXP-Input-Packet: HUC Auth-only */
30+
struct pxp43_new_huc_auth_in {
31+
struct pxp_cmd_header header;
32+
u64 huc_base_address;
33+
u32 huc_size;
34+
} __packed;
35+
36+
/* PXP-Output-Packet: HUC Load and Authentication or Auth-only */
37+
struct pxp43_huc_auth_out {
2738
struct pxp_cmd_header header;
2839
} __packed;
2940

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ int intel_pxp_huc_load_and_auth(struct intel_pxp *pxp)
1919
struct intel_gt *gt;
2020
struct intel_huc *huc;
2121
struct pxp43_start_huc_auth_in huc_in = {0};
22-
struct pxp43_start_huc_auth_out huc_out = {0};
22+
struct pxp43_huc_auth_out huc_out = {0};
2323
dma_addr_t huc_phys_addr;
2424
u8 client_id = 0;
2525
u8 fence_id = 0;

0 commit comments

Comments
 (0)