Skip to content

Commit 96e84a2

Browse files
committed
drm/xe/pxp: Add GSC session invalidation support
After a session is terminated, we need to inform the GSC so that it can clean up its side of the allocation. This is done by sending an invalidation command with the session ID. The invalidation will be triggered in response to a termination, interrupt, whose handling is coming in the next patch in the series. v2: Better comment and error messages (John) Signed-off-by: Daniele Ceraolo Spurio <daniele.ceraolospurio@intel.com> Cc: John Harrison <John.C.Harrison@Intel.com> Reviewed-by: John Harrison <John.C.Harrison@Intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20250129174140.948829-5-daniele.ceraolospurio@intel.com
1 parent f0c0667 commit 96e84a2

File tree

3 files changed

+244
-0
lines changed

3 files changed

+244
-0
lines changed

drivers/gpu/drm/xe/abi/gsc_pxp_commands_abi.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ enum pxp_status {
3131
PXP_STATUS_NOT_READY = 0x100e,
3232
PXP_STATUS_PLATFCONFIG_KF1_NOVERIF = 0x101a,
3333
PXP_STATUS_PLATFCONFIG_KF1_BAD = 0x101f,
34+
PXP_STATUS_PLATFCONFIG_FIXED_KF1_NOT_SUPPORTED = 0x1037,
3435
PXP_STATUS_OP_NOT_PERMITTED = 0x4013
3536
};
3637

@@ -49,6 +50,7 @@ struct pxp_cmd_header {
4950
u32 buffer_len;
5051
} __packed;
5152

53+
#define PXP43_CMDID_INVALIDATE_STREAM_KEY 0x00000007
5254
#define PXP43_CMDID_NEW_HUC_AUTH 0x0000003F /* MTL+ */
5355

5456
/* PXP-Input-Packet: HUC Auth-only */
@@ -63,4 +65,15 @@ struct pxp43_huc_auth_out {
6365
struct pxp_cmd_header header;
6466
} __packed;
6567

68+
/* PXP-Input-Packet: Invalidate Stream Key */
69+
struct pxp43_inv_stream_key_in {
70+
struct pxp_cmd_header header;
71+
u32 rsvd[3];
72+
} __packed;
73+
74+
/* PXP-Output-Packet: Invalidate Stream Key */
75+
struct pxp43_inv_stream_key_out {
76+
struct pxp_cmd_header header;
77+
u32 rsvd;
78+
} __packed;
6679
#endif

drivers/gpu/drm/xe/xe_pxp_submit.c

Lines changed: 228 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,13 @@
1515
#include "xe_gsc_submit.h"
1616
#include "xe_gt.h"
1717
#include "xe_lrc.h"
18+
#include "xe_map.h"
1819
#include "xe_pxp_types.h"
1920
#include "xe_sched_job.h"
2021
#include "xe_vm.h"
22+
#include "abi/gsc_command_header_abi.h"
23+
#include "abi/gsc_pxp_commands_abi.h"
24+
#include "instructions/xe_gsc_commands.h"
2125
#include "instructions/xe_mfx_commands.h"
2226
#include "instructions/xe_mi_commands.h"
2327

@@ -311,3 +315,227 @@ int xe_pxp_submit_session_termination(struct xe_pxp *pxp, u32 id)
311315

