cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

intel_pxp_session.c (4243B)


      1// SPDX-License-Identifier: MIT
      2/*
      3 * Copyright(c) 2020, Intel Corporation. All rights reserved.
      4 */
      5
      6#include "i915_drv.h"
      7
      8#include "intel_pxp.h"
      9#include "intel_pxp_cmd.h"
     10#include "intel_pxp_session.h"
     11#include "intel_pxp_tee.h"
     12#include "intel_pxp_types.h"
     13
     14#define ARB_SESSION I915_PROTECTED_CONTENT_DEFAULT_SESSION /* shorter define */
     15
     16#define GEN12_KCR_SIP _MMIO(0x32260) /* KCR hwdrm session in play 0-31 */
     17
     18/* PXP global terminate register for session termination */
     19#define PXP_GLOBAL_TERMINATE _MMIO(0x320f8)
     20
     21static bool intel_pxp_session_is_in_play(struct intel_pxp *pxp, u32 id)
     22{
     23	struct intel_uncore *uncore = pxp_to_gt(pxp)->uncore;
     24	intel_wakeref_t wakeref;
     25	u32 sip = 0;
     26
     27	/* if we're suspended the session is considered off */
     28	with_intel_runtime_pm_if_in_use(uncore->rpm, wakeref)
     29		sip = intel_uncore_read(uncore, GEN12_KCR_SIP);
     30
     31	return sip & BIT(id);
     32}
     33
     34static int pxp_wait_for_session_state(struct intel_pxp *pxp, u32 id, bool in_play)
     35{
     36	struct intel_uncore *uncore = pxp_to_gt(pxp)->uncore;
     37	intel_wakeref_t wakeref;
     38	u32 mask = BIT(id);
     39	int ret;
     40
     41	/* if we're suspended the session is considered off */
     42	wakeref = intel_runtime_pm_get_if_in_use(uncore->rpm);
     43	if (!wakeref)
     44		return in_play ? -ENODEV : 0;
     45
     46	ret = intel_wait_for_register(uncore,
     47				      GEN12_KCR_SIP,
     48				      mask,
     49				      in_play ? mask : 0,
     50				      100);
     51
     52	intel_runtime_pm_put(uncore->rpm, wakeref);
     53
     54	return ret;
     55}
     56
     57static int pxp_create_arb_session(struct intel_pxp *pxp)
     58{
     59	struct intel_gt *gt = pxp_to_gt(pxp);
     60	int ret;
     61
     62	pxp->arb_is_valid = false;
     63
     64	if (intel_pxp_session_is_in_play(pxp, ARB_SESSION)) {
     65		drm_err(&gt->i915->drm, "arb session already in play at creation time\n");
     66		return -EEXIST;
     67	}
     68
     69	ret = intel_pxp_tee_cmd_create_arb_session(pxp, ARB_SESSION);
     70	if (ret) {
     71		drm_err(&gt->i915->drm, "tee cmd for arb session creation failed\n");
     72		return ret;
     73	}
     74
     75	ret = pxp_wait_for_session_state(pxp, ARB_SESSION, true);
     76	if (ret) {
     77		drm_err(&gt->i915->drm, "arb session failed to go in play\n");
     78		return ret;
     79	}
     80
     81	if (!++pxp->key_instance)
     82		++pxp->key_instance;
     83
     84	pxp->arb_is_valid = true;
     85
     86	return 0;
     87}
     88
     89static int pxp_terminate_arb_session_and_global(struct intel_pxp *pxp)
     90{
     91	int ret;
     92	struct intel_gt *gt = pxp_to_gt(pxp);
     93
     94	/* must mark termination in progress calling this function */
     95	GEM_WARN_ON(pxp->arb_is_valid);
     96
     97	/* terminate the hw sessions */
     98	ret = intel_pxp_terminate_session(pxp, ARB_SESSION);
     99	if (ret) {
    100		drm_err(&gt->i915->drm, "Failed to submit session termination\n");
    101		return ret;
    102	}
    103
    104	ret = pxp_wait_for_session_state(pxp, ARB_SESSION, false);
    105	if (ret) {
    106		drm_err(&gt->i915->drm, "Session state did not clear\n");
    107		return ret;
    108	}
    109
    110	intel_uncore_write(gt->uncore, PXP_GLOBAL_TERMINATE, 1);
    111
    112	return ret;
    113}
    114
    115static void pxp_terminate(struct intel_pxp *pxp)
    116{
    117	int ret;
    118
    119	pxp->hw_state_invalidated = true;
    120
    121	/*
    122	 * if we fail to submit the termination there is no point in waiting for
    123	 * it to complete. PXP will be marked as non-active until the next
    124	 * termination is issued.
    125	 */
    126	ret = pxp_terminate_arb_session_and_global(pxp);
    127	if (ret)
    128		complete_all(&pxp->termination);
    129}
    130
    131static void pxp_terminate_complete(struct intel_pxp *pxp)
    132{
    133	/* Re-create the arb session after teardown handle complete */
    134	if (fetch_and_zero(&pxp->hw_state_invalidated))
    135		pxp_create_arb_session(pxp);
    136
    137	complete_all(&pxp->termination);
    138}
    139
    140void intel_pxp_session_work(struct work_struct *work)
    141{
    142	struct intel_pxp *pxp = container_of(work, typeof(*pxp), session_work);
    143	struct intel_gt *gt = pxp_to_gt(pxp);
    144	intel_wakeref_t wakeref;
    145	u32 events = 0;
    146
    147	spin_lock_irq(&gt->irq_lock);
    148	events = fetch_and_zero(&pxp->session_events);
    149	spin_unlock_irq(&gt->irq_lock);
    150
    151	if (!events)
    152		return;
    153
    154	if (events & PXP_INVAL_REQUIRED)
    155		intel_pxp_invalidate(pxp);
    156
    157	/*
    158	 * If we're processing an event while suspending then don't bother,
    159	 * we're going to re-init everything on resume anyway.
    160	 */
    161	wakeref = intel_runtime_pm_get_if_in_use(gt->uncore->rpm);
    162	if (!wakeref)
    163		return;
    164
    165	if (events & PXP_TERMINATION_REQUEST) {
    166		events &= ~PXP_TERMINATION_COMPLETE;
    167		pxp_terminate(pxp);
    168	}
    169
    170	if (events & PXP_TERMINATION_COMPLETE)
    171		pxp_terminate_complete(pxp);
    172
    173	intel_runtime_pm_put(gt->uncore->rpm, wakeref);
    174}