linux/drivers/crypto/ccp/psp-dev.c
<<
>>
Prefs
   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 0;
  74        }
  75
  76        return val;
  77}
  78
  79static int psp_check_sev_support(struct psp_device *psp,
  80                                 unsigned int capability)
  81{
  82        /* Check if device supports SEV feature */
  83        if (!(capability & 1)) {
  84                dev_dbg(psp->dev, "psp does not support SEV\n");
  85                return -ENODEV;
  86        }
  87
  88        return 0;
  89}
  90
  91static int psp_check_tee_support(struct psp_device *psp,
  92                                 unsigned int capability)
  93{
  94        /* Check if device supports TEE feature */
  95        if (!(capability & 2)) {
  96                dev_dbg(psp->dev, "psp does not support TEE\n");
  97                return -ENODEV;
  98        }
  99
 100        return 0;
 101}
 102
 103static int psp_check_support(struct psp_device *psp,
 104                             unsigned int capability)
 105{
 106        int sev_support = psp_check_sev_support(psp, capability);
 107        int tee_support = psp_check_tee_support(psp, capability);
 108
 109        /* Return error if device neither supports SEV nor TEE */
 110        if (sev_support && tee_support)
 111                return -ENODEV;
 112
 113        return 0;
 114}
 115
 116static int psp_init(struct psp_device *psp, unsigned int capability)
 117{
 118        int ret;
 119
 120        if (!psp_check_sev_support(psp, capability)) {
 121                ret = sev_dev_init(psp);
 122                if (ret)
 123                        return ret;
 124        }
 125
 126        if (!psp_check_tee_support(psp, capability)) {
 127                ret = tee_dev_init(psp);
 128                if (ret)
 129                        return ret;
 130        }
 131
 132        return 0;
 133}
 134
 135int psp_dev_init(struct sp_device *sp)
 136{
 137        struct device *dev = sp->dev;
 138        struct psp_device *psp;
 139        unsigned int capability;
 140        int ret;
 141
 142        ret = -ENOMEM;
 143        psp = psp_alloc_struct(sp);
 144        if (!psp)
 145                goto e_err;
 146
 147        sp->psp_data = psp;
 148
 149        psp->vdata = (struct psp_vdata *)sp->dev_vdata->psp_vdata;
 150        if (!psp->vdata) {
 151                ret = -ENODEV;
 152                dev_err(dev, "missing driver data\n");
 153                goto e_err;
 154        }
 155
 156        psp->io_regs = sp->io_map;
 157
 158        capability = psp_get_capability(psp);
 159        if (!capability)
 160                goto e_disable;
 161
 162        ret = psp_check_support(psp, capability);
 163        if (ret)
 164                goto e_disable;
 165
 166        /* Disable and clear interrupts until ready */
 167        iowrite32(0, psp->io_regs + psp->vdata->inten_reg);
 168        iowrite32(-1, psp->io_regs + psp->vdata->intsts_reg);
 169
 170        /* Request an irq */
 171        ret = sp_request_psp_irq(psp->sp, psp_irq_handler, psp->name, psp);
 172        if (ret) {
 173                dev_err(dev, "psp: unable to allocate an IRQ\n");
 174                goto e_err;
 175        }
 176
 177        ret = psp_init(psp, capability);
 178        if (ret)
 179                goto e_irq;
 180
 181        if (sp->set_psp_master_device)
 182                sp->set_psp_master_device(sp);
 183
 184        /* Enable interrupt */
 185        iowrite32(-1, psp->io_regs + psp->vdata->inten_reg);
 186
 187        dev_notice(dev, "psp enabled\n");
 188
 189        return 0;
 190
 191e_irq:
 192        sp_free_psp_irq(psp->sp, psp);
 193e_err:
 194        sp->psp_data = NULL;
 195
 196        dev_notice(dev, "psp initialization failed\n");
 197
 198        return ret;
 199
 200e_disable:
 201        sp->psp_data = NULL;
 202
 203        return ret;
 204}
 205
 206void psp_dev_destroy(struct sp_device *sp)
 207{
 208        struct psp_device *psp = sp->psp_data;
 209
 210        if (!psp)
 211                return;
 212
 213        sev_dev_destroy(psp);
 214
 215        tee_dev_destroy(psp);
 216
 217        sp_free_psp_irq(sp, psp);
 218
 219        if (sp->clear_psp_master_device)
 220                sp->clear_psp_master_device(sp);
 221}
 222
 223void psp_set_sev_irq_handler(struct psp_device *psp, psp_irq_handler_t handler,
 224                             void *data)
 225{
 226        psp->sev_irq_data = data;
 227        psp->sev_irq_handler = handler;
 228}
 229
 230void psp_clear_sev_irq_handler(struct psp_device *psp)
 231{
 232        psp_set_sev_irq_handler(psp, NULL, NULL);
 233}
 234
 235void psp_set_tee_irq_handler(struct psp_device *psp, psp_irq_handler_t handler,
 236                             void *data)
 237{
 238        psp->tee_irq_data = data;
 239        psp->tee_irq_handler = handler;
 240}
 241
 242void psp_clear_tee_irq_handler(struct psp_device *psp)
 243{
 244        psp_set_tee_irq_handler(psp, NULL, NULL);
 245}
 246
 247struct psp_device *psp_get_master_device(void)
 248{
 249        struct sp_device *sp = sp_get_psp_master_device();
 250
 251        return sp ? sp->psp_data : NULL;
 252}
 253
 254void psp_pci_init(void)
 255{
 256        psp_master = psp_get_master_device();
 257
 258        if (!psp_master)
 259                return;
 260
 261        sev_pci_init();
 262}
 263
 264void psp_pci_exit(void)
 265{
 266        if (!psp_master)
 267                return;
 268
 269        sev_pci_exit();
 270}
 271