Commit 41a97c4a authored by Daniele Ceraolo Spurio's avatar Daniele Ceraolo Spurio
Browse files

drm/xe/pxp/uapi: Add API to mark a BO as using PXP



The driver needs to know if a BO is encrypted with PXP to enable the
display decryption at flip time.
Furthermore, we want to keep track of the status of the encryption and
reject any operation that involves a BO that is encrypted using an old
key. There are two points in time where such checks can kick in:

1 - at VM bind time, all operations except for unmapping will be
    rejected if the key used to encrypt the BO is no longer valid. This
    check is opt-in via a new VM_BIND flag, to avoid a scenario where a
    malicious app purposely shares an invalid BO with a non-PXP aware
    app (such as a compositor). If the VM_BIND was failed, the
    compositor would be unable to display anything at all. Allowing the
    bind to go through means that output still works, it just displays
    garbage data within the bounds of the illegal BO.

2 - at job submission time, if the queue is marked as using PXP, all
    objects bound to the VM will be checked and the submission will be
    rejected if any of them was encrypted with a key that is no longer
    valid.

Note that there is no risk of leaking the encrypted data if a user does
not opt-in to those checks; the only consequence is that the user will
not realize that the encryption key is changed and that the data is no
longer valid.

v2: Better commnnts and descriptions (John), rebase

v3: Properly return the result of key_assign up the stack, do not use
xe_bo in display headers (Jani)

v4: improve key_instance variable documentation (John)

Signed-off-by: default avatarDaniele Ceraolo Spurio <daniele.ceraolospurio@intel.com>
Cc: Matthew Brost <matthew.brost@intel.com>
Cc: Thomas Hellström <thomas.hellstrom@linux.intel.com>
Cc: John Harrison <John.C.Harrison@Intel.com>
Cc: Jani Nikula <jani.nikula@intel.com>
Reviewed-by: default avatarJohn Harrison <John.C.Harrison@Intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20250129174140.948829-11-daniele.ceraolospurio@intel.com
parent bd98ac2e
Loading
Loading
Loading
Loading
+11 −1
Original line number Diff line number Diff line
@@ -9,6 +9,8 @@
#include <linux/errno.h>
#include <linux/types.h>

#include "xe_pxp.h"

struct drm_gem_object;
struct xe_pxp;

@@ -16,7 +18,15 @@ static inline int intel_pxp_key_check(struct xe_pxp *pxp,
				      struct drm_gem_object *obj,
				      bool assign)
{
	return -ENODEV;
	/*
	 * The assign variable is used in i915 to assign the key to the BO at
	 * first submission time. In Xe the key is instead assigned at BO
	 * creation time, so the assign variable must always be false.
	 */
	if (assign)
		return -EINVAL;

	return xe_pxp_obj_key_check(pxp, obj);
}

#endif
+1 −1
Original line number Diff line number Diff line
@@ -25,7 +25,7 @@ bool intel_bo_is_shmem(struct drm_gem_object *obj)

bool intel_bo_is_protected(struct drm_gem_object *obj)
{
	return false;
	return xe_bo_is_protected(gem_to_xe_bo(obj));
}

void intel_bo_flush_if_display(struct drm_gem_object *obj)
+96 −2
Original line number Diff line number Diff line
@@ -6,6 +6,7 @@
#include "xe_bo.h"

#include <linux/dma-buf.h>
#include <linux/nospec.h>

#include <drm/drm_drv.h>
#include <drm/drm_gem_ttm_helper.h>
@@ -26,6 +27,7 @@
#include "xe_migrate.h"
#include "xe_pm.h"
#include "xe_preempt_fence.h"
#include "xe_pxp.h"
#include "xe_res_cursor.h"
#include "xe_trace_bo.h"
#include "xe_ttm_stolen_mgr.h"
@@ -2155,6 +2157,93 @@ void xe_bo_vunmap(struct xe_bo *bo)
	__xe_bo_vunmap(bo);
}

static int gem_create_set_pxp_type(struct xe_device *xe, struct xe_bo *bo, u64 value)
{
	if (value == DRM_XE_PXP_TYPE_NONE)
		return 0;

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

	return xe_pxp_key_assign(xe->pxp, bo);
}

typedef int (*xe_gem_create_set_property_fn)(struct xe_device *xe,
					     struct xe_bo *bo,
					     u64 value);

static const xe_gem_create_set_property_fn gem_create_set_property_funcs[] = {
	[DRM_XE_GEM_CREATE_EXTENSION_SET_PROPERTY] = gem_create_set_pxp_type,
};

