Teardown is triggered when the display topology changes and no long meets the secure playback requirement, and hardware trashes all the encryption keys for display. So as a result, PXP should handle such case and terminate the type0 sessions, which including arb session rev21: - Bug fixing, we need to set the PXP_GLOBAL_TERMINATE 0x320f8 register after arb session termination - Remove enum pxp_session_types and enum pxp_protection_modes from single session patch series. Signed-off-by: Huang, Sean Z <sean.z.huang@xxxxxxxxx> --- drivers/gpu/drm/i915/pxp/intel_pxp.c | 3 + drivers/gpu/drm/i915/pxp/intel_pxp_arb.c | 86 ++++++++++++++++++ drivers/gpu/drm/i915/pxp/intel_pxp_arb.h | 1 + drivers/gpu/drm/i915/pxp/intel_pxp_cmd.c | 109 +++++++++++++++++++++-- drivers/gpu/drm/i915/pxp/intel_pxp_cmd.h | 11 +-- 5 files changed, 200 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/i915/pxp/intel_pxp.c b/drivers/gpu/drm/i915/pxp/intel_pxp.c index 99cd93e12455..e6dd57ec73f5 100644 --- a/drivers/gpu/drm/i915/pxp/intel_pxp.c +++ b/drivers/gpu/drm/i915/pxp/intel_pxp.c @@ -29,6 +29,9 @@ static int intel_pxp_teardown_required_callback(struct intel_pxp *pxp) mutex_lock(&pxp->ctx.mutex); pxp->ctx.global_state_attacked = true; + pxp->ctx.flag_display_hm_surface_keys = false; + + ret = intel_pxp_arb_terminate_session_with_global_terminate(pxp); mutex_unlock(&pxp->ctx.mutex); diff --git a/drivers/gpu/drm/i915/pxp/intel_pxp_arb.c b/drivers/gpu/drm/i915/pxp/intel_pxp_arb.c index dd98ca407e78..cde5ddd73da9 100644 --- a/drivers/gpu/drm/i915/pxp/intel_pxp_arb.c +++ b/drivers/gpu/drm/i915/pxp/intel_pxp_arb.c @@ -10,9 +10,13 @@ #include "intel_pxp_arb.h" #include "intel_pxp.h" #include "intel_pxp_tee.h" +#include "intel_pxp_cmd.h" #define GEN12_KCR_SIP _MMIO(0x32260) /* KCR hwdrm session in play 0-31 */ +/* PXP global terminate register for session termination */ +#define PXP_GLOBAL_TERMINATE _MMIO(0x320f8) + /* Arbitrary session */ #define ARB_SESSION_INDEX 0xf @@ -120,3 +124,85 @@ int intel_pxp_arb_create_session(struct intel_pxp *pxp) return ret; } + +static int intel_pxp_arb_session_terminate(struct intel_pxp *pxp) +{ + u32 *cmd = NULL; + u32 *cmd_ptr = NULL; + int cmd_size_in_dw = 0; + int ret; + struct intel_gt *gt = container_of(pxp, typeof(*gt), pxp); + + /* Calculate how many bytes need to be alloc */ + cmd_size_in_dw += intel_pxp_cmd_add_prolog(pxp, NULL, ARB_SESSION_INDEX); + cmd_size_in_dw += intel_pxp_cmd_add_inline_termination(NULL); + cmd_size_in_dw += intel_pxp_cmd_add_epilog(NULL); + + cmd = kzalloc(cmd_size_in_dw * 4, GFP_KERNEL); + if (!cmd) + return -ENOMEM; + + /* Program the command */ + cmd_ptr = cmd; + cmd_ptr += intel_pxp_cmd_add_prolog(pxp, cmd_ptr, ARB_SESSION_INDEX); + cmd_ptr += intel_pxp_cmd_add_inline_termination(cmd_ptr); + cmd_ptr += intel_pxp_cmd_add_epilog(cmd_ptr); + + if (cmd_size_in_dw != (cmd_ptr - cmd)) { + ret = -EINVAL; + drm_err(>->i915->drm, "Failed to %s\n", __func__); + goto end; + } + + if (drm_debug_enabled(DRM_UT_DRIVER)) { + print_hex_dump(KERN_DEBUG, "global termination cmd binaries:", + DUMP_PREFIX_OFFSET, 4, 4, cmd, cmd_size_in_dw * 4, true); + } + + ret = intel_pxp_cmd_submit(pxp, cmd, cmd_size_in_dw); + if (ret) { + drm_err(>->i915->drm, "Failed to intel_pxp_cmd_submit()\n"); + goto end; + } + +end: + kfree(cmd); + return ret; +} + +/** + * intel_pxp_arb_terminate_session_with_global_terminate - Terminate the arb hw session. + * @pxp: pointer to pxp struct. + * + * This function is NOT intended to be called from the ioctl, and need to be protected by + * ctx.mutex to ensure no SIP change during the call. + * + * Return: status. 0 means terminate is successful. + */ +int intel_pxp_arb_terminate_session_with_global_terminate(struct intel_pxp *pxp) +{ + int ret; + struct intel_gt *gt = container_of(pxp, struct intel_gt, pxp); + + lockdep_assert_held(&pxp->ctx.mutex); + + /* terminate the hw sessions */ + ret = intel_pxp_arb_session_terminate(pxp); + if (ret) { + drm_err(>->i915->drm, "Failed to intel_pxp_arb_session_terminate\n"); + return ret; + } + + pxp->ctx.arb_is_in_play = false; + + ret = wait_arb_hw_sw_state(pxp); + if (ret) { + drm_err(>->i915->drm, "Failed to wait_arb_hw_sw_state\n"); + return ret; + } + + intel_uncore_write(gt->uncore, PXP_GLOBAL_TERMINATE, 1); + + return ret; +} + diff --git a/drivers/gpu/drm/i915/pxp/intel_pxp_arb.h b/drivers/gpu/drm/i915/pxp/intel_pxp_arb.h index 2196153dd879..6b0622e8ba93 100644 --- a/drivers/gpu/drm/i915/pxp/intel_pxp_arb.h +++ b/drivers/gpu/drm/i915/pxp/intel_pxp_arb.h @@ -11,6 +11,7 @@ struct intel_pxp; int intel_pxp_arb_create_session(struct intel_pxp *pxp); +int intel_pxp_arb_terminate_session_with_global_terminate(struct intel_pxp *pxp); bool intel_pxp_arb_session_is_in_play(struct intel_pxp *pxp); #endif /* __INTEL_PXP_ARB_H__ */ diff --git a/drivers/gpu/drm/i915/pxp/intel_pxp_cmd.c b/drivers/gpu/drm/i915/pxp/intel_pxp_cmd.c index 6898b8826302..6a0fe50c1aeb 100644 --- a/drivers/gpu/drm/i915/pxp/intel_pxp_cmd.c +++ b/drivers/gpu/drm/i915/pxp/intel_pxp_cmd.c @@ -5,13 +5,29 @@ #include "intel_pxp_cmd.h" #include "i915_drv.h" +#include "gt/intel_gpu_commands.h" #include "gt/intel_context.h" #include "gt/intel_engine_pm.h" -struct i915_vma *intel_pxp_cmd_get_batch(struct intel_pxp *pxp, - struct intel_context *ce, - struct intel_gt_buffer_pool_node *pool, - u32 *cmd_buf, int cmd_size_in_dw) +/* PXP GPU command definitions */ + +/* MI_SET_APPID */ +#define MI_SET_APPID_SESSION_ID(x) ((x) << 0) + +/* MI_FLUSH_DW */ +#define MI_FLUSH_DW_DW0_PROTECTED_MEMORY_ENABLE BIT(22) + +/* MI_WAIT */ +#define MFX_WAIT_DW0_PXP_SYNC_CONTROL_FLAG BIT(9) +#define MFX_WAIT_DW0_MFX_SYNC_CONTROL_FLAG BIT(8) + +/* CRYPTO_KEY_EXCHANGE */ +#define CRYPTO_KEY_EXCHANGE ((0x3 << 29) | (0x01609 << 16)) + +static struct i915_vma *intel_pxp_cmd_get_batch(struct intel_pxp *pxp, + struct intel_context *ce, + struct intel_gt_buffer_pool_node *pool, + u32 *cmd_buf, int cmd_size_in_dw) { struct i915_vma *batch = ERR_PTR(-EINVAL); struct intel_gt *gt = container_of(pxp, struct intel_gt, pxp); @@ -46,7 +62,8 @@ struct i915_vma *intel_pxp_cmd_get_batch(struct intel_pxp *pxp, return batch; } -int intel_pxp_cmd_submit(struct intel_pxp *pxp, u32 *cmd, int cmd_size_in_dw) +int intel_pxp_cmd_submit(struct intel_pxp *pxp, u32 *cmd, + int cmd_size_in_dw) { int err = -EINVAL; struct i915_vma *batch; @@ -122,3 +139,85 @@ int intel_pxp_cmd_submit(struct intel_pxp *pxp, u32 *cmd, int cmd_size_in_dw) return err; } + +int intel_pxp_cmd_add_prolog(struct intel_pxp *pxp, u32 *cmd, + int session_index) +{ + u32 increased_size_in_dw = 0; + u32 *cmd_prolog = cmd; + const int cmd_prolog_size_in_dw = 10; + + if (!cmd) + return cmd_prolog_size_in_dw; + + /* MFX_WAIT - stall until prior PXP and MFX/HCP/HUC objects are cmopleted */ + *cmd_prolog++ = (MFX_WAIT | MFX_WAIT_DW0_PXP_SYNC_CONTROL_FLAG | + MFX_WAIT_DW0_MFX_SYNC_CONTROL_FLAG); + + /* MI_FLUSH_DW - pxp off */ + *cmd_prolog++ = MI_FLUSH_DW; /* DW0 */ + *cmd_prolog++ = 0; /* DW1 */ + *cmd_prolog++ = 0; /* DW2 */ + + /* MI_SET_APPID */ + *cmd_prolog++ = (MI_SET_APPID | MI_SET_APPID_SESSION_ID(session_index)); + + /* MFX_WAIT */ + *cmd_prolog++ = (MFX_WAIT | MFX_WAIT_DW0_PXP_SYNC_CONTROL_FLAG | + MFX_WAIT_DW0_MFX_SYNC_CONTROL_FLAG); + + /* MI_FLUSH_DW - pxp on */ + *cmd_prolog++ = (MI_FLUSH_DW | MI_FLUSH_DW_DW0_PROTECTED_MEMORY_ENABLE); /* DW0 */ + *cmd_prolog++ = 0; /* DW1 */ + *cmd_prolog++ = 0; /* DW2 */ + + /* MFX_WAIT */ + *cmd_prolog++ = (MFX_WAIT | MFX_WAIT_DW0_PXP_SYNC_CONTROL_FLAG | + MFX_WAIT_DW0_MFX_SYNC_CONTROL_FLAG); + + increased_size_in_dw = (cmd_prolog - cmd); + + return increased_size_in_dw; +} + +int intel_pxp_cmd_add_epilog(u32 *cmd) +{ + u32 increased_size_in_dw = 0; + u32 *cmd_epilog = cmd; + const int cmd_epilog_size_in_dw = 5; + + if (!cmd) + return cmd_epilog_size_in_dw; + + /* MI_FLUSH_DW - pxp off */ + *cmd_epilog++ = MI_FLUSH_DW; /* DW0 */ + *cmd_epilog++ = 0; /* DW1 */ + *cmd_epilog++ = 0; /* DW2 */ + + /* MFX_WAIT - stall until prior PXP and MFX/HCP/HUC objects are cmopleted */ + *cmd_epilog++ = (MFX_WAIT | MFX_WAIT_DW0_PXP_SYNC_CONTROL_FLAG | + MFX_WAIT_DW0_MFX_SYNC_CONTROL_FLAG); + + /* MI_BATCH_BUFFER_END */ + *cmd_epilog++ = MI_BATCH_BUFFER_END; + + increased_size_in_dw = (cmd_epilog - cmd); + return increased_size_in_dw; +} + +int intel_pxp_cmd_add_inline_termination(u32 *cmd) +{ + u32 increased_size_in_dw = 0; + u32 *cmd_termin = cmd; + const int cmd_termin_size_in_dw = 2; + + if (!cmd) + return cmd_termin_size_in_dw; + + /* CRYPTO_KEY_EXCHANGE - session inline termination */ + *cmd_termin++ = CRYPTO_KEY_EXCHANGE; /* DW0 */ + *cmd_termin++ = 0; /* DW1 */ + + increased_size_in_dw = (cmd_termin - cmd); + return increased_size_in_dw; +} diff --git a/drivers/gpu/drm/i915/pxp/intel_pxp_cmd.h b/drivers/gpu/drm/i915/pxp/intel_pxp_cmd.h index d04463962421..efd26e4987a4 100644 --- a/drivers/gpu/drm/i915/pxp/intel_pxp_cmd.h +++ b/drivers/gpu/drm/i915/pxp/intel_pxp_cmd.h @@ -9,10 +9,11 @@ #include "gt/intel_gt_buffer_pool.h" #include "intel_pxp.h" -struct i915_vma *intel_pxp_cmd_get_batch(struct intel_pxp *pxp, - struct intel_context *ce, - struct intel_gt_buffer_pool_node *pool, - u32 *cmd_buf, int cmd_size_in_dw); +int intel_pxp_cmd_submit(struct intel_pxp *pxp, u32 *cmd, + int cmd_size_in_dw); +int intel_pxp_cmd_add_prolog(struct intel_pxp *pxp, u32 *cmd, + int session_index); +int intel_pxp_cmd_add_epilog(u32 *cmd); +int intel_pxp_cmd_add_inline_termination(u32 *cmd); -int intel_pxp_cmd_submit(struct intel_pxp *pxp, u32 *cmd, int cmd_size_in_dw); #endif /* __INTEL_PXP_SM_H__ */ -- 2.17.1 _______________________________________________ Intel-gfx mailing list Intel-gfx@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/intel-gfx