With this ioctl action, userspace driver can reserve one or
multiple session slot/id assigned by kernel PXP, as the first
step of PXP session establishment flow. The session info is
stored in the session list structure.

Signed-off-by: Huang, Sean Z <sean.z.hu...@intel.com>
---
 drivers/gpu/drm/i915/Makefile                |   1 +
 drivers/gpu/drm/i915/pxp/intel_pxp.c         |  91 +++++++++
 drivers/gpu/drm/i915/pxp/intel_pxp.h         |  22 +++
 drivers/gpu/drm/i915/pxp/intel_pxp_arb.c     |   2 -
 drivers/gpu/drm/i915/pxp/intel_pxp_cmd.c     |   3 -
 drivers/gpu/drm/i915/pxp/intel_pxp_context.c |   3 +
 drivers/gpu/drm/i915/pxp/intel_pxp_context.h |   3 +
 drivers/gpu/drm/i915/pxp/intel_pxp_sm.c      | 194 +++++++++++++++++++
 drivers/gpu/drm/i915/pxp/intel_pxp_sm.h      |  43 ++++
 9 files changed, 357 insertions(+), 5 deletions(-)
 create mode 100644 drivers/gpu/drm/i915/pxp/intel_pxp_sm.c
 create mode 100644 drivers/gpu/drm/i915/pxp/intel_pxp_sm.h

diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
index d419dfa4923d..f8ef435b35d4 100644
--- a/drivers/gpu/drm/i915/Makefile
+++ b/drivers/gpu/drm/i915/Makefile
@@ -262,6 +262,7 @@ i915-$(CONFIG_DRM_I915_PXP) += \
        pxp/intel_pxp_cmd.o \
        pxp/intel_pxp_context.o \
        pxp/intel_pxp_pm.o \
+       pxp/intel_pxp_sm.o \
        pxp/intel_pxp_tee.o
 
 # Post-mortem debug and GPU hang state capture
diff --git a/drivers/gpu/drm/i915/pxp/intel_pxp.c 
b/drivers/gpu/drm/i915/pxp/intel_pxp.c
index ce3760206b76..e294134fef78 100644
--- a/drivers/gpu/drm/i915/pxp/intel_pxp.c
+++ b/drivers/gpu/drm/i915/pxp/intel_pxp.c
@@ -7,6 +7,7 @@
 #include "intel_pxp_context.h"
 #include "intel_pxp_tee.h"
 #include "intel_pxp_arb.h"
+#include "intel_pxp_sm.h"
 
 /* KCR register definitions */
 #define KCR_INIT            _MMIO(0x320f0)
@@ -14,6 +15,36 @@
 /* Setting KCR Init bit is required after system boot */
 #define KCR_INIT_ALLOW_DISPLAY_ME_WRITES (BIT(14) | (BIT(14) << 
KCR_INIT_MASK_SHIFT))
 
+#define PXP_ACTION_SET_SESSION_STATUS 1
+#define PXP_REQ_SESSION_ID_INIT 0
+
+/*
+ * struct pxp_set_session_status_params - Params to reserved, set or destroy
+ * the session from the PXP state machine.
+ */
+struct pxp_set_session_status_params {
+       u32 pxp_tag; /* in [optional], out pxp tag */
+       u32 session_type; /* in, session type */
+       u32 session_mode; /* in, session mode */
+       u32 req_session_state; /* in, new session state */
+};
+
+/* struct pxp_info - Params for PXP operation. */
+struct pxp_info {
+       u32 action; /* in - specified action of this operation */
+       u32 sm_status; /* out - status output for this operation */
+
+       /* in - action params to set the PXP session state */
+       struct pxp_set_session_status_params set_session_status;
+} __attribute__((packed));
+
+struct drm_i915_pxp_ops {
+       /* in - user space pointer to struct pxp_info */
+       struct pxp_info __user *info_ptr;
+       /* in - memory size that info_ptr points to */
+       u32 info_size;
+};
+
 static void intel_pxp_write_irq_mask_reg(struct intel_gt *gt, u32 mask)
 {
        lockdep_assert_held(&gt->irq_lock);
@@ -152,3 +183,63 @@ bool intel_pxp_gem_object_status(struct drm_i915_private 
*i915)
        else
                return false;
 }
