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_huc.c (5367B)


      1// SPDX-License-Identifier: MIT
      2/*
      3 * Copyright © 2016-2019 Intel Corporation
      4 */
      5
      6#include <linux/types.h>
      7
      8#include "gt/intel_gt.h"
      9#include "intel_huc.h"
     10#include "i915_drv.h"
     11
     12/**
     13 * DOC: HuC
     14 *
     15 * The HuC is a dedicated microcontroller for usage in media HEVC (High
     16 * Efficiency Video Coding) operations. Userspace can directly use the firmware
     17 * capabilities by adding HuC specific commands to batch buffers.
     18 *
     19 * The kernel driver is only responsible for loading the HuC firmware and
     20 * triggering its security authentication, which is performed by the GuC. For
     21 * The GuC to correctly perform the authentication, the HuC binary must be
     22 * loaded before the GuC one. Loading the HuC is optional; however, not using
     23 * the HuC might negatively impact power usage and/or performance of media
     24 * workloads, depending on the use-cases.
     25 *
     26 * See https://github.com/intel/media-driver for the latest details on HuC
     27 * functionality.
     28 */
     29
     30/**
     31 * DOC: HuC Memory Management
     32 *
     33 * Similarly to the GuC, the HuC can't do any memory allocations on its own,
     34 * with the difference being that the allocations for HuC usage are handled by
     35 * the userspace driver instead of the kernel one. The HuC accesses the memory
     36 * via the PPGTT belonging to the context loaded on the VCS executing the
     37 * HuC-specific commands.
     38 */
     39
     40void intel_huc_init_early(struct intel_huc *huc)
     41{
     42	struct drm_i915_private *i915 = huc_to_gt(huc)->i915;
     43
     44	intel_uc_fw_init_early(&huc->fw, INTEL_UC_FW_TYPE_HUC);
     45
     46	if (GRAPHICS_VER(i915) >= 11) {
     47		huc->status.reg = GEN11_HUC_KERNEL_LOAD_INFO;
     48		huc->status.mask = HUC_LOAD_SUCCESSFUL;
     49		huc->status.value = HUC_LOAD_SUCCESSFUL;
     50	} else {
     51		huc->status.reg = HUC_STATUS2;
     52		huc->status.mask = HUC_FW_VERIFIED;
     53		huc->status.value = HUC_FW_VERIFIED;
     54	}
     55}
     56
     57int intel_huc_init(struct intel_huc *huc)
     58{
     59	struct drm_i915_private *i915 = huc_to_gt(huc)->i915;
     60	int err;
     61
     62	err = intel_uc_fw_init(&huc->fw);
     63	if (err)
     64		goto out;
     65
     66	intel_uc_fw_change_status(&huc->fw, INTEL_UC_FIRMWARE_LOADABLE);
     67
     68	return 0;
     69
     70out:
     71	i915_probe_error(i915, "failed with %d\n", err);
     72	return err;
     73}
     74
     75void intel_huc_fini(struct intel_huc *huc)
     76{
     77	if (!intel_uc_fw_is_loadable(&huc->fw))
     78		return;
     79
     80	intel_uc_fw_fini(&huc->fw);
     81}
     82
     83/**
     84 * intel_huc_auth() - Authenticate HuC uCode
     85 * @huc: intel_huc structure
     86 *
     87 * Called after HuC and GuC firmware loading during intel_uc_init_hw().
     88 *
     89 * This function invokes the GuC action to authenticate the HuC firmware,
     90 * passing the offset of the RSA signature to intel_guc_auth_huc(). It then
     91 * waits for up to 50ms for firmware verification ACK.
     92 */
     93int intel_huc_auth(struct intel_huc *huc)
     94{
     95	struct intel_gt *gt = huc_to_gt(huc);
     96	struct intel_guc *guc = &gt->uc.guc;
     97	int ret;
     98
     99	GEM_BUG_ON(intel_huc_is_authenticated(huc));
    100
    101	if (!intel_uc_fw_is_loaded(&huc->fw))
    102		return -ENOEXEC;
    103
    104	ret = i915_inject_probe_error(gt->i915, -ENXIO);
    105	if (ret)
    106		goto fail;
    107
    108	ret = intel_guc_auth_huc(guc,
    109				 intel_guc_ggtt_offset(guc, huc->fw.rsa_data));
    110	if (ret) {
    111		DRM_ERROR("HuC: GuC did not ack Auth request %d\n", ret);
    112		goto fail;
    113	}
    114
    115	/* Check authentication status, it should be done by now */
    116	ret = __intel_wait_for_register(gt->uncore,
    117					huc->status.reg,
    118					huc->status.mask,
    119					huc->status.value,
    120					2, 50, NULL);
    121	if (ret) {
    122		DRM_ERROR("HuC: Firmware not verified %d\n", ret);
    123		goto fail;
    124	}
    125
    126	intel_uc_fw_change_status(&huc->fw, INTEL_UC_FIRMWARE_RUNNING);
    127	drm_info(&gt->i915->drm, "HuC authenticated\n");
    128	return 0;
    129
    130fail:
    131	i915_probe_error(gt->i915, "HuC: Authentication failed %d\n", ret);
    132	intel_uc_fw_change_status(&huc->fw, INTEL_UC_FIRMWARE_LOAD_FAIL);
    133	return ret;
    134}
    135
    136/**
    137 * intel_huc_check_status() - check HuC status
    138 * @huc: intel_huc structure
    139 *
    140 * This function reads status register to verify if HuC
    141 * firmware was successfully loaded.
    142 *
    143 * Returns:
    144 *  * -ENODEV if HuC is not present on this platform,
    145 *  * -EOPNOTSUPP if HuC firmware is disabled,
    146 *  * -ENOPKG if HuC firmware was not installed,
    147 *  * -ENOEXEC if HuC firmware is invalid or mismatched,
    148 *  * 0 if HuC firmware is not running,
    149 *  * 1 if HuC firmware is authenticated and running.
    150 */
    151int intel_huc_check_status(struct intel_huc *huc)
    152{
    153	struct intel_gt *gt = huc_to_gt(huc);
    154	intel_wakeref_t wakeref;
    155	u32 status = 0;
    156
    157	switch (__intel_uc_fw_status(&huc->fw)) {
    158	case INTEL_UC_FIRMWARE_NOT_SUPPORTED:
    159		return -ENODEV;
    160	case INTEL_UC_FIRMWARE_DISABLED:
    161		return -EOPNOTSUPP;
    162	case INTEL_UC_FIRMWARE_MISSING:
    163		return -ENOPKG;
    164	case INTEL_UC_FIRMWARE_ERROR:
    165		return -ENOEXEC;
    166	default:
    167		break;
    168	}
    169
    170	with_intel_runtime_pm(gt->uncore->rpm, wakeref)
    171		status = intel_uncore_read(gt->uncore, huc->status.reg);
    172
    173	return (status & huc->status.mask) == huc->status.value;
    174}
    175
    176/**
    177 * intel_huc_load_status - dump information about HuC load status
    178 * @huc: the HuC
    179 * @p: the &drm_printer
    180 *
    181 * Pretty printer for HuC load status.
    182 */
    183void intel_huc_load_status(struct intel_huc *huc, struct drm_printer *p)
    184{
    185	struct intel_gt *gt = huc_to_gt(huc);
    186	intel_wakeref_t wakeref;
    187
    188	if (!intel_huc_is_supported(huc)) {
    189		drm_printf(p, "HuC not supported\n");
    190		return;
    191	}
    192
    193	if (!intel_huc_is_wanted(huc)) {
    194		drm_printf(p, "HuC disabled\n");
    195		return;
    196	}
    197
    198	intel_uc_fw_dump(&huc->fw, p);
    199
    200	with_intel_runtime_pm(gt->uncore->rpm, wakeref)
    201		drm_printf(p, "HuC status: 0x%08x\n",
    202			   intel_uncore_read(gt->uncore, huc->status.reg));
    203}