Commit f0c06677 authored by Daniele Ceraolo Spurio's avatar Daniele Ceraolo Spurio
Browse files

drm/xe/pxp: Add VCS inline termination support



The key termination is done with a specific submission to the VCS
engine. This flow will be triggered in response to a termination
interrupt, whose handling is coming in a follow-up patch in the series.

v2: clean up defines and command emission code. (John)

Signed-off-by: default avatarDaniele Ceraolo Spurio <daniele.ceraolospurio@intel.com>
Cc: John Harrison <John.C.Harrison@Intel.com>
Reviewed-by: default avatarJohn Harrison <John.C.Harrison@Intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20250129174140.948829-4-daniele.ceraolospurio@intel.com
parent dcdd6b84
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@
#define XE_INSTR_CMD_TYPE		GENMASK(31, 29)
#define   XE_INSTR_MI			REG_FIELD_PREP(XE_INSTR_CMD_TYPE, 0x0)
#define   XE_INSTR_GSC			REG_FIELD_PREP(XE_INSTR_CMD_TYPE, 0x2)
#define   XE_INSTR_VIDEOPIPE		REG_FIELD_PREP(XE_INSTR_CMD_TYPE, 0x3)
#define   XE_INSTR_GFXPIPE		REG_FIELD_PREP(XE_INSTR_CMD_TYPE, 0x3)
#define   XE_INSTR_GFX_STATE		REG_FIELD_PREP(XE_INSTR_CMD_TYPE, 0x4)

+28 −0
Original line number Diff line number Diff line
/* SPDX-License-Identifier: MIT */
/*
 * Copyright © 2024 Intel Corporation
 */

#ifndef _XE_MFX_COMMANDS_H_
#define _XE_MFX_COMMANDS_H_

#include "instructions/xe_instr_defs.h"

#define MFX_CMD_SUBTYPE		REG_GENMASK(28, 27) /* A.K.A cmd pipe */
#define MFX_CMD_OPCODE		REG_GENMASK(26, 24)
#define MFX_CMD_SUB_OPCODE	REG_GENMASK(23, 16)
#define MFX_FLAGS_AND_LEN	REG_GENMASK(15, 0)

#define XE_MFX_INSTR(subtype, op, sub_op) \
	(XE_INSTR_VIDEOPIPE | \
	 REG_FIELD_PREP(MFX_CMD_SUBTYPE, subtype) | \
	 REG_FIELD_PREP(MFX_CMD_OPCODE, op) | \
	 REG_FIELD_PREP(MFX_CMD_SUB_OPCODE, sub_op))

#define MFX_WAIT				XE_MFX_INSTR(1, 0, 0)
#define MFX_WAIT_DW0_PXP_SYNC_CONTROL_FLAG	REG_BIT(9)
#define MFX_WAIT_DW0_MFX_SYNC_CONTROL_FLAG	REG_BIT(8)

#define CRYPTO_KEY_EXCHANGE			XE_MFX_INSTR(2, 6, 9)

#endif
+5 −0
Original line number Diff line number Diff line
@@ -48,6 +48,7 @@
#define   MI_LRI_LEN(x)			(((x) & 0xff) + 1)

#define MI_FLUSH_DW			__MI_INSTR(0x26)
#define   MI_FLUSH_DW_PROTECTED_MEM_EN	REG_BIT(22)
#define   MI_FLUSH_DW_STORE_INDEX	REG_BIT(21)
#define   MI_INVALIDATE_TLB		REG_BIT(18)
#define   MI_FLUSH_DW_CCS		REG_BIT(16)
@@ -66,4 +67,8 @@

#define MI_BATCH_BUFFER_START		__MI_INSTR(0x31)

#define MI_SET_APPID			__MI_INSTR(0x0e)
#define MI_SET_APPID_SESSION_ID_MASK	REG_GENMASK(6, 0)
#define MI_SET_APPID_SESSION_ID(x)	REG_FIELD_PREP(MI_SET_APPID_SESSION_ID_MASK, x)

#endif
+2 −1
Original line number Diff line number Diff line
@@ -39,7 +39,8 @@ struct xe_lrc_snapshot {
	u32 ctx_job_timestamp;
};

#define LRC_PPHWSP_SCRATCH_ADDR (0x34 * 4)
#define LRC_PPHWSP_FLUSH_INVAL_SCRATCH_ADDR (0x34 * 4)
#define LRC_PPHWSP_PXP_INVAL_SCRATCH_ADDR (0x40 * 4)

struct xe_lrc *xe_lrc_create(struct xe_hw_engine *hwe, struct xe_vm *vm,
			     u32 ring_size, u16 msix_vec);
+114 −0
Original line number Diff line number Diff line
@@ -5,15 +5,21 @@

#include "xe_pxp_submit.h"

#include <linux/delay.h>
#include <uapi/drm/xe_drm.h>