+
+int i915_pxp_ops_ioctl(struct drm_device *dev, void *data, struct drm_file 
*drmfile)
+{
+       int ret;
+       struct pxp_info pxp_info = {0};
+       struct drm_i915_pxp_ops *pxp_ops = data;
+       struct drm_i915_private *i915 = to_i915(dev);
+       struct intel_pxp *pxp = &i915->gt.pxp;
+
+       if (pxp->ctx.id == 0 || !drmfile || !pxp_ops ||
+           pxp_ops->info_size != sizeof(pxp_info))
+               return -EINVAL;
+
+       if (copy_from_user(&pxp_info, pxp_ops->info_ptr, sizeof(pxp_info)) != 0)
+               return -EFAULT;
+
+       mutex_lock(&pxp->ctx.mutex);
+
+       if (pxp->ctx.global_state_in_suspend) {
+               drm_err(&i915->drm, "Return failure due to state in suspend\n");
+               pxp_info.sm_status = PXP_SM_STATUS_SESSION_NOT_AVAILABLE;
+               ret = 0;
+               goto end;
+       }
+
+       if (pxp->ctx.global_state_attacked) {
+               drm_err(&i915->drm, "Retry required due to state attacked\n");
+               pxp_info.sm_status = PXP_SM_STATUS_RETRY_REQUIRED;
+               ret = 0;
+               goto end;
+       }
+
+       if (pxp_info.action == PXP_ACTION_SET_SESSION_STATUS) {
+               struct pxp_set_session_status_params *params = 
&pxp_info.set_session_status;
+
+               if (params->req_session_state == PXP_REQ_SESSION_ID_INIT) {
+                       ret = intel_pxp_sm_ioctl_reserve_session(pxp, drmfile,
+                                                                
params->session_type,
+                                                                
params->session_mode,
+                                                                
&params->pxp_tag);
+                       if (ret == PXP_SM_STATUS_RETRY_REQUIRED ||
+                           ret == PXP_SM_STATUS_SESSION_NOT_AVAILABLE) {
+                               pxp_info.sm_status = ret;
+                               ret = 0;
+                       }
+               } else {
+                       ret = -EINVAL;
+               }
+       } else {
+               ret = -EINVAL;
+       }
+
+end:
+       mutex_unlock(&pxp->ctx.mutex);
+
+       if (ret == 0)
+               if (copy_to_user(pxp_ops->info_ptr, &pxp_info, 
sizeof(pxp_info)) != 0)
+                       ret = -EFAULT;
+       return ret;
+}
diff --git a/drivers/gpu/drm/i915/pxp/intel_pxp.h 
b/drivers/gpu/drm/i915/pxp/intel_pxp.h
index 027c0eb84a52..461b9321441f 100644
--- a/drivers/gpu/drm/i915/pxp/intel_pxp.h
+++ b/drivers/gpu/drm/i915/pxp/intel_pxp.h
@@ -7,12 +7,21 @@
 #define __INTEL_PXP_H__
 
 #include <linux/workqueue.h>
+#include <drm/drm_file.h>
 #include "intel_pxp_context.h"
 
 #define PXP_IRQ_VECTOR_DISPLAY_PXP_STATE_TERMINATED BIT(1)
 #define PXP_IRQ_VECTOR_DISPLAY_APP_TERM_PER_FW_REQ BIT(2)
 #define PXP_IRQ_VECTOR_PXP_DISP_STATE_RESET_COMPLETE BIT(3)
 
