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 17 struct psp_device *psp_master; 18 19 static struct psp_device *psp_alloc_struct(struct sp_device *sp) 20 { 21 struct device *dev = sp->dev; 22 struct psp_device *psp; 23 24 psp = devm_kzalloc(dev, sizeof(*psp), GFP_KERNEL); 25 if (!psp) 26 return NULL; 27 28 psp->dev = dev; 29 psp->sp = sp; 30 31 snprintf(psp->name, sizeof(psp->name), "psp-%u", sp->ord); 32 33 return psp; 34 } 35 36 static irqreturn_t psp_irq_handler(int irq, void *data) 37 { 38 struct psp_device *psp = data; 39 unsigned int status; 40 41 /* Read the interrupt status: */ 42 status = ioread32(psp->io_regs + psp->vdata->intsts_reg); 43 44 /* invoke subdevice interrupt handlers */ 45 if (status) { 46 if (psp->sev_irq_handler) 47 psp->sev_irq_handler(irq, psp->sev_irq_data, status); 48 } 49 50 /* Clear the interrupt status by writing the same value we read. */ 51 iowrite32(status, psp->io_regs + psp->vdata->intsts_reg); 52 53 return IRQ_HANDLED; 54 } 55 56 static int psp_check_sev_support(struct psp_device *psp) 57 { 58 unsigned int val = ioread32(psp->io_regs + psp->vdata->feature_reg); 59 60 /* 61 * Check for a access to the registers. If this read returns 62 * 0xffffffff, it's likely that the system is running a broken 63 * BIOS which disallows access to the device. Stop here and 64 * fail the PSP initialization (but not the load, as the CCP 65 * could get properly initialized). 66 */ 67 if (val == 0xffffffff) { 68 dev_notice(psp->dev, "psp: unable to access the device: you might be running a broken BIOS.\n"); 69 return -ENODEV; 70 } 71 72 if (!(val & 1)) { 73 /* Device does not support the SEV feature */ 74 dev_dbg(psp->dev, "psp does not support SEV\n"); 75 return -ENODEV; 76 } 77 78 return 0; 79 } 80 81 int psp_dev_init(struct sp_device *sp) 82 { 83 struct device *dev = sp->dev; 84 struct psp_device *psp; 85 int ret; 86 87 ret = -ENOMEM; 88 psp = psp_alloc_struct(sp); 89 if (!psp) 90 goto e_err; 91 92 sp->psp_data = psp; 93 94 psp->vdata = (struct psp_vdata *)sp->dev_vdata->psp_vdata; 95 if (!psp->vdata) { 96 ret = -ENODEV; 97 dev_err(dev, "missing driver data\n"); 98 goto e_err; 99 } 100 101 psp->io_regs = sp->io_map; 102 103 ret = psp_check_sev_support(psp); 104 if (ret) 105 goto e_disable; 106 107 /* Disable and clear interrupts until ready */ 108 iowrite32(0, psp->io_regs + psp->vdata->inten_reg); 109 iowrite32(-1, psp->io_regs + psp->vdata->intsts_reg); 110 111 /* Request an irq */ 112 ret = sp_request_psp_irq(psp->sp, psp_irq_handler, psp->name, psp); 113 if (ret) { 114 dev_err(dev, "psp: unable to allocate an IRQ\n"); 115 goto e_err; 116 } 117 118 ret = sev_dev_init(psp); 119 if (ret) 120 goto e_irq; 121 122 if (sp->set_psp_master_device) 123 sp->set_psp_master_device(sp); 124 125 /* Enable interrupt */ 126 iowrite32(-1, psp->io_regs + psp->vdata->inten_reg); 127 128 dev_notice(dev, "psp enabled\n"); 129 130 return 0; 131 132 e_irq: 133 sp_free_psp_irq(psp->sp, psp); 134 e_err: 135 sp->psp_data = NULL; 136 137 dev_notice(dev, "psp initialization failed\n"); 138 139 return ret; 140 141 e_disable: 142 sp->psp_data = NULL; 143 144 return ret; 145 } 146 147 void psp_dev_destroy(struct sp_device *sp) 148 { 149 struct psp_device *psp = sp->psp_data; 150 151 if (!psp) 152 return; 153 154 sev_dev_destroy(psp); 155 156 sp_free_psp_irq(sp, psp); 157 } 158 159 void psp_set_sev_irq_handler(struct psp_device *psp, psp_irq_handler_t handler, 160 void *data) 161 { 162 psp->sev_irq_data = data; 163 psp->sev_irq_handler = handler; 164 } 165 166 void psp_clear_sev_irq_handler(struct psp_device *psp) 167 { 168 psp_set_sev_irq_handler(psp, NULL, NULL); 169 } 170 171 struct psp_device *psp_get_master_device(void) 172 { 173 struct sp_device *sp = sp_get_psp_master_device(); 174 175 return sp ? sp->psp_data : NULL; 176 } 177 178 void psp_pci_init(void) 179 { 180 psp_master = psp_get_master_device(); 181 182 if (!psp_master) 183 return; 184 185 sev_pci_init(); 186 } 187 188 void psp_pci_exit(void) 189 { 190 if (!psp_master) 191 return; 192 193 sev_pci_exit(); 194 } 195