brintos

brintos / linux-shallow public Read only

0
0
Text · 13.0 KiB · 248d98f Raw
560 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * AMD Secure Processor device driver4 *5 * Copyright (C) 2013,2019 Advanced Micro Devices, Inc.6 *7 * Author: Tom Lendacky <thomas.lendacky@amd.com>8 * Author: Gary R Hook <gary.hook@amd.com>9 */10 11#include <linux/bitfield.h>12#include <linux/module.h>13#include <linux/kernel.h>14#include <linux/device.h>15#include <linux/pci.h>16#include <linux/pci_ids.h>17#include <linux/dma-mapping.h>18#include <linux/kthread.h>19#include <linux/sched.h>20#include <linux/interrupt.h>21#include <linux/spinlock.h>22#include <linux/delay.h>23#include <linux/ccp.h>24 25#include "ccp-dev.h"26#include "psp-dev.h"27#include "hsti.h"28 29/* used for version string AA.BB.CC.DD */30#define AA				GENMASK(31, 24)31#define BB				GENMASK(23, 16)32#define CC				GENMASK(15, 8)33#define DD				GENMASK(7, 0)34 35#define MSIX_VECTORS			236 37struct sp_pci {38	int msix_count;39	struct msix_entry msix_entry[MSIX_VECTORS];40};41static struct sp_device *sp_dev_master;42 43#define version_attribute_show(name, _offset)					\44static ssize_t name##_show(struct device *d, struct device_attribute *attr,	\45			   char *buf)						\46{										\47	struct sp_device *sp = dev_get_drvdata(d);				\48	struct psp_device *psp = sp->psp_data;					\49	unsigned int val = ioread32(psp->io_regs + _offset);			\50	return sysfs_emit(buf, "%02lx.%02lx.%02lx.%02lx\n",			\51			  FIELD_GET(AA, val),			\52			  FIELD_GET(BB, val),			\53			  FIELD_GET(CC, val),			\54			  FIELD_GET(DD, val));			\55}56 57version_attribute_show(bootloader_version, psp->vdata->bootloader_info_reg)58static DEVICE_ATTR_RO(bootloader_version);59version_attribute_show(tee_version, psp->vdata->tee->info_reg)60static DEVICE_ATTR_RO(tee_version);61 62static struct attribute *psp_firmware_attrs[] = {63	&dev_attr_bootloader_version.attr,64	&dev_attr_tee_version.attr,65	NULL,66};67 68static umode_t psp_firmware_is_visible(struct kobject *kobj, struct attribute *attr, int idx)69{70	struct device *dev = kobj_to_dev(kobj);71	struct sp_device *sp = dev_get_drvdata(dev);72	struct psp_device *psp = sp->psp_data;73	unsigned int val = 0xffffffff;74 75	if (!psp)76		return 0;77 78	if (attr == &dev_attr_bootloader_version.attr &&79	    psp->vdata->bootloader_info_reg)80		val = ioread32(psp->io_regs + psp->vdata->bootloader_info_reg);81 82	if (attr == &dev_attr_tee_version.attr && psp->capability.tee &&83	    psp->vdata->tee->info_reg)84		val = ioread32(psp->io_regs + psp->vdata->tee->info_reg);85 86	/* If platform disallows accessing this register it will be all f's */87	if (val != 0xffffffff)88		return 0444;89 90	return 0;91}92 93static struct attribute_group psp_firmware_attr_group = {94	.attrs = psp_firmware_attrs,95	.is_visible = psp_firmware_is_visible,96};97 98static const struct attribute_group *psp_groups[] = {99#ifdef CONFIG_CRYPTO_DEV_SP_PSP100	&psp_security_attr_group,101#endif102	&psp_firmware_attr_group,103	NULL,104};105 106static int sp_get_msix_irqs(struct sp_device *sp)107{108	struct sp_pci *sp_pci = sp->dev_specific;109	struct device *dev = sp->dev;110	struct pci_dev *pdev = to_pci_dev(dev);111	int v, ret;112 113	for (v = 0; v < ARRAY_SIZE(sp_pci->msix_entry); v++)114		sp_pci->msix_entry[v].entry = v;115 116	ret = pci_enable_msix_range(pdev, sp_pci->msix_entry, 1, v);117	if (ret < 0)118		return ret;119 120	sp_pci->msix_count = ret;121	sp->use_tasklet = true;122 123	sp->psp_irq = sp_pci->msix_entry[0].vector;124	sp->ccp_irq = (sp_pci->msix_count > 1) ? sp_pci->msix_entry[1].vector125					       : sp_pci->msix_entry[0].vector;126	return 0;127}128 129static int sp_get_msi_irq(struct sp_device *sp)130{131	struct device *dev = sp->dev;132	struct pci_dev *pdev = to_pci_dev(dev);133	int ret;134 135	ret = pci_enable_msi(pdev);136	if (ret)137		return ret;138 139	sp->ccp_irq = pdev->irq;140	sp->psp_irq = pdev->irq;141 142	return 0;143}144 145static int sp_get_irqs(struct sp_device *sp)146{147	struct device *dev = sp->dev;148	int ret;149 150	ret = sp_get_msix_irqs(sp);151	if (!ret)152		return 0;153 154	/* Couldn't get MSI-X vectors, try MSI */155	dev_notice(dev, "could not enable MSI-X (%d), trying MSI\n", ret);156	ret = sp_get_msi_irq(sp);157	if (!ret)158		return 0;159 160	/* Couldn't get MSI interrupt */161	dev_notice(dev, "could not enable MSI (%d)\n", ret);162 163	return ret;164}165 166static void sp_free_irqs(struct sp_device *sp)167{168	struct sp_pci *sp_pci = sp->dev_specific;169	struct device *dev = sp->dev;170	struct pci_dev *pdev = to_pci_dev(dev);171 172	if (sp_pci->msix_count)173		pci_disable_msix(pdev);174	else if (sp->psp_irq)175		pci_disable_msi(pdev);176 177	sp->ccp_irq = 0;178	sp->psp_irq = 0;179}180 181static bool sp_pci_is_master(struct sp_device *sp)182{183	struct device *dev_cur, *dev_new;184	struct pci_dev *pdev_cur, *pdev_new;185 186	dev_new = sp->dev;187	dev_cur = sp_dev_master->dev;188 189	pdev_new = to_pci_dev(dev_new);190	pdev_cur = to_pci_dev(dev_cur);191 192	if (pdev_new->bus->number < pdev_cur->bus->number)193		return true;194 195	if (PCI_SLOT(pdev_new->devfn) < PCI_SLOT(pdev_cur->devfn))196		return true;197 198	if (PCI_FUNC(pdev_new->devfn) < PCI_FUNC(pdev_cur->devfn))199		return true;200 201	return false;202}203 204static void psp_set_master(struct sp_device *sp)205{206	if (!sp_dev_master) {207		sp_dev_master = sp;208		return;209	}210 211	if (sp_pci_is_master(sp))212		sp_dev_master = sp;213}214 215static struct sp_device *psp_get_master(void)216{217	return sp_dev_master;218}219 220static void psp_clear_master(struct sp_device *sp)221{222	if (sp == sp_dev_master) {223		sp_dev_master = NULL;224		dev_dbg(sp->dev, "Cleared sp_dev_master\n");225	}226}227 228static int sp_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)229{230	struct sp_device *sp;231	struct sp_pci *sp_pci;232	struct device *dev = &pdev->dev;233	void __iomem * const *iomap_table;234	int bar_mask;235	int ret;236 237	ret = -ENOMEM;238	sp = sp_alloc_struct(dev);239	if (!sp)240		goto e_err;241 242	sp_pci = devm_kzalloc(dev, sizeof(*sp_pci), GFP_KERNEL);243	if (!sp_pci)244		goto e_err;245 246	sp->dev_specific = sp_pci;247	sp->dev_vdata = (struct sp_dev_vdata *)id->driver_data;248	if (!sp->dev_vdata) {249		ret = -ENODEV;250		dev_err(dev, "missing driver data\n");251		goto e_err;252	}253 254	ret = pcim_enable_device(pdev);255	if (ret) {256		dev_err(dev, "pcim_enable_device failed (%d)\n", ret);257		goto e_err;258	}259 260	bar_mask = pci_select_bars(pdev, IORESOURCE_MEM);261	ret = pcim_iomap_regions(pdev, bar_mask, "ccp");262	if (ret) {263		dev_err(dev, "pcim_iomap_regions failed (%d)\n", ret);264		goto e_err;265	}266 267	iomap_table = pcim_iomap_table(pdev);268	if (!iomap_table) {269		dev_err(dev, "pcim_iomap_table failed\n");270		ret = -ENOMEM;271		goto e_err;272	}273 274	sp->io_map = iomap_table[sp->dev_vdata->bar];275	if (!sp->io_map) {276		dev_err(dev, "ioremap failed\n");277		ret = -ENOMEM;278		goto e_err;279	}280 281	ret = sp_get_irqs(sp);282	if (ret)283		goto e_err;284 285	pci_set_master(pdev);286	sp->set_psp_master_device = psp_set_master;287	sp->get_psp_master_device = psp_get_master;288	sp->clear_psp_master_device = psp_clear_master;289 290	ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(48));291	if (ret) {292		ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32));293		if (ret) {294			dev_err(dev, "dma_set_mask_and_coherent failed (%d)\n",295				ret);296			goto free_irqs;297		}298	}299 300	dev_set_drvdata(dev, sp);301 302	ret = sp_init(sp);303	if (ret)304		goto free_irqs;305 306	return 0;307 308free_irqs:309	sp_free_irqs(sp);310e_err:311	dev_notice(dev, "initialization failed\n");312	return ret;313}314 315static void sp_pci_shutdown(struct pci_dev *pdev)316{317	struct device *dev = &pdev->dev;318	struct sp_device *sp = dev_get_drvdata(dev);319 320	if (!sp)321		return;322 323	sp_destroy(sp);324}325 326static void sp_pci_remove(struct pci_dev *pdev)327{328	struct device *dev = &pdev->dev;329	struct sp_device *sp = dev_get_drvdata(dev);330 331	if (!sp)332		return;333 334	sp_destroy(sp);335 336	sp_free_irqs(sp);337}338 339static int __maybe_unused sp_pci_suspend(struct device *dev)340{341	struct sp_device *sp = dev_get_drvdata(dev);342 343	return sp_suspend(sp);344}345 346static int __maybe_unused sp_pci_resume(struct device *dev)347{348	struct sp_device *sp = dev_get_drvdata(dev);349 350	return sp_resume(sp);351}352 353#ifdef CONFIG_CRYPTO_DEV_SP_PSP354static const struct sev_vdata sevv1 = {355	.cmdresp_reg		= 0x10580,	/* C2PMSG_32 */356	.cmdbuff_addr_lo_reg	= 0x105e0,	/* C2PMSG_56 */357	.cmdbuff_addr_hi_reg	= 0x105e4,	/* C2PMSG_57 */358};359 360static const struct sev_vdata sevv2 = {361	.cmdresp_reg		= 0x10980,	/* C2PMSG_32 */362	.cmdbuff_addr_lo_reg	= 0x109e0,	/* C2PMSG_56 */363	.cmdbuff_addr_hi_reg	= 0x109e4,	/* C2PMSG_57 */364};365 366static const struct tee_vdata teev1 = {367	.ring_wptr_reg          = 0x10550,	/* C2PMSG_20 */368	.ring_rptr_reg          = 0x10554,	/* C2PMSG_21 */369	.info_reg		= 0x109e8,	/* C2PMSG_58 */370};371 372static const struct tee_vdata teev2 = {373	.ring_wptr_reg		= 0x10950,	/* C2PMSG_20 */374	.ring_rptr_reg		= 0x10954,	/* C2PMSG_21 */375};376 377static const struct platform_access_vdata pa_v1 = {378	.cmdresp_reg		= 0x10570,	/* C2PMSG_28 */379	.cmdbuff_addr_lo_reg	= 0x10574,	/* C2PMSG_29 */380	.cmdbuff_addr_hi_reg	= 0x10578,	/* C2PMSG_30 */381	.doorbell_button_reg	= 0x10a24,	/* C2PMSG_73 */382	.doorbell_cmd_reg	= 0x10a40,	/* C2PMSG_80 */383};384 385static const struct platform_access_vdata pa_v2 = {386	.doorbell_button_reg	= 0x10a24,	/* C2PMSG_73 */387	.doorbell_cmd_reg	= 0x10a40,	/* C2PMSG_80 */388};389 390static const struct psp_vdata pspv1 = {391	.sev			= &sevv1,392	.bootloader_info_reg	= 0x105ec,	/* C2PMSG_59 */393	.feature_reg		= 0x105fc,	/* C2PMSG_63 */394	.inten_reg		= 0x10610,	/* P2CMSG_INTEN */395	.intsts_reg		= 0x10614,	/* P2CMSG_INTSTS */396};397 398static const struct psp_vdata pspv2 = {399	.sev			= &sevv2,400	.platform_access	= &pa_v1,401	.bootloader_info_reg	= 0x109ec,	/* C2PMSG_59 */402	.feature_reg		= 0x109fc,	/* C2PMSG_63 */403	.inten_reg		= 0x10690,	/* P2CMSG_INTEN */404	.intsts_reg		= 0x10694,	/* P2CMSG_INTSTS */405	.platform_features	= PLATFORM_FEATURE_HSTI,406};407 408static const struct psp_vdata pspv3 = {409	.tee			= &teev1,410	.platform_access	= &pa_v1,411	.cmdresp_reg		= 0x10544,	/* C2PMSG_17 */412	.cmdbuff_addr_lo_reg	= 0x10548,	/* C2PMSG_18 */413	.cmdbuff_addr_hi_reg	= 0x1054c,	/* C2PMSG_19 */414	.bootloader_info_reg	= 0x109ec,	/* C2PMSG_59 */415	.feature_reg		= 0x109fc,	/* C2PMSG_63 */416	.inten_reg		= 0x10690,	/* P2CMSG_INTEN */417	.intsts_reg		= 0x10694,	/* P2CMSG_INTSTS */418	.platform_features	= PLATFORM_FEATURE_DBC |419				  PLATFORM_FEATURE_HSTI,420};421 422static const struct psp_vdata pspv4 = {423	.sev			= &sevv2,424	.tee			= &teev1,425	.cmdresp_reg		= 0x10544,	/* C2PMSG_17 */426	.cmdbuff_addr_lo_reg	= 0x10548,	/* C2PMSG_18 */427	.cmdbuff_addr_hi_reg	= 0x1054c,	/* C2PMSG_19 */428	.bootloader_info_reg	= 0x109ec,	/* C2PMSG_59 */429	.feature_reg		= 0x109fc,	/* C2PMSG_63 */430	.inten_reg		= 0x10690,	/* P2CMSG_INTEN */431	.intsts_reg		= 0x10694,	/* P2CMSG_INTSTS */432};433 434static const struct psp_vdata pspv5 = {435	.tee			= &teev2,436	.platform_access	= &pa_v2,437	.cmdresp_reg		= 0x10944,	/* C2PMSG_17 */438	.cmdbuff_addr_lo_reg	= 0x10948,	/* C2PMSG_18 */439	.cmdbuff_addr_hi_reg	= 0x1094c,	/* C2PMSG_19 */440	.feature_reg		= 0x109fc,	/* C2PMSG_63 */441	.inten_reg		= 0x10510,	/* P2CMSG_INTEN */442	.intsts_reg		= 0x10514,	/* P2CMSG_INTSTS */443};444 445static const struct psp_vdata pspv6 = {446	.sev                    = &sevv2,447	.tee                    = &teev2,448	.cmdresp_reg		= 0x10944,	/* C2PMSG_17 */449	.cmdbuff_addr_lo_reg	= 0x10948,	/* C2PMSG_18 */450	.cmdbuff_addr_hi_reg	= 0x1094c,	/* C2PMSG_19 */451	.feature_reg            = 0x109fc,	/* C2PMSG_63 */452	.inten_reg              = 0x10510,	/* P2CMSG_INTEN */453	.intsts_reg             = 0x10514,	/* P2CMSG_INTSTS */454};455 456#endif457 458static const struct sp_dev_vdata dev_vdata[] = {459	{	/* 0 */460		.bar = 2,461#ifdef CONFIG_CRYPTO_DEV_SP_CCP462		.ccp_vdata = &ccpv3,463#endif464	},465	{	/* 1 */466		.bar = 2,467#ifdef CONFIG_CRYPTO_DEV_SP_CCP468		.ccp_vdata = &ccpv5a,469#endif470#ifdef CONFIG_CRYPTO_DEV_SP_PSP471		.psp_vdata = &pspv1,472#endif473	},474	{	/* 2 */475		.bar = 2,476#ifdef CONFIG_CRYPTO_DEV_SP_CCP477		.ccp_vdata = &ccpv5b,478#endif479	},480	{	/* 3 */481		.bar = 2,482#ifdef CONFIG_CRYPTO_DEV_SP_CCP483		.ccp_vdata = &ccpv5a,484#endif485#ifdef CONFIG_CRYPTO_DEV_SP_PSP486		.psp_vdata = &pspv2,487#endif488	},489	{	/* 4 */490		.bar = 2,491#ifdef CONFIG_CRYPTO_DEV_SP_CCP492		.ccp_vdata = &ccpv5a,493#endif494#ifdef CONFIG_CRYPTO_DEV_SP_PSP495		.psp_vdata = &pspv3,496#endif497	},498	{	/* 5 */499		.bar = 2,500#ifdef CONFIG_CRYPTO_DEV_SP_PSP501		.psp_vdata = &pspv4,502#endif503	},504	{	/* 6 */505		.bar = 2,506#ifdef CONFIG_CRYPTO_DEV_SP_PSP507		.psp_vdata = &pspv3,508#endif509	},510	{	/* 7 */511		.bar = 2,512#ifdef CONFIG_CRYPTO_DEV_SP_PSP513		.psp_vdata = &pspv5,514#endif515	},516	{	/* 8 */517		.bar = 2,518#ifdef CONFIG_CRYPTO_DEV_SP_PSP519		.psp_vdata = &pspv6,520#endif521	},522};523static const struct pci_device_id sp_pci_table[] = {524	{ PCI_VDEVICE(AMD, 0x1537), (kernel_ulong_t)&dev_vdata[0] },525	{ PCI_VDEVICE(AMD, 0x1456), (kernel_ulong_t)&dev_vdata[1] },526	{ PCI_VDEVICE(AMD, 0x1468), (kernel_ulong_t)&dev_vdata[2] },527	{ PCI_VDEVICE(AMD, 0x1486), (kernel_ulong_t)&dev_vdata[3] },528	{ PCI_VDEVICE(AMD, 0x15DF), (kernel_ulong_t)&dev_vdata[4] },529	{ PCI_VDEVICE(AMD, 0x14CA), (kernel_ulong_t)&dev_vdata[5] },530	{ PCI_VDEVICE(AMD, 0x15C7), (kernel_ulong_t)&dev_vdata[6] },531	{ PCI_VDEVICE(AMD, 0x1649), (kernel_ulong_t)&dev_vdata[6] },532	{ PCI_VDEVICE(AMD, 0x17E0), (kernel_ulong_t)&dev_vdata[7] },533	{ PCI_VDEVICE(AMD, 0x156E), (kernel_ulong_t)&dev_vdata[8] },534	/* Last entry must be zero */535	{ 0, }536};537MODULE_DEVICE_TABLE(pci, sp_pci_table);538 539static SIMPLE_DEV_PM_OPS(sp_pci_pm_ops, sp_pci_suspend, sp_pci_resume);540 541static struct pci_driver sp_pci_driver = {542	.name = "ccp",543	.id_table = sp_pci_table,544	.probe = sp_pci_probe,545	.remove = sp_pci_remove,546	.shutdown = sp_pci_shutdown,547	.driver.pm = &sp_pci_pm_ops,548	.dev_groups = psp_groups,549};550 551int sp_pci_init(void)552{553	return pci_register_driver(&sp_pci_driver);554}555 556void sp_pci_exit(void)557{558	pci_unregister_driver(&sp_pci_driver);559}560