+#define GEN12_KCR_SIP _MMIO(0x32260) /* KCR type0 session in play 0-31 */
+
+#define PXP_MAX_TYPE0_SESSIONS 16
+#define PXP_MAX_TYPE1_SESSIONS 6
+
+/* we need to reserve one type0 slot for arbitrary session */
+#define PXP_MAX_NORMAL_TYPE0_SESSIONS (PXP_MAX_TYPE0_SESSIONS - 1)
+
 enum pxp_session_types {
        SESSION_TYPE_TYPE0 = 0,
        SESSION_TYPE_TYPE1 = 1,
@@ -29,6 +38,13 @@ enum pxp_protection_modes {
        PROTECTION_MODE_ALL
 };
 
+enum pxp_sm_status {
+       PXP_SM_STATUS_SUCCESS,
+       PXP_SM_STATUS_RETRY_REQUIRED,
+       PXP_SM_STATUS_SESSION_NOT_AVAILABLE,
+       PXP_SM_STATUS_ERROR_UNKNOWN
+};
+
 struct intel_pxp {
        struct work_struct irq_work;
        u32 handled_irr;
@@ -47,6 +63,7 @@ int i915_pxp_global_terminate_complete_callback(struct 
intel_pxp *pxp);
 int intel_pxp_init(struct intel_pxp *pxp);
 void intel_pxp_uninit(struct intel_pxp *pxp);
 bool intel_pxp_gem_object_status(struct drm_i915_private *i915);
+int i915_pxp_ops_ioctl(struct drm_device *dev, void *data, struct drm_file 
*drmfile);
 #else
 static inline void intel_pxp_irq_handler(struct intel_pxp *pxp, u16 iir)
 {
@@ -75,6 +92,11 @@ static inline bool intel_pxp_gem_object_status(struct 
drm_i915_private *i915)
 {
        return false;
 }
+
+static inline int i915_pxp_ops_ioctl(struct drm_device *dev, void *data, 
struct drm_file *drmfile)
+{
+       return 0;
+}
 #endif
 
 #endif /* __INTEL_PXP_PM_H__ */
diff --git a/drivers/gpu/drm/i915/pxp/intel_pxp_arb.c 
b/drivers/gpu/drm/i915/pxp/intel_pxp_arb.c
index d94b08fe9190..a3a1df42a869 100644
--- a/drivers/gpu/drm/i915/pxp/intel_pxp_arb.c
+++ b/drivers/gpu/drm/i915/pxp/intel_pxp_arb.c
@@ -12,8 +12,6 @@
 #include "intel_pxp_tee.h"
 #include "intel_pxp_cmd.h"
 
-#define GEN12_KCR_SIP _MMIO(0x32260) /* KCR type0 session in play 0-31 */
-
 /* Arbitrary session */
 #define ARB_SESSION_INDEX 0xf
 #define ARB_SESSION_TYPE SESSION_TYPE_TYPE0
diff --git a/drivers/gpu/drm/i915/pxp/intel_pxp_cmd.c 
b/drivers/gpu/drm/i915/pxp/intel_pxp_cmd.c
index 079024d5f063..17ff6bd61d20 100644
--- a/drivers/gpu/drm/i915/pxp/intel_pxp_cmd.c
+++ b/drivers/gpu/drm/i915/pxp/intel_pxp_cmd.c
@@ -24,9 +24,6 @@
 /* CRYPTO_KEY_EXCHANGE */
 #define CRYPTO_KEY_EXCHANGE ((0x3 << 29) | (0x01609 << 16))
 
-#define PXP_MAX_TYPE0_SESSIONS 16
-#define PXP_MAX_TYPE1_SESSIONS 6
-
 static struct i915_vma *intel_pxp_cmd_get_batch(struct intel_pxp *pxp,
                                                struct intel_context *ce,
                                                struct 
intel_gt_buffer_pool_node *pool,
diff --git a/drivers/gpu/drm/i915/pxp/intel_pxp_context.c 
b/drivers/gpu/drm/i915/pxp/intel_pxp_context.c
index d00f4e0b88ba..f690c1470bd5 100644
--- a/drivers/gpu/drm/i915/pxp/intel_pxp_context.c
+++ b/drivers/gpu/drm/i915/pxp/intel_pxp_context.c
@@ -17,6 +17,9 @@ void intel_pxp_ctx_init(struct pxp_context *ctx)
        ctx->global_state_attacked = false;
 
        mutex_init(&ctx->mutex);
+
+       INIT_LIST_HEAD(&ctx->type0_sessions);
+       INIT_LIST_HEAD(&ctx->type1_sessions);
 }
 
 /**
diff --git a/drivers/gpu/drm/i915/pxp/intel_pxp_context.h 
b/drivers/gpu/drm/i915/pxp/intel_pxp_context.h
index 8d3308ac3120..4c583f831831 100644
--- a/drivers/gpu/drm/i915/pxp/intel_pxp_context.h
+++ b/drivers/gpu/drm/i915/pxp/intel_pxp_context.h
@@ -17,6 +17,9 @@ struct pxp_context {
        struct pxp_protected_session arb_session;
        u32 arb_session_pxp_tag;
 
+       struct list_head type0_sessions;
+       struct list_head type1_sessions;
+
        int id;
 
        bool global_state_attacked;
diff --git a/drivers/gpu/drm/i915/pxp/intel_pxp_sm.c 
b/drivers/gpu/drm/i915/pxp/intel_pxp_sm.c
new file mode 100644
index 000000000000..e30be334d0dd
--- /dev/null
+++ b/drivers/gpu/drm/i915/pxp/intel_pxp_sm.c
@@ -0,0 +1,194 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright(c) 2020, Intel Corporation. All rights reserved.
+ */
+#include "gt/intel_context.h"
+#include "gt/intel_engine_pm.h"
+#include "intel_pxp_sm.h"
+#include "intel_pxp.h"
+
+#define KCR_STATUS_1   _MMIO(0x320f4)
+#define KCR_STATUS_1_ATTACK_MASK 0x80000000
+
+#define GEN12_KCR_TSIP _MMIO(0x32264) /* KCR type1 session in play 0-63 */
+
+static inline int session_max(int session_type)
+{
+       return (session_type == SESSION_TYPE_TYPE0) ?
+               PXP_MAX_NORMAL_TYPE0_SESSIONS : PXP_MAX_TYPE1_SESSIONS;
+}
+
+static inline struct list_head *session_list(struct intel_pxp *pxp,
+                                            int session_type)
+{
+       return (session_type == SESSION_TYPE_TYPE0) ?
+               &pxp->ctx.type0_sessions : &pxp->ctx.type1_sessions;
+}
+
+/**
+ * is_sw_session_active - Check if the given sw session id is active.
+ * @pxp: pointer to pxp struct
+ * @session_type: Specified session type
+ * @session_index: Numeric session identifier.
+ * @is_in_play: Set false to return true if the specified session is active.
+ *              Set true to also check if the session is active and in_play.
+ *
+ * The caller needs to use mutex lock to protect the session list
+ * inside this function.
+ *
+ * Return : true if session with the same identifier is active (and in_play).
+ */
+static bool is_sw_session_active(struct intel_pxp *pxp, int session_type,
+                                int session_index, bool is_in_play)
+{
+       struct intel_pxp_sm_session *curr, *n;
+
+       lockdep_assert_held(&pxp->ctx.mutex);
+
+       list_for_each_entry_safe(curr, n, session_list(pxp, session_type), 
list) {
+               if (curr->index == session_index) {
+                       if (is_in_play && !curr->is_in_play)
+                               return false;
+                       return true;
+               }
+       }
+
+       return false;
+}
+
+static bool is_hw_session_in_play(struct intel_pxp *pxp,
+                                 int session_type, int session_index)
+{
+       u64 regval_sip = 0;
+       intel_wakeref_t wakeref;
+       struct intel_gt *gt = container_of(pxp, struct intel_gt, pxp);
+
+       with_intel_runtime_pm(&gt->i915->runtime_pm, wakeref) {
+               if (session_type == SESSION_TYPE_TYPE0)
+                       regval_sip = intel_uncore_read(gt->uncore, 
GEN12_KCR_SIP);
+               else
+                       regval_sip = intel_uncore_read64(gt->uncore, 
GEN12_KCR_TSIP);
+       }
+
+       return regval_sip & BIT(session_index);
+}
+
+/* wait hw session_in_play reg to match the current sw state */
+static int wait_hw_sw_state(struct intel_pxp *pxp, int session_index, int 
session_type)
+{
+       const int max_retry = 10;
+       int retry = 0;
+
+       for (retry = 0; retry < max_retry; retry++) {
+               if (is_hw_session_in_play(pxp, session_type, session_index) ==
+                   is_sw_session_active(pxp, session_type, session_index, 
true))
+                       return 0;
+
+               msleep(10);
+       }
+       return -EINVAL;
+}
+
+/**
+ * is_type0_session_attacked - To check if type0 active sessions are attacked.
+ * @pxp: pointer pxp struct
+ *
+ * Return: true if hardware sessions is attacked, false otherwise.
+ */
+static bool is_type0_session_attacked(struct intel_pxp *pxp)
+{
+       u32 regval = 0;
+       intel_wakeref_t wakeref;
+       struct intel_gt *gt = container_of(pxp, struct intel_gt, pxp);
+
+       if (pxp->ctx.global_state_attacked)
+               return true;
+
+       with_intel_runtime_pm(&gt->i915->runtime_pm, wakeref)
+               regval = intel_uncore_read(gt->uncore, KCR_STATUS_1);
+
+       return regval & KCR_STATUS_1_ATTACK_MASK;
+}
+
+/**
+ * create_session_entry - Create a new session entry with provided info.
+ * @pxp: pointer to pxp struct
+ * @drmfile: pointer to drm_file
+ * @context_id: Numeric identifier of the context created by the caller.
+ * @session_type: Type of the session requested. One of enum pxp_session_types.
+ * @protection_mode: Type of protection requested for the session.
+ *                   One of the enum pxp_protection_modes.
+ * @session_index: Numeric session identifier.
+ *
+ * Return: status. 0 means creation is successful.
+ */
+static int create_session_entry(struct intel_pxp *pxp, struct drm_file 
*drmfile,
+                               int context_id, int session_type, int 
protection_mode,
+                               int session_index)
+{
+       struct intel_pxp_sm_session *session = NULL;
+       int pid = 0;
+
+       if (drmfile)
+               pid = pid_nr(drmfile->pid);
+
+       session = kzalloc(sizeof(*session), GFP_KERNEL);
+       if (!session)
+               return -ENOMEM;
+
+       session->context_id = context_id;
+       session->type = session_type;
+       session->protection_mode = protection_mode;
+       session->index = session_index;
+       session->is_in_play = false;
+       session->drmfile = drmfile;
+       session->pid = pid;
+
+       list_add(&session->list, session_list(pxp, session_type));
+       return 0;
+}
+
+/**
+ * intel_pxp_sm_ioctl_reserve_session - To reserve an available protected 
session.
+ * @pxp: pointer to pxp struct
+ * @drmfile: pointer to drm_file.
+ * @session_type: Type of the session requested. One of enum pxp_session_types.
+ * @protection_mode: Type of protection requested for the session. One of the
+ *                   enum pxp_protection_modes.
+ * @pxp_tag: Numeric session identifier returned back to caller.
+ *
+ * Return: status. 0 means reserve is successful.
+ */
+int intel_pxp_sm_ioctl_reserve_session(struct intel_pxp *pxp, struct drm_file 
*drmfile,
+                                      int session_type, int protection_mode,
+                                      u32 *pxp_tag)
+{
+       int ret;
+       int idx = 0;
+
+       if (!drmfile || !pxp_tag)
+               return -EINVAL;
+
+       lockdep_assert_held(&pxp->ctx.mutex);
+
+       /* check if sessions are under attack. if so, don't allow creation */
+       if (session_type == SESSION_TYPE_TYPE0 &&
+           is_type0_session_attacked(pxp))
+               return -EPERM;
+
+       for (idx = 0; idx < session_max(session_type); idx++) {
+               if (!is_sw_session_active(pxp, session_type, idx, false)) {
+                       ret = wait_hw_sw_state(pxp, idx, session_type);
+                       if (ret)
+                               return PXP_SM_STATUS_RETRY_REQUIRED;
+
+                       ret = create_session_entry(pxp, drmfile, pxp->ctx.id,
+                                                  session_type,
+                                                  protection_mode, idx);
+                       *pxp_tag = idx;
+                       return ret;
+               }
+       }
+
+       return PXP_SM_STATUS_SESSION_NOT_AVAILABLE;
+}
diff --git a/drivers/gpu/drm/i915/pxp/intel_pxp_sm.h 
b/drivers/gpu/drm/i915/pxp/intel_pxp_sm.h
new file mode 100644
index 000000000000..75fffb7d8b0e
--- /dev/null
+++ b/drivers/gpu/drm/i915/pxp/intel_pxp_sm.h
@@ -0,0 +1,43 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright(c) 2020, Intel Corporation. All rights reserved.
+ */
+
+#ifndef __INTEL_PXP_SM_H__
+#define __INTEL_PXP_SM_H__
+
+#include "intel_pxp.h"
+
+/**
+ * struct pxp_protected_session - linked list to track all active sessions.
+ */
+struct intel_pxp_sm_session {
+       /** @list: linked list infrastructure, do not change its order. */
+       struct list_head list;
+       /** @index: Numeric identifier for this protected session */
+       int index;
+       /** @type: Type of session */
+       int type;
+       /** @protection_mode: mode of protection requested */
+       int protection_mode;
+       /** @context_id: context identifier of the protected session requestor 
*/
+       int context_id;
+       /** @pid: pid of this session's creator */
+       int pid;
+       /** @drmfile: pointer to drm_file, which is allocated on device file 
open() call */
+       struct drm_file *drmfile;
+
+       /**
+        * @is_in_play: indicates whether the session has been established
+        *              in the HW root of trust if this flag is false, it
+        *              indicates an application has reserved this session,
+        *              but has not established the session in the hardware
+        *              yet.
+        */
+       bool is_in_play;
+};
+
+int intel_pxp_sm_ioctl_reserve_session(struct intel_pxp *pxp, struct drm_file 
*drmfile,
+                                      int session_type, int protection_mode,
+                                      u32 *pxp_tag);
+#endif /* __INTEL_PXP_SM_H__ */
-- 
2.17.1

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

Reply via email to