#include "xe_device_types.h"
#include "xe_bb.h"
#include "xe_bo.h"
#include "xe_exec_queue.h"
#include "xe_gsc_submit.h"
#include "xe_gt.h"
#include "xe_lrc.h"
#include "xe_pxp_types.h"
#include "xe_sched_job.h"
#include "xe_vm.h"
#include "instructions/xe_mfx_commands.h"
#include "instructions/xe_mi_commands.h"

/*
 * The VCS is used for kernel-owned GGTT submissions to issue key termination.
@@ -197,3 +203,111 @@ void xe_pxp_destroy_execution_resources(struct xe_pxp *pxp)
	destroy_gsc_client_resources(&pxp->gsc_res);
	destroy_vcs_execution_resources(pxp);
}

#define emit_cmd(xe_, map_, offset_, val_) \
	xe_map_wr(xe_, map_, (offset_) * sizeof(u32), u32, val_)

/* stall until prior PXP and MFX/HCP/HUC objects are completed */
#define MFX_WAIT_PXP (MFX_WAIT | \
		      MFX_WAIT_DW0_PXP_SYNC_CONTROL_FLAG | \
		      MFX_WAIT_DW0_MFX_SYNC_CONTROL_FLAG)
static u32 pxp_emit_wait(struct xe_device *xe, struct iosys_map *batch, u32 offset)
{
	/* wait for cmds to go through */
	emit_cmd(xe, batch, offset++, MFX_WAIT_PXP);
	emit_cmd(xe, batch, offset++, 0);

	return offset;
}

static u32 pxp_emit_session_selection(struct xe_device *xe, struct iosys_map *batch,
				      u32 offset, u32 idx)
{
	offset = pxp_emit_wait(xe, batch, offset);

	/* pxp off */
	emit_cmd(xe, batch, offset++, MI_FLUSH_DW | MI_FLUSH_IMM_DW);
	emit_cmd(xe, batch, offset++, 0);
	emit_cmd(xe, batch, offset++, 0);
	emit_cmd(xe, batch, offset++, 0);

	/* select session */
	emit_cmd(xe, batch, offset++, MI_SET_APPID | MI_SET_APPID_SESSION_ID(idx));
	emit_cmd(xe, batch, offset++, 0);

	offset = pxp_emit_wait(xe, batch, offset);

	/* pxp on */
	emit_cmd(xe, batch, offset++, MI_FLUSH_DW |
				      MI_FLUSH_DW_PROTECTED_MEM_EN |
				      MI_FLUSH_DW_OP_STOREDW | MI_FLUSH_DW_STORE_INDEX |
				      MI_FLUSH_IMM_DW);
	emit_cmd(xe, batch, offset++, LRC_PPHWSP_PXP_INVAL_SCRATCH_ADDR |
				      MI_FLUSH_DW_USE_GTT);
	emit_cmd(xe, batch, offset++, 0);
	emit_cmd(xe, batch, offset++, 0);

	offset = pxp_emit_wait(xe, batch, offset);

	return offset;
}

static u32 pxp_emit_inline_termination(struct xe_device *xe,
				       struct iosys_map *batch, u32 offset)
{
	/* session inline termination */
	emit_cmd(xe, batch, offset++, CRYPTO_KEY_EXCHANGE);
	emit_cmd(xe, batch, offset++, 0);

	return offset;
}

static u32 pxp_emit_session_termination(struct xe_device *xe, struct iosys_map *batch,
					u32 offset, u32 idx)
{
	offset = pxp_emit_session_selection(xe, batch, offset, idx);
	offset = pxp_emit_inline_termination(xe, batch, offset);

	return offset;
}

/**
 * xe_pxp_submit_session_termination - submits a PXP inline termination
 * @pxp: the xe_pxp structure
 * @id: the session to terminate
 *
 * Emit an inline termination via the VCS engine to terminate a session.
 *
 * Returns 0 if the submission is successful, an errno value otherwise.
 */
int xe_pxp_submit_session_termination(struct xe_pxp *pxp, u32 id)
{
	struct xe_sched_job *job;
	struct dma_fence *fence;
	long timeout;
	u32 offset = 0;
	u64 addr = xe_bo_ggtt_addr(pxp->vcs_exec.bo);

	offset = pxp_emit_session_termination(pxp->xe, &pxp->vcs_exec.bo->vmap, offset, id);
	offset = pxp_emit_wait(pxp->xe, &pxp->vcs_exec.bo->vmap, offset);
	emit_cmd(pxp->xe, &pxp->vcs_exec.bo->vmap, offset, MI_BATCH_BUFFER_END);

	job = xe_sched_job_create(pxp->vcs_exec.q, &addr);
	if (IS_ERR(job))
		return PTR_ERR(job);

	xe_sched_job_arm(job);
	fence = dma_fence_get(&job->drm.s_fence->finished);
	xe_sched_job_push(job);

	timeout = dma_fence_wait_timeout(fence, false, HZ);

	dma_fence_put(fence);

	if (!timeout)
		return -ETIMEDOUT;
	else if (timeout < 0)
		return timeout;

	return 0;
}
Loading