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

psp-dev.c (5314B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * AMD Platform Security Processor (PSP) interface
      4 *
      5 * Copyright (C) 2016,2019 Advanced Micro Devices, Inc.
      6 *
      7 * Author: Brijesh Singh <brijesh.singh@amd.com>
      8 */
      9
     10#include <linux/kernel.h>
     11#include <linux/irqreturn.h>
     12
     13#include "sp-dev.h"
     14#include "psp-dev.h"
     15#include "sev-dev.h"
     16#include "tee-dev.h"
     17
     18struct psp_device *psp_master;
     19
     20static struct psp_device *psp_alloc_struct(struct sp_device *sp)
     21{
     22	struct device *dev = sp->dev;
     23	struct psp_device *psp;
     24
     25	psp = devm_kzalloc(dev, sizeof(*psp), GFP_KERNEL);
     26	if (!psp)
     27		return NULL;
     28
     29	psp->dev = dev;
     30	psp->sp = sp;
     31
     32	snprintf(psp->name, sizeof(psp->name), "psp-%u", sp->ord);
     33
     34	return psp;
     35}
     36
     37static irqreturn_t psp_irq_handler(int irq, void *data)
     38{
     39	struct psp_device *psp = data;
     40	unsigned int status;
     41
     42	/* Read the interrupt status: */
     43	status = ioread32(psp->io_regs + psp->vdata->intsts_reg);
     44
     45	/* invoke subdevice interrupt handlers */
     46	if (status) {
     47		if (psp->sev_irq_handler)
     48			psp->sev_irq_handler(irq, psp->sev_irq_data, status);
     49
     50		if (psp->tee_irq_handler)
     51			psp->tee_irq_handler(irq, psp->tee_irq_data, status);
     52	}
     53
     54	/* Clear the interrupt status by writing the same value we read. */
     55	iowrite32(status, psp->io_regs + psp->vdata->intsts_reg);
     56
     57	return IRQ_HANDLED;
     58}
     59
     60static unsigned int psp_get_capability(struct psp_device *psp)
     61{
     62	unsigned int val = ioread32(psp->io_regs + psp->vdata->feature_reg);
     63
     64	/*
     65	 * Check for a access to the registers.  If this read returns
     66	 * 0xffffffff, it's likely that the system is running a broken
     67	 * BIOS which disallows access to the device. Stop here and
     68	 * fail the PSP initialization (but not the load, as the CCP
     69	 * could get properly initialized).
     70	 */
     71	if (val == 0xffffffff) {
     72		dev_notice(psp->dev, "psp: unable to access the device: you might be running a broken BIOS.\n");
     73		return -ENODEV;
     74	}
     75	psp->capability = val;
     76
     77	/* Detect if TSME and SME are both enabled */
     78	if (psp->capability & PSP_CAPABILITY_PSP_SECURITY_REPORTING &&
     79	    psp->capability & (PSP_SECURITY_TSME_STATUS << PSP_CAPABILITY_PSP_SECURITY_OFFSET) &&
     80	    cc_platform_has(CC_ATTR_HOST_MEM_ENCRYPT))
     81		dev_notice(psp->dev, "psp: Both TSME and SME are active, SME is unnecessary when TSME is active.\n");
     82
     83	return 0;
     84}
     85
     86static int psp_check_sev_support(struct psp_device *psp)
     87{
     88	/* Check if device supports SEV feature */
     89	if (!(psp->capability & PSP_CAPABILITY_SEV)) {
     90		dev_dbg(psp->dev, "psp does not support SEV\n");
     91		return -ENODEV;
     92	}
     93
     94	return 0;
     95}
     96
     97static int psp_check_tee_support(struct psp_device *psp)
     98{
     99	/* Check if device supports TEE feature */
    100	if (!(psp->capability & PSP_CAPABILITY_TEE)) {
    101		dev_dbg(psp->dev, "psp does not support TEE\n");
    102		return -ENODEV;
    103	}
    104
    105	return 0;
    106}
    107
    108static int psp_init(struct psp_device *psp)
    109{
    110	int ret;
    111
    112	if (!psp_check_sev_support(psp)) {
    113		ret = sev_dev_init(psp);
    114		if (ret)
    115			return ret;
    116	}
    117
    118	if (!psp_check_tee_support(psp)) {
    119		ret = tee_dev_init(psp);
    120		if (ret)
    121			return ret;
    122	}
    123
    124	return 0;
    125}
    126
    127int psp_dev_init(struct sp_device *sp)
    128{
    129	struct device *dev = sp->dev;
    130	struct psp_device *psp;
    131	int ret;
    132
    133	ret = -ENOMEM;
    134	psp = psp_alloc_struct(sp);
    135	if (!psp)
    136		goto e_err;
    137
    138	sp->psp_data = psp;
    139
    140	psp->vdata = (struct psp_vdata *)sp->dev_vdata->psp_vdata;
    141	if (!psp->vdata) {
    142		ret = -ENODEV;
    143		dev_err(dev, "missing driver data\n");
    144		goto e_err;
    145	}
    146
    147	psp->io_regs = sp->io_map;
    148
    149	ret = psp_get_capability(psp);
    150	if (ret)
    151		goto e_disable;
    152
    153	/* Disable and clear interrupts until ready */
    154	iowrite32(0, psp->io_regs + psp->vdata->inten_reg);
    155	iowrite32(-1, psp->io_regs + psp->vdata->intsts_reg);
    156
    157	/* Request an irq */
    158	ret = sp_request_psp_irq(psp->sp, psp_irq_handler, psp->name, psp);
    159	if (ret) {
    160		dev_err(dev, "psp: unable to allocate an IRQ\n");
    161		goto e_err;
    162	}
    163
    164	ret = psp_init(psp);
    165	if (ret)
    166		goto e_irq;
    167
    168	if (sp->set_psp_master_device)
    169		sp->set_psp_master_device(sp);
    170
    171	/* Enable interrupt */
    172	iowrite32(-1, psp->io_regs + psp->vdata->inten_reg);
    173
    174	dev_notice(dev, "psp enabled\n");
    175
    176	return 0;
    177
    178e_irq:
    179	sp_free_psp_irq(psp->sp, psp);
    180e_err:
    181	sp->psp_data = NULL;
    182
    183	dev_notice(dev, "psp initialization failed\n");
    184
    185	return ret;
    186
    187e_disable:
    188	sp->psp_data = NULL;
    189
    190	return ret;
    191}
    192
    193void psp_dev_destroy(struct sp_device *sp)
    194{
    195	struct psp_device *psp = sp->psp_data;
    196
    197	if (!psp)
    198		return;
    199
    200	sev_dev_destroy(psp);
    201
    202	tee_dev_destroy(psp);
    203
    204	sp_free_psp_irq(sp, psp);
    205
    206	if (sp->clear_psp_master_device)
    207		sp->clear_psp_master_device(sp);
    208}
    209
    210void psp_set_sev_irq_handler(struct psp_device *psp, psp_irq_handler_t handler,
    211			     void *data)
    212{
    213	psp->sev_irq_data = data;
    214	psp->sev_irq_handler = handler;
    215}
    216
    217void psp_clear_sev_irq_handler(struct psp_device *psp)
    218{
    219	psp_set_sev_irq_handler(psp, NULL, NULL);
    220}
    221
    222void psp_set_tee_irq_handler(struct psp_device *psp, psp_irq_handler_t handler,
    223			     void *data)
    224{
    225	psp->tee_irq_data = data;
    226	psp->tee_irq_handler = handler;
    227}
    228
    229void psp_clear_tee_irq_handler(struct psp_device *psp)
    230{
    231	psp_set_tee_irq_handler(psp, NULL, NULL);
    232}
    233
    234struct psp_device *psp_get_master_device(void)
    235{
    236	struct sp_device *sp = sp_get_psp_master_device();
    237
    238	return sp ? sp->psp_data : NULL;
    239}
    240
    241void psp_pci_init(void)
    242{
    243	psp_master = psp_get_master_device();
    244
    245	if (!psp_master)
    246		return;
    247
    248	sev_pci_init();
    249}
    250
    251void psp_pci_exit(void)
    252{
    253	if (!psp_master)
    254		return;
    255
    256	sev_pci_exit();
    257}