xref: /openbsd-src/sys/dev/pci/drm/i915/pxp/intel_pxp_cmd.c (revision f005ef32267c16bdb134f0e9fa4477dbe07c263a)
11bb76ff1Sjsg // SPDX-License-Identifier: MIT
21bb76ff1Sjsg /*
31bb76ff1Sjsg  * Copyright(c) 2020, Intel Corporation. All rights reserved.
41bb76ff1Sjsg  */
51bb76ff1Sjsg 
61bb76ff1Sjsg #include "gt/intel_context.h"
71bb76ff1Sjsg #include "gt/intel_engine_pm.h"
81bb76ff1Sjsg #include "gt/intel_gpu_commands.h"
91bb76ff1Sjsg #include "gt/intel_ring.h"
101bb76ff1Sjsg 
111bb76ff1Sjsg #include "i915_trace.h"
121bb76ff1Sjsg 
13*f005ef32Sjsg #include "intel_pxp.h"
14*f005ef32Sjsg #include "intel_pxp_cmd.h"
15*f005ef32Sjsg #include "intel_pxp_session.h"
16*f005ef32Sjsg #include "intel_pxp_types.h"
17*f005ef32Sjsg 
181bb76ff1Sjsg /* stall until prior PXP and MFX/HCP/HUC objects are cmopleted */
191bb76ff1Sjsg #define MFX_WAIT_PXP (MFX_WAIT | \
201bb76ff1Sjsg 		      MFX_WAIT_DW0_PXP_SYNC_CONTROL_FLAG | \
211bb76ff1Sjsg 		      MFX_WAIT_DW0_MFX_SYNC_CONTROL_FLAG)
221bb76ff1Sjsg 
pxp_emit_session_selection(u32 * cs,u32 idx)231bb76ff1Sjsg static u32 *pxp_emit_session_selection(u32 *cs, u32 idx)
241bb76ff1Sjsg {
251bb76ff1Sjsg 	*cs++ = MFX_WAIT_PXP;
261bb76ff1Sjsg 
271bb76ff1Sjsg 	/* pxp off */
281bb76ff1Sjsg 	*cs++ = MI_FLUSH_DW;
291bb76ff1Sjsg 	*cs++ = 0;
301bb76ff1Sjsg 	*cs++ = 0;
311bb76ff1Sjsg 
321bb76ff1Sjsg 	/* select session */
331bb76ff1Sjsg 	*cs++ = MI_SET_APPID | MI_SET_APPID_SESSION_ID(idx);
341bb76ff1Sjsg 
351bb76ff1Sjsg 	*cs++ = MFX_WAIT_PXP;
361bb76ff1Sjsg 
371bb76ff1Sjsg 	/* pxp on */
381bb76ff1Sjsg 	*cs++ = MI_FLUSH_DW | MI_FLUSH_DW_PROTECTED_MEM_EN |
391bb76ff1Sjsg 		MI_FLUSH_DW_OP_STOREDW | MI_FLUSH_DW_STORE_INDEX;
401bb76ff1Sjsg 	*cs++ = I915_GEM_HWS_PXP_ADDR | MI_FLUSH_DW_USE_GTT;
411bb76ff1Sjsg 	*cs++ = 0;
421bb76ff1Sjsg 
431bb76ff1Sjsg 	*cs++ = MFX_WAIT_PXP;
441bb76ff1Sjsg 
451bb76ff1Sjsg 	return cs;
461bb76ff1Sjsg }
471bb76ff1Sjsg 
pxp_emit_inline_termination(u32 * cs)481bb76ff1Sjsg static u32 *pxp_emit_inline_termination(u32 *cs)
491bb76ff1Sjsg {
501bb76ff1Sjsg 	/* session inline termination */
511bb76ff1Sjsg 	*cs++ = CRYPTO_KEY_EXCHANGE;
521bb76ff1Sjsg 	*cs++ = 0;
531bb76ff1Sjsg 
541bb76ff1Sjsg 	return cs;
551bb76ff1Sjsg }
561bb76ff1Sjsg 
pxp_emit_session_termination(u32 * cs,u32 idx)571bb76ff1Sjsg static u32 *pxp_emit_session_termination(u32 *cs, u32 idx)
581bb76ff1Sjsg {
591bb76ff1Sjsg 	cs = pxp_emit_session_selection(cs, idx);
601bb76ff1Sjsg 	cs = pxp_emit_inline_termination(cs);
611bb76ff1Sjsg 
621bb76ff1Sjsg 	return cs;
631bb76ff1Sjsg }
641bb76ff1Sjsg 
pxp_emit_wait(u32 * cs)651bb76ff1Sjsg static u32 *pxp_emit_wait(u32 *cs)
661bb76ff1Sjsg {
671bb76ff1Sjsg 	/* wait for cmds to go through */
681bb76ff1Sjsg 	*cs++ = MFX_WAIT_PXP;
691bb76ff1Sjsg 	*cs++ = 0;
701bb76ff1Sjsg 
711bb76ff1Sjsg 	return cs;
721bb76ff1Sjsg }
731bb76ff1Sjsg 
741bb76ff1Sjsg /*
751bb76ff1Sjsg  * if we ever need to terminate more than one session, we can submit multiple
761bb76ff1Sjsg  * selections and terminations back-to-back with a single wait at the end
771bb76ff1Sjsg  */
781bb76ff1Sjsg #define SELECTION_LEN 10
791bb76ff1Sjsg #define TERMINATION_LEN 2
801bb76ff1Sjsg #define SESSION_TERMINATION_LEN(x) ((SELECTION_LEN + TERMINATION_LEN) * (x))
811bb76ff1Sjsg #define WAIT_LEN 2
821bb76ff1Sjsg 
pxp_request_commit(struct i915_request * rq)831bb76ff1Sjsg static void pxp_request_commit(struct i915_request *rq)
841bb76ff1Sjsg {
851bb76ff1Sjsg 	struct i915_sched_attr attr = { .priority = I915_PRIORITY_MAX };
861bb76ff1Sjsg 	struct intel_timeline * const tl = i915_request_timeline(rq);
871bb76ff1Sjsg 
881bb76ff1Sjsg 	lockdep_unpin_lock(&tl->mutex, rq->cookie);
891bb76ff1Sjsg 
901bb76ff1Sjsg 	trace_i915_request_add(rq);
911bb76ff1Sjsg 	__i915_request_commit(rq);
921bb76ff1Sjsg 	__i915_request_queue(rq, &attr);
931bb76ff1Sjsg 
941bb76ff1Sjsg 	mutex_unlock(&tl->mutex);
951bb76ff1Sjsg }
961bb76ff1Sjsg 
intel_pxp_terminate_session(struct intel_pxp * pxp,u32 id)971bb76ff1Sjsg int intel_pxp_terminate_session(struct intel_pxp *pxp, u32 id)
981bb76ff1Sjsg {
991bb76ff1Sjsg 	struct i915_request *rq;
1001bb76ff1Sjsg 	struct intel_context *ce = pxp->ce;
1011bb76ff1Sjsg 	u32 *cs;
1021bb76ff1Sjsg 	int err = 0;
1031bb76ff1Sjsg 
1041bb76ff1Sjsg 	if (!intel_pxp_is_enabled(pxp))
1051bb76ff1Sjsg 		return 0;
1061bb76ff1Sjsg 
1071bb76ff1Sjsg 	rq = i915_request_create(ce);
1081bb76ff1Sjsg 	if (IS_ERR(rq))
1091bb76ff1Sjsg 		return PTR_ERR(rq);
1101bb76ff1Sjsg 
1111bb76ff1Sjsg 	if (ce->engine->emit_init_breadcrumb) {
1121bb76ff1Sjsg 		err = ce->engine->emit_init_breadcrumb(rq);
1131bb76ff1Sjsg 		if (err)
1141bb76ff1Sjsg 			goto out_rq;
1151bb76ff1Sjsg 	}
1161bb76ff1Sjsg 
1171bb76ff1Sjsg 	cs = intel_ring_begin(rq, SESSION_TERMINATION_LEN(1) + WAIT_LEN);
1181bb76ff1Sjsg 	if (IS_ERR(cs)) {
1191bb76ff1Sjsg 		err = PTR_ERR(cs);
1201bb76ff1Sjsg 		goto out_rq;
1211bb76ff1Sjsg 	}
1221bb76ff1Sjsg 
1231bb76ff1Sjsg 	cs = pxp_emit_session_termination(cs, id);
1241bb76ff1Sjsg 	cs = pxp_emit_wait(cs);
1251bb76ff1Sjsg 
1261bb76ff1Sjsg 	intel_ring_advance(rq, cs);
1271bb76ff1Sjsg 
1281bb76ff1Sjsg out_rq:
1291bb76ff1Sjsg 	i915_request_get(rq);
1301bb76ff1Sjsg 
1311bb76ff1Sjsg 	if (unlikely(err))
1321bb76ff1Sjsg 		i915_request_set_error_once(rq, err);
1331bb76ff1Sjsg 
1341bb76ff1Sjsg 	pxp_request_commit(rq);
1351bb76ff1Sjsg 
1361bb76ff1Sjsg 	if (!err && i915_request_wait(rq, 0, HZ / 5) < 0)
1371bb76ff1Sjsg 		err = -ETIME;
1381bb76ff1Sjsg 
1391bb76ff1Sjsg 	i915_request_put(rq);
1401bb76ff1Sjsg 
1411bb76ff1Sjsg 	return err;
1421bb76ff1Sjsg }
1431bb76ff1Sjsg 
144