Commit 72d47960 authored by Daniele Ceraolo Spurio's avatar Daniele Ceraolo Spurio
Browse files

drm/xe/pxp/uapi: Add userspace and LRC support for PXP-using queues



Userspace is required to mark a queue as using PXP to guarantee that the
PXP instructions will work. In addition to managing the PXP sessions,
when a PXP queue is created the driver will set the relevant bits in
its context control register.

On submission of a valid PXP queue, the driver will validate all
encrypted objects mapped to the VM to ensured they were encrypted with
the current key.

v2: Remove pxp_types include outside of PXP code (Jani), better comments
and code cleanup (John)

v3: split the internal PXP management to a separate patch for ease of
review. re-order ioctl checks to always return -EINVAL if parameters are
invalid, rebase on msix changes.

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-9-daniele.ceraolospurio@intel.com
parent f8caa801
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -132,6 +132,7 @@
#define RING_EXECLIST_STATUS_HI(base)		XE_REG((base) + 0x234 + 4)

#define RING_CONTEXT_CONTROL(base)		XE_REG((base) + 0x244, XE_REG_OPTION_MASKED)
#define	  CTX_CTRL_PXP_ENABLE			REG_BIT(10)
#define	  CTX_CTRL_OAC_CONTEXT_ENABLE		REG_BIT(8)
#define	  CTX_CTRL_RUN_ALONE			REG_BIT(7)
#define	  CTX_CTRL_INDIRECT_RING_STATE_ENABLE	REG_BIT(4)
+54 −2
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@
#include "xe_ring_ops_types.h"
#include "xe_trace.h"
#include "xe_vm.h"
#include "xe_pxp.h"