312316
return 0;
313317
}
318+
319+
static bool
320+
is_fw_err_platform_config(u32 type)
321+
{
322+
switch (type) {
323+
case PXP_STATUS_ERROR_API_VERSION:
324+
case PXP_STATUS_PLATFCONFIG_KF1_NOVERIF:
325+
case PXP_STATUS_PLATFCONFIG_KF1_BAD:
326+
case PXP_STATUS_PLATFCONFIG_FIXED_KF1_NOT_SUPPORTED:
327+
return true;
328+
default:
329+
break;
330+
}
331+
return false;
332+
}
333+
334+
static const char *
335+
fw_err_to_string(u32 type)
336+
{
337+
switch (type) {
338+
case PXP_STATUS_ERROR_API_VERSION:
339+
return "ERR_API_VERSION";
340+
case PXP_STATUS_NOT_READY:
341+
return "ERR_NOT_READY";
342+
case PXP_STATUS_PLATFCONFIG_KF1_NOVERIF:
343+
case PXP_STATUS_PLATFCONFIG_KF1_BAD:
344+
case PXP_STATUS_PLATFCONFIG_FIXED_KF1_NOT_SUPPORTED:
345+
return "ERR_PLATFORM_CONFIG";
346+
default:
347+
break;
348+
}
349+
return NULL;
350+
}
351+
352+
static int pxp_pkt_submit(struct xe_exec_queue *q, u64 batch_addr)
353+
{
354+
struct xe_gt *gt = q->gt;
355+
struct xe_device *xe = gt_to_xe(gt);
356+
struct xe_sched_job *job;
357+
struct dma_fence *fence;
358+
long timeout;
359+
360+
xe_assert(xe, q->hwe->engine_id == XE_HW_ENGINE_GSCCS0);
361+
362+
job = xe_sched_job_create(q, &batch_addr);
363+
if (IS_ERR(job))
364+
return PTR_ERR(job);
365+
366+
xe_sched_job_arm(job);
367+
fence = dma_fence_get(&job->drm.s_fence->finished);
368+
xe_sched_job_push(job);
369+
370+
timeout = dma_fence_wait_timeout(fence, false, HZ);
371+
dma_fence_put(fence);
372+
if (timeout < 0)
373+
return timeout;
374+
else if (!timeout)
375+
return -ETIME;
376+
377+
return 0;
378+
}
379+
380+
static void emit_pxp_heci_cmd(struct xe_device *xe, struct iosys_map *batch,
381+
u64 addr_in, u32 size_in, u64 addr_out, u32 size_out)
382+
{
383+
u32 len = 0;
384+
385+
xe_map_wr(xe, batch, len++ * sizeof(u32), u32, GSC_HECI_CMD_PKT);
386+
xe_map_wr(xe, batch, len++ * sizeof(u32), u32, lower_32_bits(addr_in));
387+
xe_map_wr(xe, batch, len++ * sizeof(u32), u32, upper_32_bits(addr_in));
388+
xe_map_wr(xe, batch, len++ * sizeof(u32), u32, size_in);
389+
xe_map_wr(xe, batch, len++ * sizeof(u32), u32, lower_32_bits(addr_out));
390+
xe_map_wr(xe, batch, len++ * sizeof(u32), u32, upper_32_bits(addr_out));
391+
xe_map_wr(xe, batch, len++ * sizeof(u32), u32, size_out);
392+
xe_map_wr(xe, batch, len++ * sizeof(u32), u32, 0);
393+
xe_map_wr(xe, batch, len++ * sizeof(u32), u32, MI_BATCH_BUFFER_END);
394+
}
395+
396+
#define GSC_PENDING_RETRY_MAXCOUNT 40
397+
#define GSC_PENDING_RETRY_PAUSE_MS 50
398+
static int gsccs_send_message(struct xe_pxp_gsc_client_resources *gsc_res,
399+
void *msg_in, size_t msg_in_size,
400+
void *msg_out, size_t msg_out_size_max)
401+
{
402+
struct xe_device *xe = gsc_res->vm->xe;
403+
const size_t max_msg_size = gsc_res->inout_size - sizeof(struct intel_gsc_mtl_header);
404+
u32 wr_offset;
405+
u32 rd_offset;
406+
u32 reply_size;
407+
u32 min_reply_size = 0;
408+
int ret;
409+
int retry = GSC_PENDING_RETRY_MAXCOUNT;
410+
411+
if (msg_in_size > max_msg_size || msg_out_size_max > max_msg_size)
412+
return -ENOSPC;
413+
414+
wr_offset = xe_gsc_emit_header(xe, &gsc_res->msg_in, 0,
415+
HECI_MEADDRESS_PXP,
416+
gsc_res->host_session_handle,
417+
msg_in_size);
418+
419+
/* NOTE: zero size packets are used for session-cleanups */
420+
if (msg_in && msg_in_size) {
421+
xe_map_memcpy_to(xe, &gsc_res->msg_in, wr_offset,
422+
msg_in, msg_in_size);
423+
min_reply_size = sizeof(struct pxp_cmd_header);
424+
}
425+
426+
/* Make sure the reply header does not contain stale data */
427+
xe_gsc_poison_header(xe, &gsc_res->msg_out, 0);
428+
429+
/*
430+
* The BO is mapped at address 0 of the PPGTT, so no need to add its
431+
* base offset when calculating the in/out addresses.
432+
*/
433+
emit_pxp_heci_cmd(xe, &gsc_res->batch, PXP_BB_SIZE,
434+
wr_offset + msg_in_size, PXP_BB_SIZE + gsc_res->inout_size,
435+
wr_offset + msg_out_size_max);
436+
437+
xe_device_wmb(xe);
438+
439+
/*
440+
* If the GSC needs to communicate with CSME to complete our request,
441+
* it'll set the "pending" flag in the return header. In this scenario
442+
* we're expected to wait 50ms to give some time to the proxy code to
443+
* handle the GSC<->CSME communication and then try again. Note that,
444+
* although in most case the 50ms window is enough, the proxy flow is
445+
* not actually guaranteed to complete within that time period, so we
446+
* might have to try multiple times, up to a worst case of 2 seconds,
447+
* after which the request is considered aborted.
448+
*/
449+
do {
450+
ret = pxp_pkt_submit(gsc_res->q, 0);
451+
if (ret)
452+
break;
453+
454+
if (xe_gsc_check_and_update_pending(xe, &gsc_res->msg_in, 0,
455+
&gsc_res->msg_out, 0)) {
456+
ret = -EAGAIN;
457+
msleep(GSC_PENDING_RETRY_PAUSE_MS);
458+
}
459+
} while (--retry && ret == -EAGAIN);
460+
461+
if (ret) {
462+
drm_err(&xe->drm, "failed to submit GSC PXP message (%pe)\n", ERR_PTR(ret));
463+
return ret;
464+
}
465+
466+
ret = xe_gsc_read_out_header(xe, &gsc_res->msg_out, 0,
467+
min_reply_size, &rd_offset);
468+
if (ret) {
469+
drm_err(&xe->drm, "invalid GSC reply for PXP (%pe)\n", ERR_PTR(ret));
470+
return ret;
471+
}
472+
473+
if (msg_out && min_reply_size) {
474+
reply_size = xe_map_rd_field(xe, &gsc_res->msg_out, rd_offset,
475+
struct pxp_cmd_header, buffer_len);
476+
reply_size += sizeof(struct pxp_cmd_header);
477+
478+
if (reply_size > msg_out_size_max) {
479+
drm_warn(&xe->drm, "PXP reply size overflow: %u (%zu)\n",
480+
reply_size, msg_out_size_max);
481+
reply_size = msg_out_size_max;
482+
}
483+
484+
xe_map_memcpy_from(xe, msg_out, &gsc_res->msg_out,
485+
rd_offset, reply_size);
486+
}
487+
488+
xe_gsc_poison_header(xe, &gsc_res->msg_in, 0);
489+
490+
return ret;
491+
}
492+
493+
/**
494+
* xe_pxp_submit_session_invalidation - submits a PXP GSC invalidation
495+
* @gsc_res: the pxp client resources
496+
* @id: the session to invalidate
497+
*
498+
* Submit a message to the GSC FW to notify it that a session has been
499+
* terminated and is therefore invalid.
500+
*
501+
* Returns 0 if the submission is successful, an errno value otherwise.
502+
*/
503+
int xe_pxp_submit_session_invalidation(struct xe_pxp_gsc_client_resources *gsc_res, u32 id)
504+
{
505+
struct xe_device *xe = gsc_res->vm->xe;
506+
struct pxp43_inv_stream_key_in msg_in = {0};
507+
struct pxp43_inv_stream_key_out msg_out = {0};
508+
int ret = 0;
509+
510+
/*
511+
* Stream key invalidation reuses the same version 4.2 input/output
512+
* command format but firmware requires 4.3 API interaction
513+
*/
514+
msg_in.header.api_version = PXP_APIVER(4, 3);
515+
msg_in.header.command_id = PXP43_CMDID_INVALIDATE_STREAM_KEY;
516+
msg_in.header.buffer_len = sizeof(msg_in) - sizeof(msg_in.header);
517+
518+
msg_in.header.stream_id = FIELD_PREP(PXP_CMDHDR_EXTDATA_SESSION_VALID, 1);
519+
msg_in.header.stream_id |= FIELD_PREP(PXP_CMDHDR_EXTDATA_APP_TYPE, 0);
520+
msg_in.header.stream_id |= FIELD_PREP(PXP_CMDHDR_EXTDATA_SESSION_ID, id);
521+
522+
ret = gsccs_send_message(gsc_res, &msg_in, sizeof(msg_in),
523+
&msg_out, sizeof(msg_out));
524+
if (ret) {
525+
drm_err(&xe->drm, "Failed to invalidate PXP stream-key %u (%pe)\n",
526+
id, ERR_PTR(ret));
527+
} else if (msg_out.header.status != 0) {
528+
ret = -EIO;
529+
530+
if (is_fw_err_platform_config(msg_out.header.status))
531+
drm_info_once(&xe->drm,
532+
"Failed to invalidate PXP stream-key %u: BIOS/SOC 0x%08x(%s)\n",
533+
id, msg_out.header.status,
534+
fw_err_to_string(msg_out.header.status));
535+
else
536+
drm_dbg(&xe->drm, "Failed to invalidate stream-key %u, s=0x%08x\n",
537+
id, msg_out.header.status);
538+
}
539+
540+
return ret;
541+
}

drivers/gpu/drm/xe/xe_pxp_submit.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,13 @@
99
#include <linux/types.h>
1010

1111
struct xe_pxp;
12+
struct xe_pxp_gsc_client_resources;
1213

1314
int xe_pxp_allocate_execution_resources(struct xe_pxp *pxp);
1415
void xe_pxp_destroy_execution_resources(struct xe_pxp *pxp);
1516

1617
int xe_pxp_submit_session_termination(struct xe_pxp *pxp, u32 id);
18+
int xe_pxp_submit_session_invalidation(struct xe_pxp_gsc_client_resources *gsc_res,
19+
u32 id);
1720

1821
#endif /* __XE_PXP_SUBMIT_H__ */

0 commit comments

Comments
 (0)