[PATCH i-g-t 5/7] tests/intel/xe_pxp: Test PXP submissions
Daniele Ceraolo Spurio
daniele.ceraolospurio at intel.com
Thu Dec 12 00:18:26 UTC 2024
The render supports PXP usage via rendercopy. We can use this to test
that a user is able to correctly encrypt their data. In particular, we
cover these 2 scenarios:
1) copy from clear to encrypted - we expect the dest buffer to not match
the src one due to the encryption.
2) copy from encrypted to encrypted = we expect the 2 BOs to match since
they hold the same data encrypted with the same key.
Note that the clear to clear copy is already covered by the
xe_render_copy test.
Since the render_copy uses the intel_batchbuffer helpers, those helpers
have been updated to support vm bind of protected objects.
Signed-off-by: Daniele Ceraolo Spurio <daniele.ceraolospurio at intel.com>
---
lib/intel_batchbuffer.c | 17 ++-
tests/intel/xe_pxp.c | 270 ++++++++++++++++++++++++++++++++++++++++
2 files changed, 283 insertions(+), 4 deletions(-)
diff --git a/lib/intel_batchbuffer.c b/lib/intel_batchbuffer.c
index 72bbbf8c6..489e78782 100644
--- a/lib/intel_batchbuffer.c
+++ b/lib/intel_batchbuffer.c
@@ -1333,7 +1333,9 @@ void intel_bb_destroy(struct intel_bb *ibb)
}
#define XE_OBJ_SIZE(rsvd1) ((rsvd1) & ~(SZ_4K-1))
-#define XE_OBJ_PAT_IDX(rsvd1) ((rsvd1) & (SZ_4K-1))
+#define XE_OBJ_PAT_IDX(rsvd1) ((rsvd1) & (0xFF))
+#define XE_OBJ_PXP_BIT (0x100)
+#define XE_OBJ_PXP(rsvd1) ((rsvd1) & (XE_OBJ_PXP_BIT))
static struct drm_xe_vm_bind_op *xe_alloc_bind_ops(struct intel_bb *ibb,
uint32_t op, uint32_t flags,
@@ -1355,6 +1357,9 @@ static struct drm_xe_vm_bind_op *xe_alloc_bind_ops(struct intel_bb *ibb,
ops->op = op;
ops->flags = flags;
+
+ if (XE_OBJ_PXP(objects[i]->rsvd1))
+ ops->flags |= DRM_XE_VM_BIND_FLAG_CHECK_PXP;
ops->obj_offset = 0;
ops->addr = objects[i]->offset;
ops->range = XE_OBJ_SIZE(objects[i]->rsvd1);
@@ -1745,7 +1750,7 @@ static void __remove_from_objects(struct intel_bb *ibb,
static struct drm_i915_gem_exec_object2 *
__intel_bb_add_object(struct intel_bb *ibb, uint32_t handle, uint64_t size,
uint64_t offset, uint64_t alignment, uint8_t pat_index,
- bool write)
+ bool protected, bool write)
{
struct drm_i915_gem_exec_object2 *object;
@@ -1822,6 +1827,7 @@ __intel_bb_add_object(struct intel_bb *ibb, uint32_t handle, uint64_t size,
object->alignment = alignment;
object->rsvd1 = size;
igt_assert(!XE_OBJ_PAT_IDX(object->rsvd1));
+ igt_assert(!XE_OBJ_PXP(object->rsvd1));
if (pat_index == DEFAULT_PAT_INDEX)
pat_index = intel_get_pat_idx_wb(ibb->fd);
@@ -1833,6 +1839,9 @@ __intel_bb_add_object(struct intel_bb *ibb, uint32_t handle, uint64_t size,
* information on xe...
*/
object->rsvd1 |= pat_index;
+
+ if (protected)
+ object->rsvd1 |= XE_OBJ_PXP_BIT;
}
return object;
@@ -1845,7 +1854,7 @@ intel_bb_add_object(struct intel_bb *ibb, uint32_t handle, uint64_t size,
struct drm_i915_gem_exec_object2 *obj = NULL;
obj = __intel_bb_add_object(ibb, handle, size, offset,
- alignment, DEFAULT_PAT_INDEX, write);
+ alignment, DEFAULT_PAT_INDEX, false, write);
igt_assert(obj);
return obj;
@@ -1909,7 +1918,7 @@ __intel_bb_add_intel_buf(struct intel_bb *ibb, struct intel_buf *buf,
obj = __intel_bb_add_object(ibb, buf->handle, intel_buf_bo_size(buf),
buf->addr.offset, alignment, buf->pat_index,
- write);
+ buf->is_protected, write);
igt_assert(obj);
buf->addr.offset = obj->offset;
diff --git a/tests/intel/xe_pxp.c b/tests/intel/xe_pxp.c
index cfe118a1a..3d625af8f 100644
--- a/tests/intel/xe_pxp.c
+++ b/tests/intel/xe_pxp.c
@@ -4,6 +4,10 @@
*/
#include "igt.h"
+#include "intel_batchbuffer.h"
+#include "intel_bufops.h"
+#include "intel_mocs.h"
+#include "intel_pat.h"
#include "xe_drm.h"
#include "xe/xe_ioctl.h"
#include "xe/xe_query.h"
@@ -39,6 +43,15 @@ static int __pxp_bo_create(int fd, uint32_t vm, uint64_t size,
return ret;
}
+static uint32_t pxp_bo_create(int fd, uint32_t vm, uint64_t size, uint32_t type)
+{
+ uint32_t handle;
+
+ igt_assert_eq(__pxp_bo_create(fd, vm, size, type, &handle), 0);
+
+ return handle;
+}
+
static int __create_pxp_rcs_queue(int fd, uint32_t vm,
uint32_t session_type,
uint32_t *q)
@@ -57,6 +70,17 @@ static int __create_pxp_rcs_queue(int fd, uint32_t vm,
return __xe_exec_queue_create(fd, vm, 1, 1, &inst, ext_ptr, q);
}
+static uint32_t create_pxp_rcs_queue(int fd, uint32_t vm)
+{
+ uint32_t q;
+ int err;
+
+ err = __create_pxp_rcs_queue(fd, vm, DRM_XE_PXP_TYPE_HWDRM, &q);
+ igt_assert_eq(err, 0);
+
+ return q;
+}
+
static int query_pxp_status(int fd)
{
struct drm_xe_query_pxp_status *pxp_query;
@@ -174,10 +198,241 @@ static void test_pxp_queue_creation(int fd, bool pxp_supported)
xe_vm_destroy(fd, vm);
}
+static void fill_bo_content(int fd, uint32_t bo, uint32_t size, uint8_t initcolor)
+{
+ uint32_t *ptr;
+
+ ptr = xe_bo_mmap_ext(fd, bo, size, PROT_READ|PROT_WRITE);
+
+ /* read and count all dword matches till size */
+ memset(ptr, initcolor, size);
+
+ igt_assert(munmap(ptr, size) == 0);
+}
+
+static void __check_bo_color(int fd, uint32_t bo, uint32_t size, uint32_t color, bool readible)
+{
+ uint64_t comp;
+ uint64_t *ptr;
+ int i, num_matches = 0;
+
+ comp = color;
+ comp = comp | (comp << 32);
+
+ ptr = xe_bo_mmap_ext(fd, bo, size, PROT_READ);
+
+ igt_assert_eq(size % sizeof(uint64_t), 0);
+
+ for (i = 0; i < (size / sizeof(uint64_t)); i++)
+ if (ptr[i] == comp)
+ ++num_matches;
+
+ if (readible)
+ igt_assert_eq(num_matches, (size / sizeof(uint64_t)));
+ else
+ igt_assert_eq(num_matches, 0);
+}
+
+static void check_bo_color(int fd, uint32_t bo, uint32_t size, uint8_t color, bool readible)
+{
+ uint32_t comp;
+
+ /*
+ * We memset the buffer using a u8 color value. However, this is too
+ * small to ensure the encrypted data does not accidentally match it,
+ * so we scale it up to a bigger size.
+ */
+ comp = color;
+ comp = comp | (comp << 8) | (comp << 16) | (comp << 24);
+
+ return __check_bo_color(fd, bo, size, comp, readible);
+}
+
+static uint32_t __bo_create_and_fill(int fd, uint32_t vm, bool protected,
+ uint32_t size, uint8_t init_color)
+{
+ uint32_t bo;
+
+ if (protected)
+ bo = pxp_bo_create(fd, vm, size, DRM_XE_PXP_TYPE_HWDRM);
+ else
+ bo = xe_bo_create(fd, vm, size, system_memory(fd), 0);
+
+ fill_bo_content(fd, bo, size, init_color);
+
+ return bo;
+}
+
+static uint32_t pxp_bo_create_and_fill(int fd, uint32_t vm, uint32_t size,
+ uint8_t init_color)
+{
+ return __bo_create_and_fill(fd, vm, true, size, init_color);
+}
+
+static uint32_t regular_bo_create_and_fill(int fd, uint32_t vm, uint32_t size,
+ uint8_t init_color)
+{
+ return __bo_create_and_fill(fd, vm, false, size, init_color);
+}
+
+static struct intel_buf *buf_create(int fd, struct buf_ops *bops, uint32_t handle,
+ int width, int height, int bpp, uint64_t size)
+{
+ igt_assert(handle);
+ igt_assert(size);
+ return intel_buf_create_full(bops, handle, width, height, bpp, 0,
+ I915_TILING_NONE, 0, size, 0,
+ system_memory(fd),
+ DEFAULT_PAT_INDEX, DEFAULT_MOCS_INDEX);
+}
+
+/* Rendering tests surface attributes */
+#define TSTSURF_WIDTH 64
+#define TSTSURF_HEIGHT 64
+#define TSTSURF_BYTESPP 4
+#define TSTSURF_STRIDE (TSTSURF_WIDTH * TSTSURF_BYTESPP)
+#define TSTSURF_SIZE (TSTSURF_STRIDE * TSTSURF_HEIGHT)
+#define TSTSURF_INITCOLOR1 0xAA
+#define TSTSURF_FILLCOLOR1 0x55
+#define TSTSURF_INITCOLOR2 0x33
+
+static void pxp_rendercopy(int fd, uint32_t q, uint32_t vm, uint32_t copy_size,
+ uint32_t srcbo, bool src_pxp, uint32_t dstbo, bool dst_pxp)
+{
+ igt_render_copyfunc_t render_copy;
+ struct intel_buf *srcbuf, *dstbuf;
+ struct buf_ops *bops;
+ struct intel_bb *ibb;
+
+ /*
+ * we use the defined width and height below, which only works if the BO
+ * size is TSTSURF_SIZE
+ */
+ igt_assert_eq(copy_size, TSTSURF_SIZE);
+
+ render_copy = igt_get_render_copyfunc(intel_get_drm_devid(fd));
+ igt_assert(render_copy);
+
+ bops = buf_ops_create(fd);
+ igt_assert(bops);
+
+ ibb = intel_bb_create_with_context(fd, q, vm, NULL, 4096);
+ igt_assert(ibb);
+ intel_bb_set_pxp(ibb, true, DISPLAY_APPTYPE, DRM_XE_PXP_HWDRM_DEFAULT_SESSION);
+
+ dstbuf = buf_create(fd, bops, dstbo, TSTSURF_WIDTH, TSTSURF_HEIGHT,
+ TSTSURF_BYTESPP * 8, TSTSURF_SIZE);
+ intel_buf_set_pxp(dstbuf, dst_pxp);
+
+ srcbuf = buf_create(fd, bops, srcbo, TSTSURF_WIDTH, TSTSURF_HEIGHT,
+ TSTSURF_BYTESPP * 8, TSTSURF_SIZE);
+ intel_buf_set_pxp(srcbuf, src_pxp);
+
+ render_copy(ibb, srcbuf, 0, 0, TSTSURF_WIDTH, TSTSURF_HEIGHT, dstbuf, 0, 0);
+ intel_bb_sync(ibb);
+
+ intel_buf_destroy(srcbuf);
+ intel_buf_destroy(dstbuf);
+ intel_bb_destroy(ibb);
+ buf_ops_destroy(bops);
+}
+
+/**
+ * SUBTEST: regular-src-to-pxp-dest-rendercopy
+ * Description: copy from a regular BO to a PXP one and verify the encryption
+ */
+static void test_render_regular_src_to_pxp_dest(int fd)
+{
+ uint32_t vm, srcbo, dstbo;
+ uint32_t q;
+
+ vm = xe_vm_create(fd, 0, 0);
+
+ /*
+ * Perform a protected render operation but only label the dest as
+ * protected. After rendering, the content should be encrypted.
+ */
+ q = create_pxp_rcs_queue(fd, vm);
+
+ srcbo = regular_bo_create_and_fill(fd, vm, TSTSURF_SIZE, TSTSURF_FILLCOLOR1);
+ dstbo = pxp_bo_create_and_fill(fd, vm, TSTSURF_SIZE, TSTSURF_INITCOLOR1);
+
+ pxp_rendercopy(fd, q, vm, TSTSURF_SIZE, srcbo, false, dstbo, true);
+
+ check_bo_color(fd, dstbo, TSTSURF_SIZE, TSTSURF_FILLCOLOR1, false);
+
+ gem_close(fd, srcbo);
+ gem_close(fd, dstbo);
+ xe_exec_queue_destroy(fd, q);
+ xe_vm_destroy(fd, vm);
+}
+
+static int bocmp(int fd, uint32_t bo1, uint32_t bo2, uint32_t size)
+{
+ uint32_t *ptr1, *ptr2;
+ int ret;
+
+ ptr1 = xe_bo_mmap_ext(fd, bo1, size, PROT_READ);
+ ptr2 = xe_bo_mmap_ext(fd, bo2, size, PROT_READ);
+
+ ret = memcmp(ptr1, ptr2, size);
+
+ igt_assert_eq(munmap(ptr1, size), 0);
+ igt_assert_eq(munmap(ptr2, size), 0);
+
+ return ret;
+}
+
+/**
+ * SUBTEST: pxp-src-to-pxp-dest-rendercopy
+ * Description: copy between 2 PXP BOs and verify the encryption
+ */
+
+static void test_render_pxp_protsrc_to_protdest(int fd)
+{
+ uint32_t vm, srcbo, dstbo, dstbo2;
+ uint32_t q;
+
+ vm = xe_vm_create(fd, 0, 0);
+
+ q = create_pxp_rcs_queue(fd, vm);
+
+ /*
+ * Copy from a regular src to a PXP dst to get a buffer with a
+ * valid encryption.
+ */
+ srcbo = regular_bo_create_and_fill(fd, vm, TSTSURF_SIZE, TSTSURF_FILLCOLOR1);
+ dstbo = pxp_bo_create_and_fill(fd, vm, TSTSURF_SIZE, TSTSURF_INITCOLOR1);
+
+ pxp_rendercopy(fd, q, vm, TSTSURF_SIZE, srcbo, false, dstbo, true);
+
+ check_bo_color(fd, dstbo, TSTSURF_SIZE, TSTSURF_FILLCOLOR1, false);
+
+ /*
+ * Reuse prior dst as the new-src and create dst2 as the new-dest.
+ * After the rendering, we should find no difference in content since
+ * both new-src and new-dest are labelled as encrypted. HW should read
+ * and decrypt new-src, perform the copy and re-encrypt with the same
+ * key when going into new-dest
+ */
+ dstbo2 = pxp_bo_create_and_fill(fd, vm, TSTSURF_SIZE, TSTSURF_INITCOLOR2);
+
+ pxp_rendercopy(fd, q, vm, TSTSURF_SIZE, dstbo, true, dstbo2, true);
+
+ igt_assert_eq(bocmp(fd, dstbo, dstbo2, TSTSURF_SIZE), 0);
+
+ gem_close(fd, srcbo);
+ gem_close(fd, dstbo);
+ gem_close(fd, dstbo2);
+ xe_exec_queue_destroy(fd, q);
+ xe_vm_destroy(fd, vm);
+}
+
igt_main
{
int xe_fd = -1;
bool pxp_supported = true;
+ uint32_t devid = 0;
igt_fixture {
xe_fd = drm_open_driver(DRIVER_XE);
@@ -195,6 +450,21 @@ igt_main
test_pxp_queue_creation(xe_fd, pxp_supported);
}
+ igt_subtest_group {
+ igt_fixture {
+ igt_require(pxp_supported);
+ devid = intel_get_drm_devid(xe_fd);
+ igt_assert(devid);
+ igt_require(igt_get_render_copyfunc(devid));
+ }
+
+ igt_describe("Verify protected render operations:");
+ igt_subtest("regular-src-to-pxp-dest-rendercopy")
+ test_render_regular_src_to_pxp_dest(xe_fd);
+ igt_subtest("pxp-src-to-pxp-dest-rendercopy")
+ test_render_pxp_protsrc_to_protdest(xe_fd);
+ }
+
igt_fixture {
close(xe_fd);
}
--
2.43.0
More information about the igt-dev
mailing list