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_gsc.c (4846B)


      1// SPDX-License-Identifier: MIT
      2/*
      3 * Copyright(c) 2019-2022, Intel Corporation. All rights reserved.
      4 */
      5
      6#include <linux/irq.h>
      7#include <linux/mei_aux.h>
      8#include "i915_drv.h"
      9#include "i915_reg.h"
     10#include "gt/intel_gsc.h"
     11#include "gt/intel_gt.h"
     12
     13#define GSC_BAR_LENGTH  0x00000FFC
     14
     15static void gsc_irq_mask(struct irq_data *d)
     16{
     17	/* generic irq handling */
     18}
     19
     20static void gsc_irq_unmask(struct irq_data *d)
     21{
     22	/* generic irq handling */
     23}
     24
     25static struct irq_chip gsc_irq_chip = {
     26	.name = "gsc_irq_chip",
     27	.irq_mask = gsc_irq_mask,
     28	.irq_unmask = gsc_irq_unmask,
     29};
     30
     31static int gsc_irq_init(int irq)
     32{
     33	irq_set_chip_and_handler_name(irq, &gsc_irq_chip,
     34				      handle_simple_irq, "gsc_irq_handler");
     35
     36	return irq_set_chip_data(irq, NULL);
     37}
     38
     39struct gsc_def {
     40	const char *name;
     41	unsigned long bar;
     42	size_t bar_size;
     43};
     44
     45/* gsc resources and definitions (HECI1 and HECI2) */
     46static const struct gsc_def gsc_def_dg1[] = {
     47	{
     48		/* HECI1 not yet implemented. */
     49	},
     50	{
     51		.name = "mei-gscfi",
     52		.bar = DG1_GSC_HECI2_BASE,
     53		.bar_size = GSC_BAR_LENGTH,
     54	}
     55};
     56
     57static const struct gsc_def gsc_def_dg2[] = {
     58	{
     59		.name = "mei-gsc",
     60		.bar = DG2_GSC_HECI1_BASE,
     61		.bar_size = GSC_BAR_LENGTH,
     62	},
     63	{
     64		.name = "mei-gscfi",
     65		.bar = DG2_GSC_HECI2_BASE,
     66		.bar_size = GSC_BAR_LENGTH,
     67	}
     68};
     69
     70static void gsc_release_dev(struct device *dev)
     71{
     72	struct auxiliary_device *aux_dev = to_auxiliary_dev(dev);
     73	struct mei_aux_device *adev = auxiliary_dev_to_mei_aux_dev(aux_dev);
     74
     75	kfree(adev);
     76}
     77
     78static void gsc_destroy_one(struct intel_gsc_intf *intf)
     79{
     80	if (intf->adev) {
     81		auxiliary_device_delete(&intf->adev->aux_dev);
     82		auxiliary_device_uninit(&intf->adev->aux_dev);
     83		intf->adev = NULL;
     84	}
     85	if (intf->irq >= 0)
     86		irq_free_desc(intf->irq);
     87	intf->irq = -1;
     88}
     89
     90static void gsc_init_one(struct drm_i915_private *i915,
     91			 struct intel_gsc_intf *intf,
     92			 unsigned int intf_id)
     93{
     94	struct pci_dev *pdev = to_pci_dev(i915->drm.dev);
     95	struct mei_aux_device *adev;
     96	struct auxiliary_device *aux_dev;
     97	const struct gsc_def *def;
     98	int ret;
     99
    100	intf->irq = -1;
    101	intf->id = intf_id;
    102
    103	if (intf_id == 0 && !HAS_HECI_PXP(i915))
    104		return;
    105
    106	if (IS_DG1(i915)) {
    107		def = &gsc_def_dg1[intf_id];
    108	} else if (IS_DG2(i915)) {
    109		def = &gsc_def_dg2[intf_id];
    110	} else {
    111		drm_warn_once(&i915->drm, "Unknown platform\n");
    112		return;
    113	}
    114
    115	if (!def->name) {
    116		drm_warn_once(&i915->drm, "HECI%d is not implemented!\n", intf_id + 1);
    117		return;
    118	}
    119
    120	intf->irq = irq_alloc_desc(0);
    121	if (intf->irq < 0) {
    122		drm_err(&i915->drm, "gsc irq error %d\n", intf->irq);
    123		return;
    124	}
    125
    126	ret = gsc_irq_init(intf->irq);
    127	if (ret < 0) {
    128		drm_err(&i915->drm, "gsc irq init failed %d\n", ret);
    129		goto fail;
    130	}
    131
    132	adev = kzalloc(sizeof(*adev), GFP_KERNEL);
    133	if (!adev)
    134		goto fail;
    135
    136	adev->irq = intf->irq;
    137	adev->bar.parent = &pdev->resource[0];
    138	adev->bar.start = def->bar + pdev->resource[0].start;
    139	adev->bar.end = adev->bar.start + def->bar_size - 1;
    140	adev->bar.flags = IORESOURCE_MEM;
    141	adev->bar.desc = IORES_DESC_NONE;
    142
    143	aux_dev = &adev->aux_dev;
    144	aux_dev->name = def->name;
    145	aux_dev->id = (pci_domain_nr(pdev->bus) << 16) |
    146		      PCI_DEVID(pdev->bus->number, pdev->devfn);
    147	aux_dev->dev.parent = &pdev->dev;
    148	aux_dev->dev.release = gsc_release_dev;
    149
    150	ret = auxiliary_device_init(aux_dev);
    151	if (ret < 0) {
    152		drm_err(&i915->drm, "gsc aux init failed %d\n", ret);
    153		kfree(adev);
    154		goto fail;
    155	}
    156
    157	ret = auxiliary_device_add(aux_dev);
    158	if (ret < 0) {
    159		drm_err(&i915->drm, "gsc aux add failed %d\n", ret);
    160		/* adev will be freed with the put_device() and .release sequence */
    161		auxiliary_device_uninit(aux_dev);
    162		goto fail;
    163	}
    164	intf->adev = adev;
    165
    166	return;
    167fail:
    168	gsc_destroy_one(intf);
    169}
    170
    171static void gsc_irq_handler(struct intel_gt *gt, unsigned int intf_id)
    172{
    173	int ret;
    174
    175	if (intf_id >= INTEL_GSC_NUM_INTERFACES) {
    176		drm_warn_once(&gt->i915->drm, "GSC irq: intf_id %d is out of range", intf_id);
    177		return;
    178	}
    179
    180	if (!HAS_HECI_GSC(gt->i915)) {
    181		drm_warn_once(&gt->i915->drm, "GSC irq: not supported");
    182		return;
    183	}
    184
    185	if (gt->gsc.intf[intf_id].irq < 0) {
    186		drm_err_ratelimited(&gt->i915->drm, "GSC irq: irq not set");
    187		return;
    188	}
    189
    190	ret = generic_handle_irq(gt->gsc.intf[intf_id].irq);
    191	if (ret)
    192		drm_err_ratelimited(&gt->i915->drm, "error handling GSC irq: %d\n", ret);
    193}
    194
    195void intel_gsc_irq_handler(struct intel_gt *gt, u32 iir)
    196{
    197	if (iir & GSC_IRQ_INTF(0))
    198		gsc_irq_handler(gt, 0);
    199	if (iir & GSC_IRQ_INTF(1))
    200		gsc_irq_handler(gt, 1);
    201}
    202
    203void intel_gsc_init(struct intel_gsc *gsc, struct drm_i915_private *i915)
    204{
    205	unsigned int i;
    206
    207	if (!HAS_HECI_GSC(i915))
    208		return;
    209
    210	for (i = 0; i < INTEL_GSC_NUM_INTERFACES; i++)
    211		gsc_init_one(i915, &gsc->intf[i], i);
    212}
    213
    214void intel_gsc_fini(struct intel_gsc *gsc)
    215{
    216	struct intel_gt *gt = gsc_to_gt(gsc);
    217	unsigned int i;
    218
    219	if (!HAS_HECI_GSC(gt->i915))
    220		return;
    221
    222	for (i = 0; i < INTEL_GSC_NUM_INTERFACES; i++)
    223		gsc_destroy_one(&gsc->intf[i]);
    224}