enum xe_exec_queue_sched_prop {
	XE_EXEC_QUEUE_JOB_TIMEOUT = 0,
@@ -38,6 +39,8 @@ static int exec_queue_user_extensions(struct xe_device *xe, struct xe_exec_queue

static void __xe_exec_queue_free(struct xe_exec_queue *q)
{
	if (xe_exec_queue_uses_pxp(q))
		xe_pxp_exec_queue_remove(gt_to_xe(q->gt)->pxp, q);
	if (q->vm)
		xe_vm_put(q->vm);

@@ -113,6 +116,21 @@ static int __xe_exec_queue_init(struct xe_exec_queue *q)
{
	struct xe_vm *vm = q->vm;
	int i, err;
	u32 flags = 0;

	/*
	 * PXP workloads executing on RCS or CCS must run in isolation (i.e. no
	 * other workload can use the EUs at the same time). On MTL this is done
	 * by setting the RUNALONE bit in the LRC, while starting on Xe2 there
	 * is a dedicated bit for it.
	 */
	if (xe_exec_queue_uses_pxp(q) &&
	    (q->class == XE_ENGINE_CLASS_RENDER || q->class == XE_ENGINE_CLASS_COMPUTE)) {
		if (GRAPHICS_VER(gt_to_xe(q->gt)) >= 20)
			flags |= XE_LRC_CREATE_PXP;
		else
			flags |= XE_LRC_CREATE_RUNALONE;
	}

	if (vm) {
		err = xe_vm_lock(vm, true);
@@ -121,7 +139,7 @@ static int __xe_exec_queue_init(struct xe_exec_queue *q)
	}

	for (i = 0; i < q->width; ++i) {
		q->lrc[i] = xe_lrc_create(q->hwe, q->vm, SZ_16K, q->msix_vec);
		q->lrc[i] = xe_lrc_create(q->hwe, q->vm, SZ_16K, q->msix_vec, flags);
		if (IS_ERR(q->lrc[i])) {
			err = PTR_ERR(q->lrc[i]);
			goto err_unlock;
@@ -166,6 +184,19 @@ struct xe_exec_queue *xe_exec_queue_create(struct xe_device *xe, struct xe_vm *v
	if (err)
		goto err_post_alloc;

	/*
	 * We can only add the queue to the PXP list after the init is complete,
	 * because the PXP termination can call exec_queue_kill and that will
	 * go bad if the queue is only half-initialized. This means that we
	 * can't do it when we handle the PXP extension in __xe_exec_queue_alloc
	 * and we need to do it here instead.
	 */
	if (xe_exec_queue_uses_pxp(q)) {
		err = xe_pxp_exec_queue_add(xe->pxp, q);
		if (err)
			goto err_post_alloc;
	}

	return q;

err_post_alloc:
@@ -254,6 +285,9 @@ void xe_exec_queue_destroy(struct kref *ref)
	struct xe_exec_queue *q = container_of(ref, struct xe_exec_queue, refcount);
	struct xe_exec_queue *eq, *next;

	if (xe_exec_queue_uses_pxp(q))
		xe_pxp_exec_queue_remove(gt_to_xe(q->gt)->pxp, q);

	xe_exec_queue_last_fence_put_unlocked(q);
	if (!(q->flags & EXEC_QUEUE_FLAG_BIND_ENGINE_CHILD)) {
		list_for_each_entry_safe(eq, next, &q->multi_gt_list,
@@ -409,6 +443,22 @@ static int exec_queue_set_timeslice(struct xe_device *xe, struct xe_exec_queue *
	return 0;
}

static int
exec_queue_set_pxp_type(struct xe_device *xe, struct xe_exec_queue *q, u64 value)
{
	if (value == DRM_XE_PXP_TYPE_NONE)
		return 0;

	/* we only support HWDRM sessions right now */
	if (XE_IOCTL_DBG(xe, value != DRM_XE_PXP_TYPE_HWDRM))
		return -EINVAL;

	if (!xe_pxp_is_enabled(xe->pxp))
		return -ENODEV;

	return xe_pxp_exec_queue_set_type(xe->pxp, q, DRM_XE_PXP_TYPE_HWDRM);
}

typedef int (*xe_exec_queue_set_property_fn)(struct xe_device *xe,
					     struct xe_exec_queue *q,
					     u64 value);
@@ -416,6 +466,7 @@ typedef int (*xe_exec_queue_set_property_fn)(struct xe_device *xe,
static const xe_exec_queue_set_property_fn exec_queue_set_property_funcs[] = {
	[DRM_XE_EXEC_QUEUE_SET_PROPERTY_PRIORITY] = exec_queue_set_priority,
	[DRM_XE_EXEC_QUEUE_SET_PROPERTY_TIMESLICE] = exec_queue_set_timeslice,
	[DRM_XE_EXEC_QUEUE_SET_PROPERTY_PXP_TYPE] = exec_queue_set_pxp_type,
};

static int exec_queue_user_ext_set_property(struct xe_device *xe,
@@ -435,7 +486,8 @@ static int exec_queue_user_ext_set_property(struct xe_device *xe,
			 ARRAY_SIZE(exec_queue_set_property_funcs)) ||
	    XE_IOCTL_DBG(xe, ext.pad) ||
	    XE_IOCTL_DBG(xe, ext.property != DRM_XE_EXEC_QUEUE_SET_PROPERTY_PRIORITY &&
			 ext.property != DRM_XE_EXEC_QUEUE_SET_PROPERTY_TIMESLICE))
			 ext.property != DRM_XE_EXEC_QUEUE_SET_PROPERTY_TIMESLICE &&
			 ext.property != DRM_XE_EXEC_QUEUE_SET_PROPERTY_PXP_TYPE))
		return -EINVAL;

	idx = array_index_nospec(ext.property, ARRAY_SIZE(exec_queue_set_property_funcs));
+5 −0
Original line number Diff line number Diff line
@@ -57,6 +57,11 @@ static inline bool xe_exec_queue_is_parallel(struct xe_exec_queue *q)
	return q->width > 1;
}

static inline bool xe_exec_queue_uses_pxp(struct xe_exec_queue *q)
{
	return q->pxp.type;
}

bool xe_exec_queue_is_lr(struct xe_exec_queue *q);

bool xe_exec_queue_ring_full(struct xe_exec_queue *q);
+2 −0
Original line number Diff line number Diff line
@@ -132,6 +132,8 @@ struct xe_exec_queue {

	/** @pxp: PXP info tracking */
	struct {
		/** @pxp.type: PXP session type used by this queue */
		u8 type;
		/** @pxp.link: link into the list of PXP exec queues */
		struct list_head link;
	} pxp;
+1 −1
Original line number Diff line number Diff line
@@ -269,7 +269,7 @@ struct xe_execlist_port *xe_execlist_port_create(struct xe_device *xe,

	port->hwe = hwe;

	port->lrc = xe_lrc_create(hwe, NULL, SZ_16K, XE_IRQ_DEFAULT_MSIX);
	port->lrc = xe_lrc_create(hwe, NULL, SZ_16K, XE_IRQ_DEFAULT_MSIX, 0);
	if (IS_ERR(port->lrc)) {
		err = PTR_ERR(port->lrc);
		goto err;
Loading