+ }
+
/* pad_to_size was once a reserved field, so sanitize it */
if (entry->flags & EXEC_OBJECT_PAD_TO_SIZE) {
if (unlikely(offset_in_page(entry->pad_to_size)))
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object.c
b/drivers/gpu/drm/i915/gem/i915_gem_object.c
index 6cdff5fc5882..b321f5484ae6 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_object.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_object.c
@@ -25,6 +25,7 @@
#include <linux/sched/mm.h>
#include "display/intel_frontbuffer.h"
+#include "pxp/intel_pxp.h"
#include "i915_drv.h"
#include "i915_gem_clflush.h"
#include "i915_gem_context.h"
@@ -72,6 +73,8 @@ void i915_gem_object_init(struct
drm_i915_gem_object *obj,
INIT_LIST_HEAD(&obj->lut_list);
spin_lock_init(&obj->lut_lock);
+ INIT_LIST_HEAD(&obj->pxp_link);
+
spin_lock_init(&obj->mmo.lock);
obj->mmo.offsets = RB_ROOT;
@@ -120,6 +123,9 @@ static void i915_gem_close_object(struct
drm_gem_object *gem, struct drm_file *f
struct i915_lut_handle *lut, *ln;
LIST_HEAD(close);
+ if (i915_gem_object_has_valid_protection(obj))
+ intel_pxp_object_remove(obj);
+
spin_lock(&obj->lut_lock);
list_for_each_entry_safe(lut, ln, &obj->lut_list, obj_link) {
struct i915_gem_context *ctx = lut->ctx;
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object.h
b/drivers/gpu/drm/i915/gem/i915_gem_object.h
index 366d23afbb1a..a1fa7539c0f7 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_object.h
+++ b/drivers/gpu/drm/i915/gem/i915_gem_object.h
@@ -274,6 +274,18 @@ i915_gem_object_needs_async_cancel(const
struct drm_i915_gem_object *obj)
return i915_gem_object_type_has(obj,
I915_GEM_OBJECT_ASYNC_CANCEL);
}
+static inline bool
+i915_gem_object_is_protected(const struct drm_i915_gem_object *obj)
+{
+ return obj->user_flags & I915_GEM_OBJECT_PROTECTED;
+}
+
+static inline bool
+i915_gem_object_has_valid_protection(const struct
drm_i915_gem_object *obj)
+{
+ return i915_gem_object_is_protected(obj) &&
!list_empty(&obj->pxp_link);
+}
+
static inline bool
i915_gem_object_is_framebuffer(const struct drm_i915_gem_object
*obj)
{
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object_types.h
b/drivers/gpu/drm/i915/gem/i915_gem_object_types.h
index 0a1fdbac882e..6eee580c7aba 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_object_types.h
+++ b/drivers/gpu/drm/i915/gem/i915_gem_object_types.h
@@ -167,6 +167,11 @@ struct drm_i915_gem_object {
} mmo;
I915_SELFTEST_DECLARE(struct list_head st_link);
+ /**
+ * @user_flags: small set of booleans set by the user
+ */
+ unsigned long user_flags;
+#define I915_GEM_OBJECT_PROTECTED BIT(0)
unsigned long flags;
#define I915_BO_ALLOC_CONTIGUOUS BIT(0)
@@ -290,6 +295,14 @@ struct drm_i915_gem_object {
bool dirty:1;
} mm;
+ /*
+ * When the PXP session is invalidated, we need to mark all
protected
+ * objects as invalid. To easily do so we add them all to a
list. The
+ * presence on the list is used to check if the encryption is
valid or
+ * not.
+ */
+ struct list_head pxp_link;
+
/** Record of address bit 17 of each page at last unbind. */
unsigned long *bit_17;
diff --git a/drivers/gpu/drm/i915/pxp/intel_pxp.c
b/drivers/gpu/drm/i915/pxp/intel_pxp.c
index 5912e4a12d94..03151cd7f4b8 100644
--- a/drivers/gpu/drm/i915/pxp/intel_pxp.c
+++ b/drivers/gpu/drm/i915/pxp/intel_pxp.c
@@ -69,6 +69,8 @@ void intel_pxp_init(struct intel_pxp *pxp)
return;
mutex_init(&pxp->mutex);
+ spin_lock_init(&pxp->lock);
+ INIT_LIST_HEAD(&pxp->protected_objects);
/*
* we'll use the completion to check if there is a
termination pending,
@@ -136,11 +138,49 @@ int
intel_pxp_wait_for_termination_completion(struct intel_pxp *pxp)
return ret;
}
+int intel_pxp_object_add(struct drm_i915_gem_object *obj)
+{
+ struct intel_pxp *pxp = &to_i915(obj->base.dev)->gt.pxp;
+
+ if (!intel_pxp_is_enabled(pxp))
+ return -ENODEV;
+
+ if (!list_empty(&obj->pxp_link))
+ return -EEXIST;
+
+ spin_lock_irq(&pxp->lock);
+ list_add(&obj->pxp_link, &pxp->protected_objects);
+ spin_unlock_irq(&pxp->lock);
+
+ return 0;
+}
+
+void intel_pxp_object_remove(struct drm_i915_gem_object *obj)
+{
+ struct intel_pxp *pxp = &to_i915(obj->base.dev)->gt.pxp;
+
+ if (!intel_pxp_is_enabled(pxp))
+ return;
+
+ spin_lock_irq(&pxp->lock);
+ list_del_init(&obj->pxp_link);
+ spin_unlock_irq(&pxp->lock);
+}
+
void intel_pxp_invalidate(struct intel_pxp *pxp)
{
struct drm_i915_private *i915 = pxp_to_gt(pxp)->i915;
+ struct drm_i915_gem_object *obj, *tmp;
struct i915_gem_context *ctx, *cn;
+ /* delete objects that have been used with the invalidated
session */
+ spin_lock_irq(&pxp->lock);
+ list_for_each_entry_safe(obj, tmp, &pxp->protected_objects,
pxp_link) {
+ if (i915_gem_object_has_pages(obj))
+ list_del_init(&obj->pxp_link);
+ }
+ spin_unlock_irq(&pxp->lock);
+
/* ban all contexts marked as protected */
spin_lock_irq(&i915->gem.contexts.lock);
list_for_each_entry_safe(ctx, cn, &i915->gem.contexts.list,
link) {
diff --git a/drivers/gpu/drm/i915/pxp/intel_pxp.h
b/drivers/gpu/drm/i915/pxp/intel_pxp.h
index e36200833095..3315b07d271b 100644
--- a/drivers/gpu/drm/i915/pxp/intel_pxp.h
+++ b/drivers/gpu/drm/i915/pxp/intel_pxp.h
@@ -9,6 +9,8 @@
#include "gt/intel_gt_types.h"
#include "intel_pxp_types.h"
+struct drm_i915_gem_object;
+
#define GEN12_DISPLAY_PXP_STATE_TERMINATED_INTERRUPT BIT(1)
#define GEN12_DISPLAY_APP_TERMINATED_PER_FW_REQ_INTERRUPT BIT(2)
#define GEN12_DISPLAY_STATE_RESET_COMPLETE_INTERRUPT BIT(3)
@@ -38,6 +40,9 @@ void intel_pxp_init(struct intel_pxp *pxp);
void intel_pxp_fini(struct intel_pxp *pxp);
int intel_pxp_wait_for_termination_completion(struct intel_pxp
*pxp);
+
+int intel_pxp_object_add(struct drm_i915_gem_object *obj);
+void intel_pxp_object_remove(struct drm_i915_gem_object *obj);
void intel_pxp_invalidate(struct intel_pxp *pxp);
#else
static inline void intel_pxp_init(struct intel_pxp *pxp)
@@ -52,6 +57,14 @@ static inline int
intel_pxp_wait_for_termination_completion(struct intel_pxp *px
{
return 0;
}
+
+static inline int intel_pxp_object_add(struct drm_i915_gem_object
*obj)
+{
+ return 0;
+}
+static inline void intel_pxp_object_remove(struct
drm_i915_gem_object *obj)
+{
+}
#endif
#endif /* __INTEL_PXP_H__ */
diff --git a/drivers/gpu/drm/i915/pxp/intel_pxp_types.h
b/drivers/gpu/drm/i915/pxp/intel_pxp_types.h
index 6f659a6f8f1c..53a2a8acfe51 100644
--- a/drivers/gpu/drm/i915/pxp/intel_pxp_types.h
+++ b/drivers/gpu/drm/i915/pxp/intel_pxp_types.h
@@ -7,8 +7,10 @@
#define __INTEL_PXP_TYPES_H__
#include <linux/completion.h>
+#include <linux/list.h>
#include <linux/types.h>
#include <linux/mutex.h>
+#include <linux/spinlock.h>
#include <linux/workqueue.h>
struct intel_context;
@@ -28,6 +30,9 @@ struct intel_pxp {
struct work_struct irq_work;
bool irq_enabled;
u32 current_events; /* protected with gt->irq_lock */
+
+ struct spinlock lock;
+ struct list_head protected_objects;
};
#endif /* __INTEL_PXP_TYPES_H__ */
diff --git a/include/uapi/drm/i915_drm.h b/include/uapi/drm/i915_drm.h
index 9ebe8523aa0c..0f8b771a6d53 100644
--- a/include/uapi/drm/i915_drm.h
+++ b/include/uapi/drm/i915_drm.h
@@ -1753,6 +1753,28 @@ struct drm_i915_gem_object_param {
*/
#define I915_OBJECT_PARAM (1ull << 32)
+/*
+ * I915_OBJECT_PARAM_PROTECTED_CONTENT:
+ *
+ * If set to true, buffer contents is expected to be protected by PXP
+ * encryption and requires decryption for scan out and processing.
This is
+ * only possible on platforms that have PXP enabled, on all other
scenarios
+ * setting this flag will cause the ioctl to fail and return -ENODEV.
+ *
+ * Protected buffers can only be used with contexts created using the
+ * I915_CONTEXT_PARAM_PROTECTED_CONTENT flag. The buffer contents are
+ * considered invalid after a PXP session teardown.
+ *
+ * Given the restriction above, the following errors are possible
when
+ * submitting a protected object in an execbuf call:
+ *
+ * -ENODEV: PXP session not currently active
+ * -EIO: buffer has become invalid after a teardown event
+ * -EPERM: buffer submitted using a context not marked as protected
+ */
+#define I915_OBJECT_PARAM_PROTECTED_CONTENT 0x0
+/* Must be kept compact -- no holes and well documented */
+
__u64 param;
/* Data value or pointer */