From 050948b6058d953c8bc023027725b3599be62e18 Mon Sep 17 00:00:00 2001 From: Li_Xin6 Date: Thu, 13 Feb 2025 14:01:55 +0800 Subject: [PATCH] [CP] Create Protected Queue for Protected Context Protected queue is required for protected execution. --- .../linux/common/os/xe/include/README.md | 44 +++++ .../linux/common/os/xe/include/xe_drm.h | 160 +++++++++++++++++- .../linux/common/os/xe/mos_bufmgr_xe.c | 24 ++- 3 files changed, 222 insertions(+), 6 deletions(-) diff --git a/media_softlet/linux/common/os/xe/include/README.md b/media_softlet/linux/common/os/xe/include/README.md index 869b9b95adf..f5915edcac7 100644 --- a/media_softlet/linux/common/os/xe/include/README.md +++ b/media_softlet/linux/common/os/xe/include/README.md @@ -13,6 +13,50 @@ $ make headers_install INSTALL_HDR_PATH=/path/to/install The last update was done at the following kernel commit: +commit 41a97c4a12947c2786a1680d6839bb72d1c57cec (HEAD -> drm-xe-next, origin/drm-xe-next) + +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 +Cc: Matthew Brost +Cc: Thomas Hellström +Cc: John Harrison +Cc: Jani Nikula +Reviewed-by: default avatarJohn Harrison +Link: https://patchwork.freedesktop.org/patch/msgid/20250129174140.948829-11-daniele.ceraolospurio@intel.com + commit f2881dfdaaa9ec873dbd383ef5512fc31e576cbb (HEAD -> drm-xe-next, origin/drm-xe-next) drm/xe/oa/uapi: Make bit masks unsigned diff --git a/media_softlet/linux/common/os/xe/include/xe_drm.h b/media_softlet/linux/common/os/xe/include/xe_drm.h index b6fbe4988f2..892f54d3aa0 100644 --- a/media_softlet/linux/common/os/xe/include/xe_drm.h +++ b/media_softlet/linux/common/os/xe/include/xe_drm.h @@ -512,7 +512,9 @@ struct drm_xe_query_gt_list { * containing the following in mask: * ``DSS_COMPUTE ff ff ff ff 00 00 00 00`` * means 32 DSS are available for compute. - * - %DRM_XE_TOPO_L3_BANK - To query the mask of enabled L3 banks + * - %DRM_XE_TOPO_L3_BANK - To query the mask of enabled L3 banks. This type + * may be omitted if the driver is unable to query the mask from the + * hardware. * - %DRM_XE_TOPO_EU_PER_DSS - To query the mask of Execution Units (EU) * available per Dual Sub Slices (DSS). For example a query response * containing the following in mask: @@ -627,6 +629,39 @@ struct drm_xe_query_uc_fw_version { __u64 reserved; }; +/** + * struct drm_xe_query_pxp_status - query if PXP is ready + * + * If PXP is enabled and no fatal error has occurred, the status will be set to + * one of the following values: + * 0: PXP init still in progress + * 1: PXP init complete + * + * If PXP is not enabled or something has gone wrong, the query will be failed + * with one of the following error codes: + * -ENODEV: PXP not supported or disabled; + * -EIO: fatal error occurred during init, so PXP will never be enabled; + * -EINVAL: incorrect value provided as part of the query; + * -EFAULT: error copying the memory between kernel and userspace. + * + * The status can only be 0 in the first few seconds after driver load. If + * everything works as expected, the status will transition to init complete in + * less than 1 second, while in case of errors the driver might take longer to + * start returning an error code, but it should still take less than 10 seconds. + * + * The supported session type bitmask is based on the values in + * enum drm_xe_pxp_session_type. TYPE_NONE is always supported and therefore + * is not reported in the bitmask. + * + */ +struct drm_xe_query_pxp_status { + /** @status: current PXP status */ + __u32 status; + + /** @supported_session_types: bitmask of supported PXP session types */ + __u32 supported_session_types; +}; + /** * struct drm_xe_device_query - Input of &DRM_IOCTL_XE_DEVICE_QUERY - main * structure to query device information @@ -646,6 +681,7 @@ struct drm_xe_query_uc_fw_version { * attributes. * - %DRM_XE_DEVICE_QUERY_GT_TOPOLOGY * - %DRM_XE_DEVICE_QUERY_ENGINE_CYCLES + * - %DRM_XE_DEVICE_QUERY_PXP_STATUS * * If size is set to 0, the driver fills it with the required size for * the requested type of data to query. If size is equal to the required @@ -698,6 +734,7 @@ struct drm_xe_device_query { #define DRM_XE_DEVICE_QUERY_ENGINE_CYCLES 6 #define DRM_XE_DEVICE_QUERY_UC_FW_VERSION 7 #define DRM_XE_DEVICE_QUERY_OA_UNITS 8 +#define DRM_XE_DEVICE_QUERY_PXP_STATUS 9 /** @query: The type of data to query */ __u32 query; @@ -741,8 +778,23 @@ struct drm_xe_device_query { * - %DRM_XE_GEM_CPU_CACHING_WC - Allocate the pages as write-combined. This * is uncached. Scanout surfaces should likely use this. All objects * that can be placed in VRAM must use this. + * + * This ioctl supports setting the following properties via the + * %DRM_XE_GEM_CREATE_EXTENSION_SET_PROPERTY extension, which uses the + * generic @drm_xe_ext_set_property struct: + * + * - %DRM_XE_GEM_CREATE_SET_PROPERTY_PXP_TYPE - set the type of PXP session + * this object will be used with. Valid values are listed in enum + * drm_xe_pxp_session_type. %DRM_XE_PXP_TYPE_NONE is the default behavior, so + * there is no need to explicitly set that. Objects used with session of type + * %DRM_XE_PXP_TYPE_HWDRM will be marked as invalid if a PXP invalidation + * event occurs after their creation. Attempting to flip an invalid object + * will cause a black frame to be displayed instead. Submissions with invalid + * objects mapped in the VM will be rejected. */ struct drm_xe_gem_create { +#define DRM_XE_GEM_CREATE_EXTENSION_SET_PROPERTY 0 +#define DRM_XE_GEM_CREATE_SET_PROPERTY_PXP_TYPE 0 /** @extensions: Pointer to the first extension struct, if any */ __u64 extensions; @@ -809,6 +861,32 @@ struct drm_xe_gem_create { /** * struct drm_xe_gem_mmap_offset - Input of &DRM_IOCTL_XE_GEM_MMAP_OFFSET + * + * The @flags can be: + * - %DRM_XE_MMAP_OFFSET_FLAG_PCI_BARRIER - For user to query special offset + * for use in mmap ioctl. Writing to the returned mmap address will generate a + * PCI memory barrier with low overhead (avoiding IOCTL call as well as writing + * to VRAM which would also add overhead), acting like an MI_MEM_FENCE + * instruction. + * + * Note: The mmap size can be at most 4K, due to HW limitations. As a result + * this interface is only supported on CPU architectures that support 4K page + * size. The mmap_offset ioctl will detect this and gracefully return an + * error, where userspace is expected to have a different fallback method for + * triggering a barrier. + * + * Roughly the usage would be as follows: + * + * .. code-block:: C + * + * struct drm_xe_gem_mmap_offset mmo = { + * .handle = 0, // must be set to 0 + * .flags = DRM_XE_MMAP_OFFSET_FLAG_PCI_BARRIER, + * }; + * + * err = ioctl(fd, DRM_IOCTL_XE_GEM_MMAP_OFFSET, &mmo); + * map = mmap(NULL, size, PROT_WRITE, MAP_SHARED, fd, mmo.offset); + * map[i] = 0xdeadbeaf; // issue barrier */ struct drm_xe_gem_mmap_offset { /** @extensions: Pointer to the first extension struct, if any */ @@ -817,7 +895,8 @@ struct drm_xe_gem_mmap_offset { /** @handle: Handle for the object being mapped. */ __u32 handle; - /** @flags: Must be zero */ +#define DRM_XE_MMAP_OFFSET_FLAG_PCI_BARRIER (1 << 0) + /** @flags: Flags */ __u32 flags; /** @offset: The fake offset to use for subsequent mmap call */ @@ -904,6 +983,9 @@ struct drm_xe_vm_destroy { * will only be valid for DRM_XE_VM_BIND_OP_MAP operations, the BO * handle MBZ, and the BO offset MBZ. This flag is intended to * implement VK sparse bindings. + * - %DRM_XE_VM_BIND_FLAG_CHECK_PXP - If the object is encrypted via PXP, + * reject the binding if the encryption key is no longer valid. This + * flag has no effect on BOs that are not marked as using PXP. */ struct drm_xe_vm_bind_op { /** @extensions: Pointer to the first extension struct, if any */ @@ -994,6 +1076,7 @@ struct drm_xe_vm_bind_op { #define DRM_XE_VM_BIND_FLAG_IMMEDIATE (1 << 1) #define DRM_XE_VM_BIND_FLAG_NULL (1 << 2) #define DRM_XE_VM_BIND_FLAG_DUMPABLE (1 << 3) +#define DRM_XE_VM_BIND_FLAG_CHECK_PXP (1 << 4) /** @flags: Bind flags */ __u32 flags; @@ -1085,6 +1168,24 @@ struct drm_xe_vm_bind { /** * struct drm_xe_exec_queue_create - Input of &DRM_IOCTL_XE_EXEC_QUEUE_CREATE * + * This ioctl supports setting the following properties via the + * %DRM_XE_EXEC_QUEUE_EXTENSION_SET_PROPERTY extension, which uses the + * generic @drm_xe_ext_set_property struct: + * + * - %DRM_XE_EXEC_QUEUE_SET_PROPERTY_PRIORITY - set the queue priority. + * CAP_SYS_NICE is required to set a value above normal. + * - %DRM_XE_EXEC_QUEUE_SET_PROPERTY_TIMESLICE - set the queue timeslice + * duration in microseconds. + * - %DRM_XE_EXEC_QUEUE_SET_PROPERTY_PXP_TYPE - set the type of PXP session + * this queue will be used with. Valid values are listed in enum + * drm_xe_pxp_session_type. %DRM_XE_PXP_TYPE_NONE is the default behavior, so + * there is no need to explicitly set that. When a queue of type + * %DRM_XE_PXP_TYPE_HWDRM is created, the PXP default HWDRM session + * (%XE_PXP_HWDRM_DEFAULT_SESSION) will be started, if isn't already running. + * Given that going into a power-saving state kills PXP HWDRM sessions, + * runtime PM will be blocked while queues of this type are alive. + * All PXP queues will be killed if a PXP invalidation event occurs. + * * The example below shows how to use @drm_xe_exec_queue_create to create * a simple exec_queue (no parallel submission) of class * &DRM_XE_ENGINE_CLASS_RENDER. @@ -1108,7 +1209,7 @@ struct drm_xe_exec_queue_create { #define DRM_XE_EXEC_QUEUE_EXTENSION_SET_PROPERTY 0 #define DRM_XE_EXEC_QUEUE_SET_PROPERTY_PRIORITY 0 #define DRM_XE_EXEC_QUEUE_SET_PROPERTY_TIMESLICE 1 - +#define DRM_XE_EXEC_QUEUE_SET_PROPERTY_PXP_TYPE 2 /** @extensions: Pointer to the first extension struct, if any */ __u64 extensions; @@ -1483,6 +1584,9 @@ struct drm_xe_oa_unit { /** @capabilities: OA capabilities bit-mask */ __u64 capabilities; #define DRM_XE_OA_CAPS_BASE (1 << 0) +#define DRM_XE_OA_CAPS_SYNCS (1 << 1) +#define DRM_XE_OA_CAPS_OA_BUFFER_SIZE (1 << 2) +#define DRM_XE_OA_CAPS_WAIT_NUM_REPORTS (1 << 3) /** @oa_timestamp_freq: OA timestamp freq */ __u64 oa_timestamp_freq; @@ -1632,6 +1736,36 @@ enum drm_xe_oa_property_id { * to be disabled for the stream exec queue. */ DRM_XE_OA_PROPERTY_NO_PREEMPT, + + /** + * @DRM_XE_OA_PROPERTY_NUM_SYNCS: Number of syncs in the sync array + * specified in @DRM_XE_OA_PROPERTY_SYNCS + */ + DRM_XE_OA_PROPERTY_NUM_SYNCS, + + /** + * @DRM_XE_OA_PROPERTY_SYNCS: Pointer to struct @drm_xe_sync array + * with array size specified via @DRM_XE_OA_PROPERTY_NUM_SYNCS. OA + * configuration will wait till input fences signal. Output fences + * will signal after the new OA configuration takes effect. For + * @DRM_XE_SYNC_TYPE_USER_FENCE, @addr is a user pointer, similar + * to the VM bind case. + */ + DRM_XE_OA_PROPERTY_SYNCS, + + /** + * @DRM_XE_OA_PROPERTY_OA_BUFFER_SIZE: Size of OA buffer to be + * allocated by the driver in bytes. Supported sizes are powers of + * 2 from 128 KiB to 128 MiB. When not specified, a 16 MiB OA + * buffer is allocated by default. + */ + DRM_XE_OA_PROPERTY_OA_BUFFER_SIZE, + + /** + * @DRM_XE_OA_PROPERTY_WAIT_NUM_REPORTS: Number of reports to wait + * for before unblocking poll or read + */ + DRM_XE_OA_PROPERTY_WAIT_NUM_REPORTS, }; /** @@ -1694,6 +1828,26 @@ struct drm_xe_oa_stream_info { __u64 reserved[3]; }; +/** + * enum drm_xe_pxp_session_type - Supported PXP session types. + * + * We currently only support HWDRM sessions, which are used for protected + * content that ends up being displayed, but the HW supports multiple types, so + * we might extend support in the future. + */ +enum drm_xe_pxp_session_type { + /** @DRM_XE_PXP_TYPE_NONE: PXP not used */ + DRM_XE_PXP_TYPE_NONE = 0, + /** + * @DRM_XE_PXP_TYPE_HWDRM: HWDRM sessions are used for content that ends + * up on the display. + */ + DRM_XE_PXP_TYPE_HWDRM = 1, +}; + +/* ID of the protected content session managed by Xe when PXP is active */ +#define DRM_XE_PXP_HWDRM_DEFAULT_SESSION 0xf + #if defined(__cplusplus) } #endif diff --git a/media_softlet/linux/common/os/xe/mos_bufmgr_xe.c b/media_softlet/linux/common/os/xe/mos_bufmgr_xe.c index e919da1a44d..f4581d27e0f 100644 --- a/media_softlet/linux/common/os/xe/mos_bufmgr_xe.c +++ b/media_softlet/linux/common/os/xe/mos_bufmgr_xe.c @@ -899,7 +899,6 @@ mos_context_create_shared_xe( { MOS_UNUSED(ctx); MOS_UNUSED(ctx_type); - MOS_UNUSED(bContextProtected); MOS_DRM_CHK_NULL_RETURN_VALUE(bufmgr, nullptr) MOS_DRM_CHK_NULL_RETURN_VALUE(engine_map, nullptr) @@ -925,6 +924,10 @@ mos_context_create_shared_xe( context = MOS_New(mos_xe_context); MOS_DRM_CHK_NULL_RETURN_VALUE(context, nullptr) + struct drm_xe_ext_set_property* ext = nullptr; + struct drm_xe_ext_set_property timeslice; + struct drm_xe_ext_set_property protect; + /** * Set exec_queue timeslice for render/ compute only as WA to ensure exec sequence. * Note, this is caused by a potential issue in kmd since exec_queue preemption by plenty of WL w/ same priority. @@ -934,7 +937,6 @@ mos_context_create_shared_xe( && (ctx_width * num_placements == 1) && bufmgr_gem->exec_queue_timeslice != EXEC_QUEUE_TIMESLICE_DEFAULT) { - struct drm_xe_ext_set_property timeslice; memclear(timeslice); timeslice.property = DRM_XE_EXEC_QUEUE_SET_PROPERTY_TIMESLICE; /** @@ -942,11 +944,27 @@ mos_context_create_shared_xe( */ timeslice.value = bufmgr_gem->exec_queue_timeslice; timeslice.base.name = DRM_XE_EXEC_QUEUE_EXTENSION_SET_PROPERTY; - create.extensions = (uintptr_t)(×lice); + ext = ×lice; MOS_DRM_NORMALMESSAGE("WA: exec_queue timeslice set by engine class(%d), value(%d)", engine_class, bufmgr_gem->exec_queue_timeslice); } + /** + * Set exec_queue protect for PXP usage. + */ + if (bContextProtected) + { + memclear(protect); + protect.base.name = DRM_XE_EXEC_QUEUE_EXTENSION_SET_PROPERTY, + protect.property = DRM_XE_EXEC_QUEUE_SET_PROPERTY_PXP_TYPE, + protect.value = DRM_XE_PXP_TYPE_HWDRM; + + protect.base.next_extension = (uintptr_t)ext; + ext = &protect; + } + + create.extensions = (uintptr_t)ext; + ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_XE_EXEC_QUEUE_CREATE, &create); MOS_DRM_CHK_STATUS_MESSAGE_RETURN_VALUE_WH_OP(ret, context, MOS_Delete, nullptr,