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_guc_hwconfig.c (3424B)


      1// SPDX-License-Identifier: MIT
      2/*
      3 * Copyright © 2022 Intel Corporation
      4 */
      5
      6#include "gt/intel_gt.h"
      7#include "gt/intel_hwconfig.h"
      8#include "i915_drv.h"
      9#include "i915_memcpy.h"
     10
     11/*
     12 * GuC has a blob containing hardware configuration information (HWConfig).
     13 * This is formatted as a simple and flexible KLV (Key/Length/Value) table.
     14 *
     15 * For example, a minimal version could be:
     16 *   enum device_attr {
     17 *     ATTR_SOME_VALUE = 0,
     18 *     ATTR_SOME_MASK  = 1,
     19 *   };
     20 *
     21 *   static const u32 hwconfig[] = {
     22 *     ATTR_SOME_VALUE,
     23 *     1,		// Value Length in DWords
     24 *     8,		// Value
     25 *
     26 *     ATTR_SOME_MASK,
     27 *     3,
     28 *     0x00FFFFFFFF, 0xFFFFFFFF, 0xFF000000,
     29 *   };
     30 *
     31 * The attribute ids are defined in a hardware spec.
     32 */
     33
     34static int __guc_action_get_hwconfig(struct intel_guc *guc,
     35				     u32 ggtt_offset, u32 ggtt_size)
     36{
     37	u32 action[] = {
     38		INTEL_GUC_ACTION_GET_HWCONFIG,
     39		lower_32_bits(ggtt_offset),
     40		upper_32_bits(ggtt_offset),
     41		ggtt_size,
     42	};
     43	int ret;
     44
     45	ret = intel_guc_send_mmio(guc, action, ARRAY_SIZE(action), NULL, 0);
     46	if (ret == -ENXIO)
     47		return -ENOENT;
     48
     49	return ret;
     50}
     51
     52static int guc_hwconfig_discover_size(struct intel_guc *guc, struct intel_hwconfig *hwconfig)
     53{
     54	int ret;
     55
     56	/*
     57	 * Sending a query with zero offset and size will return the
     58	 * size of the blob.
     59	 */
     60	ret = __guc_action_get_hwconfig(guc, 0, 0);
     61	if (ret < 0)
     62		return ret;
     63
     64	if (ret == 0)
     65		return -EINVAL;
     66
     67	hwconfig->size = ret;
     68	return 0;
     69}
     70
     71static int guc_hwconfig_fill_buffer(struct intel_guc *guc, struct intel_hwconfig *hwconfig)
     72{
     73	struct i915_vma *vma;
     74	u32 ggtt_offset;
     75	void *vaddr;
     76	int ret;
     77
     78	GEM_BUG_ON(!hwconfig->size);
     79
     80	ret = intel_guc_allocate_and_map_vma(guc, hwconfig->size, &vma, &vaddr);
     81	if (ret)
     82		return ret;
     83
     84	ggtt_offset = intel_guc_ggtt_offset(guc, vma);
     85
     86	ret = __guc_action_get_hwconfig(guc, ggtt_offset, hwconfig->size);
     87	if (ret >= 0)
     88		memcpy(hwconfig->ptr, vaddr, hwconfig->size);
     89
     90	i915_vma_unpin_and_release(&vma, I915_VMA_RELEASE_MAP);
     91
     92	return ret;
     93}
     94
     95static bool has_table(struct drm_i915_private *i915)
     96{
     97	if (IS_ALDERLAKE_P(i915))
     98		return true;
     99	if (IS_DG2(i915))
    100		return true;
    101
    102	return false;
    103}
    104
    105/**
    106 * intel_guc_hwconfig_init - Initialize the HWConfig
    107 *
    108 * Retrieve the HWConfig table from the GuC and save it locally.
    109 * It can then be queried on demand by other users later on.
    110 */
    111static int guc_hwconfig_init(struct intel_gt *gt)
    112{
    113	struct intel_hwconfig *hwconfig = &gt->info.hwconfig;
    114	struct intel_guc *guc = &gt->uc.guc;
    115	int ret;
    116
    117	if (!has_table(gt->i915))
    118		return 0;
    119
    120	ret = guc_hwconfig_discover_size(guc, hwconfig);
    121	if (ret)
    122		return ret;
    123
    124	hwconfig->ptr = kmalloc(hwconfig->size, GFP_KERNEL);
    125	if (!hwconfig->ptr) {
    126		hwconfig->size = 0;
    127		return -ENOMEM;
    128	}
    129
    130	ret = guc_hwconfig_fill_buffer(guc, hwconfig);
    131	if (ret < 0) {
    132		intel_gt_fini_hwconfig(gt);
    133		return ret;
    134	}
    135
    136	return 0;
    137}
    138
    139/**
    140 * intel_gt_init_hwconfig - Initialize the HWConfig if available
    141 *
    142 * Retrieve the HWConfig table if available on the current platform.
    143 */
    144int intel_gt_init_hwconfig(struct intel_gt *gt)
    145{
    146	if (!intel_uc_uses_guc(&gt->uc))
    147		return 0;
    148
    149	return guc_hwconfig_init(gt);
    150}
    151
    152/**
    153 * intel_gt_fini_hwconfig - Finalize the HWConfig
    154 *
    155 * Free up the memory allocation holding the table.
    156 */
    157void intel_gt_fini_hwconfig(struct intel_gt *gt)
    158{
    159	struct intel_hwconfig *hwconfig = &gt->info.hwconfig;
    160
    161	kfree(hwconfig->ptr);
    162	hwconfig->size = 0;
    163	hwconfig->ptr = NULL;
    164}