static int gem_create_user_ext_set_property(struct xe_device *xe,
					    struct xe_bo *bo,
					    u64 extension)
{
	u64 __user *address = u64_to_user_ptr(extension);
	struct drm_xe_ext_set_property ext;
	int err;
	u32 idx;

	err = __copy_from_user(&ext, address, sizeof(ext));
	if (XE_IOCTL_DBG(xe, err))
		return -EFAULT;

	if (XE_IOCTL_DBG(xe, ext.property >=
			 ARRAY_SIZE(gem_create_set_property_funcs)) ||
	    XE_IOCTL_DBG(xe, ext.pad) ||
	    XE_IOCTL_DBG(xe, ext.property != DRM_XE_GEM_CREATE_EXTENSION_SET_PROPERTY))
		return -EINVAL;

	idx = array_index_nospec(ext.property, ARRAY_SIZE(gem_create_set_property_funcs));
	if (!gem_create_set_property_funcs[idx])
		return -EINVAL;

	return gem_create_set_property_funcs[idx](xe, bo, ext.value);
}

typedef int (*xe_gem_create_user_extension_fn)(struct xe_device *xe,
					       struct xe_bo *bo,
					       u64 extension);

static const xe_gem_create_user_extension_fn gem_create_user_extension_funcs[] = {
	[DRM_XE_GEM_CREATE_EXTENSION_SET_PROPERTY] = gem_create_user_ext_set_property,
};

#define MAX_USER_EXTENSIONS	16
static int gem_create_user_extensions(struct xe_device *xe, struct xe_bo *bo,
				      u64 extensions, int ext_number)
{
	u64 __user *address = u64_to_user_ptr(extensions);
	struct drm_xe_user_extension ext;
	int err;
	u32 idx;

	if (XE_IOCTL_DBG(xe, ext_number >= MAX_USER_EXTENSIONS))
		return -E2BIG;

	err = __copy_from_user(&ext, address, sizeof(ext));
	if (XE_IOCTL_DBG(xe, err))
		return -EFAULT;

	if (XE_IOCTL_DBG(xe, ext.pad) ||
	    XE_IOCTL_DBG(xe, ext.name >= ARRAY_SIZE(gem_create_user_extension_funcs)))
		return -EINVAL;

	idx = array_index_nospec(ext.name,
				 ARRAY_SIZE(gem_create_user_extension_funcs));
	err = gem_create_user_extension_funcs[idx](xe, bo, extensions);
	if (XE_IOCTL_DBG(xe, err))
		return err;

	if (ext.next_extension)
		return gem_create_user_extensions(xe, bo, ext.next_extension,
						  ++ext_number);

	return 0;
}

int xe_gem_create_ioctl(struct drm_device *dev, void *data,
			struct drm_file *file)
{
@@ -2167,8 +2256,7 @@ int xe_gem_create_ioctl(struct drm_device *dev, void *data,
	u32 handle;
	int err;

	if (XE_IOCTL_DBG(xe, args->extensions) ||
	    XE_IOCTL_DBG(xe, args->pad[0] || args->pad[1] || args->pad[2]) ||
	if (XE_IOCTL_DBG(xe, args->pad[0] || args->pad[1] || args->pad[2]) ||
	    XE_IOCTL_DBG(xe, args->reserved[0] || args->reserved[1]))
		return -EINVAL;

@@ -2250,6 +2338,12 @@ int xe_gem_create_ioctl(struct drm_device *dev, void *data,
		goto out_vm;
	}

	if (args->extensions) {
		err = gem_create_user_extensions(xe, bo, args->extensions, 0);
		if (err)
			goto out_bulk;
	}

	err = drm_gem_handle_create(file, &bo->ttm.base, &handle);
	if (err)
		goto out_bulk;
+5 −0
Original line number Diff line number Diff line
@@ -186,6 +186,11 @@ static inline bool xe_bo_is_pinned(struct xe_bo *bo)
	return bo->ttm.pin_count;
}

static inline bool xe_bo_is_protected(const struct xe_bo *bo)
{
	return bo->pxp_key_instance;
}

static inline void xe_bo_unpin_map_no_vm(struct xe_bo *bo)
{
	if (likely(bo)) {
+6 −0
Original line number Diff line number Diff line
@@ -57,6 +57,12 @@ struct xe_bo {
	 */
	struct list_head client_link;
#endif
	/**
	 * @pxp_key_instance: PXP key instance this BO was created against. A
	 * 0 in this variable indicates that the BO does not use PXP encryption.
	 */
	u32 pxp_key_instance;

	/** @freed: List node for delayed put. */
	struct llist_node freed;
	/** @update_index: Update index if PT BO */
Loading