Skip to content

Commit

Permalink
[CP] Create Protected Queue for Protected Context
Browse files Browse the repository at this point in the history
Protected queue is required for protected execution.
  • Loading branch information
lixin5x authored and intel-mediadev committed Feb 19, 2025
1 parent 223d039 commit 050948b
Show file tree
Hide file tree
Showing 3 changed files with 222 additions and 6 deletions.
44 changes: 44 additions & 0 deletions media_softlet/linux/common/os/xe/include/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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 <[email protected]>
Cc: Matthew Brost <[email protected]>
Cc: Thomas Hellström <[email protected]>
Cc: John Harrison <[email protected]>
Cc: Jani Nikula <[email protected]>
Reviewed-by: default avatarJohn Harrison <[email protected]>
Link: https://patchwork.freedesktop.org/patch/msgid/[email protected]

commit f2881dfdaaa9ec873dbd383ef5512fc31e576cbb (HEAD -> drm-xe-next, origin/drm-xe-next)

drm/xe/oa/uapi: Make bit masks unsigned
Expand Down
160 changes: 157 additions & 3 deletions media_softlet/linux/common/os/xe/include/xe_drm.h
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down Expand Up @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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;

Expand Down Expand Up @@ -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;

Expand Down Expand Up @@ -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 */
Expand All @@ -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 */
Expand Down Expand Up @@ -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 */
Expand Down Expand Up @@ -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;

Expand Down Expand Up @@ -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.
Expand All @@ -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;

Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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,
};

/**
Expand Down Expand Up @@ -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
Expand Down
24 changes: 21 additions & 3 deletions media_softlet/linux/common/os/xe/mos_bufmgr_xe.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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.
Expand All @@ -934,19 +937,34 @@ 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;
/**
* Note, this value indicates to maximum of time slice for WL instead of real waiting time.
*/
timeslice.value = bufmgr_gem->exec_queue_timeslice;
timeslice.base.name = DRM_XE_EXEC_QUEUE_EXTENSION_SET_PROPERTY;
create.extensions = (uintptr_t)(&timeslice);
ext = &timeslice;
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,
Expand Down

0 comments on commit 050948b

Please sign in to comment.