The goal of this patch series is to introduce TEE (Trusted Execution
Environment) interface support to AMD Secure Processor driver. The
TEE is a secure area of a processor which ensures that sensitive data
is stored, processed and protected in an isolated and trusted
environment. The Platform Security Processor (PSP) is a dedicated
processor which provides TEE to enable HW platform security. It offers
protection against software attacks generated in Rich Operating System
(Rich OS) such as Linux running on x86.
Based on the platform feature support, the PSP is capable of supporting
either SEV (Secure Encrypted Virtualization) and/or TEE. The first three
patches in this series is about moving SEV specific functions and data
structures from PSP device driver file to a dedicated SEV interface
driver file. The last two patches add TEE interface support to AMD
Secure Processor driver. This TEE interface will be used by AMD-TEE
driver to submit command buffers for processing in PSP Trusted Execution
Environment.
v3:
* Rebased the patches onto cryptodev-2.6 tree with base commit
4ee812f6143d (crypto: vmx - Avoid weird build failures)
v2:
* Rebased the patches on cryptodev-2.6 tree with base commit
d158367682cd (crypto: atmel - Fix selection of CRYPTO_AUTHENC)
* Regenerated patch with correct diff-stat to show file rename
* Used Co-developed-by: tag to give proper credit to co-author
Rijo Thomas (6):
crypto: ccp - rename psp-dev files to sev-dev
crypto: ccp - create a generic psp-dev file
crypto: ccp - move SEV vdata to a dedicated data structure
crypto: ccp - check whether PSP supports SEV or TEE before
initialization
crypto: ccp - add TEE support for Raven Ridge
crypto: ccp - provide in-kernel API to submit TEE commands
drivers/crypto/ccp/Makefile | 4 +-
drivers/crypto/ccp/psp-dev.c | 1033 ++++------------------------------------
drivers/crypto/ccp/psp-dev.h | 51 +-
drivers/crypto/ccp/sev-dev.c | 1068 ++++++++++++++++++++++++++++++++++++++++++
drivers/crypto/ccp/sev-dev.h | 63 +++
drivers/crypto/ccp/sp-dev.h | 17 +-
drivers/crypto/ccp/sp-pci.c | 43 +-
drivers/crypto/ccp/tee-dev.c | 364 ++++++++++++++
drivers/crypto/ccp/tee-dev.h | 110 +++++
include/linux/psp-tee.h | 73 +++
10 files changed, 1842 insertions(+), 984 deletions(-)
create mode 100644 drivers/crypto/ccp/sev-dev.c
create mode 100644 drivers/crypto/ccp/sev-dev.h
create mode 100644 drivers/crypto/ccp/tee-dev.c
create mode 100644 drivers/crypto/ccp/tee-dev.h
create mode 100644 include/linux/psp-tee.h
--
1.9.1
PSP can support both SEV and TEE interface. Therefore, move
SEV specific registers to a dedicated data structure.
TEE interface specific registers will be added in a later
patch.
Cc: Ard Biesheuvel <[email protected]>
Cc: Tom Lendacky <[email protected]>
Cc: Jens Wiklander <[email protected]>
Co-developed-by: Devaraj Rangasamy <[email protected]>
Signed-off-by: Devaraj Rangasamy <[email protected]>
Signed-off-by: Rijo Thomas <[email protected]>
---
drivers/crypto/ccp/sev-dev.c | 17 ++++++++++++-----
drivers/crypto/ccp/sev-dev.h | 2 ++
drivers/crypto/ccp/sp-dev.h | 6 +++++-
drivers/crypto/ccp/sp-pci.c | 16 ++++++++++++----
4 files changed, 31 insertions(+), 10 deletions(-)
diff --git a/drivers/crypto/ccp/sev-dev.c b/drivers/crypto/ccp/sev-dev.c
index a608b52..e68fa48 100644
--- a/drivers/crypto/ccp/sev-dev.c
+++ b/drivers/crypto/ccp/sev-dev.c
@@ -65,7 +65,7 @@ static void sev_irq_handler(int irq, void *data, unsigned int status)
return;
/* Check if it is SEV command completion: */
- reg = ioread32(sev->io_regs + sev->psp->vdata->cmdresp_reg);
+ reg = ioread32(sev->io_regs + sev->vdata->cmdresp_reg);
if (reg & PSP_CMDRESP_RESP) {
sev->int_rcvd = 1;
wake_up(&sev->int_queue);
@@ -82,7 +82,7 @@ static int sev_wait_cmd_ioc(struct sev_device *sev,
if (!ret)
return -ETIMEDOUT;
- *reg = ioread32(sev->io_regs + sev->psp->vdata->cmdresp_reg);
+ *reg = ioread32(sev->io_regs + sev->vdata->cmdresp_reg);
return 0;
}
@@ -148,15 +148,15 @@ static int __sev_do_cmd_locked(int cmd, void *data, int *psp_ret)
print_hex_dump_debug("(in): ", DUMP_PREFIX_OFFSET, 16, 2, data,
sev_cmd_buffer_len(cmd), false);
- iowrite32(phys_lsb, sev->io_regs + psp->vdata->cmdbuff_addr_lo_reg);
- iowrite32(phys_msb, sev->io_regs + psp->vdata->cmdbuff_addr_hi_reg);
+ iowrite32(phys_lsb, sev->io_regs + sev->vdata->cmdbuff_addr_lo_reg);
+ iowrite32(phys_msb, sev->io_regs + sev->vdata->cmdbuff_addr_hi_reg);
sev->int_rcvd = 0;
reg = cmd;
reg <<= SEV_CMDRESP_CMD_SHIFT;
reg |= SEV_CMDRESP_IOC;
- iowrite32(reg, sev->io_regs + psp->vdata->cmdresp_reg);
+ iowrite32(reg, sev->io_regs + sev->vdata->cmdresp_reg);
/* wait for command completion */
ret = sev_wait_cmd_ioc(sev, ®, psp_timeout);
@@ -949,6 +949,13 @@ int sev_dev_init(struct psp_device *psp)
sev->io_regs = psp->io_regs;
+ sev->vdata = (struct sev_vdata *)psp->vdata->sev;
+ if (!sev->vdata) {
+ ret = -ENODEV;
+ dev_err(dev, "sev: missing driver data\n");
+ goto e_err;
+ }
+
psp_set_sev_irq_handler(psp, sev_irq_handler, sev);
ret = sev_misc_init(sev);
diff --git a/drivers/crypto/ccp/sev-dev.h b/drivers/crypto/ccp/sev-dev.h
index 3d84ac3..dd5c4fe 100644
--- a/drivers/crypto/ccp/sev-dev.h
+++ b/drivers/crypto/ccp/sev-dev.h
@@ -40,6 +40,8 @@ struct sev_device {
void __iomem *io_regs;
+ struct sev_vdata *vdata;
+
int state;
unsigned int int_rcvd;
wait_queue_head_t int_queue;
diff --git a/drivers/crypto/ccp/sp-dev.h b/drivers/crypto/ccp/sp-dev.h
index 53c1256..0394c75 100644
--- a/drivers/crypto/ccp/sp-dev.h
+++ b/drivers/crypto/ccp/sp-dev.h
@@ -39,10 +39,14 @@ struct ccp_vdata {
const unsigned int rsamax;
};
-struct psp_vdata {
+struct sev_vdata {
const unsigned int cmdresp_reg;
const unsigned int cmdbuff_addr_lo_reg;
const unsigned int cmdbuff_addr_hi_reg;
+};
+
+struct psp_vdata {
+ const struct sev_vdata *sev;
const unsigned int feature_reg;
const unsigned int inten_reg;
const unsigned int intsts_reg;
diff --git a/drivers/crypto/ccp/sp-pci.c b/drivers/crypto/ccp/sp-pci.c
index b29d2e6..733693d 100644
--- a/drivers/crypto/ccp/sp-pci.c
+++ b/drivers/crypto/ccp/sp-pci.c
@@ -262,19 +262,27 @@ static int sp_pci_resume(struct pci_dev *pdev)
#endif
#ifdef CONFIG_CRYPTO_DEV_SP_PSP
-static const struct psp_vdata pspv1 = {
+static const struct sev_vdata sevv1 = {
.cmdresp_reg = 0x10580,
.cmdbuff_addr_lo_reg = 0x105e0,
.cmdbuff_addr_hi_reg = 0x105e4,
+};
+
+static const struct sev_vdata sevv2 = {
+ .cmdresp_reg = 0x10980,
+ .cmdbuff_addr_lo_reg = 0x109e0,
+ .cmdbuff_addr_hi_reg = 0x109e4,
+};
+
+static const struct psp_vdata pspv1 = {
+ .sev = &sevv1,
.feature_reg = 0x105fc,
.inten_reg = 0x10610,
.intsts_reg = 0x10614,
};
static const struct psp_vdata pspv2 = {
- .cmdresp_reg = 0x10980,
- .cmdbuff_addr_lo_reg = 0x109e0,
- .cmdbuff_addr_hi_reg = 0x109e4,
+ .sev = &sevv2,
.feature_reg = 0x109fc,
.inten_reg = 0x10690,
.intsts_reg = 0x10694,
--
1.9.1
Adds a PCI device entry for Raven Ridge. Raven Ridge is an APU with a
dedicated AMD Secure Processor having Trusted Execution Environment (TEE)
support. The TEE provides a secure environment for running Trusted
Applications (TAs) which implement security-sensitive parts of a feature.
This patch configures AMD Secure Processor's TEE interface by initializing
a ring buffer (shared memory between Rich OS and Trusted OS) which can hold
multiple command buffer entries. The TEE interface is facilitated by a set
of CPU to PSP mailbox registers.
The next patch will address how commands are submitted to the ring buffer.
Cc: Jens Wiklander <[email protected]>
Cc: Tom Lendacky <[email protected]>
Cc: Ard Biesheuvel <[email protected]>
Co-developed-by: Devaraj Rangasamy <[email protected]>
Signed-off-by: Devaraj Rangasamy <[email protected]>
Signed-off-by: Rijo Thomas <[email protected]>
---
drivers/crypto/ccp/Makefile | 3 +-
drivers/crypto/ccp/psp-dev.c | 39 ++++++-
drivers/crypto/ccp/psp-dev.h | 8 ++
drivers/crypto/ccp/sp-dev.h | 11 +-
drivers/crypto/ccp/sp-pci.c | 27 ++++-
drivers/crypto/ccp/tee-dev.c | 238 +++++++++++++++++++++++++++++++++++++++++++
drivers/crypto/ccp/tee-dev.h | 109 ++++++++++++++++++++
7 files changed, 431 insertions(+), 4 deletions(-)
create mode 100644 drivers/crypto/ccp/tee-dev.c
create mode 100644 drivers/crypto/ccp/tee-dev.h
diff --git a/drivers/crypto/ccp/Makefile b/drivers/crypto/ccp/Makefile
index 3b29ea4..db362fe 100644
--- a/drivers/crypto/ccp/Makefile
+++ b/drivers/crypto/ccp/Makefile
@@ -9,7 +9,8 @@ ccp-$(CONFIG_CRYPTO_DEV_SP_CCP) += ccp-dev.o \
ccp-$(CONFIG_CRYPTO_DEV_CCP_DEBUGFS) += ccp-debugfs.o
ccp-$(CONFIG_PCI) += sp-pci.o
ccp-$(CONFIG_CRYPTO_DEV_SP_PSP) += psp-dev.o \
- sev-dev.o
+ sev-dev.o \
+ tee-dev.o
obj-$(CONFIG_CRYPTO_DEV_CCP_CRYPTO) += ccp-crypto.o
ccp-crypto-objs := ccp-crypto-main.o \
diff --git a/drivers/crypto/ccp/psp-dev.c b/drivers/crypto/ccp/psp-dev.c
index 3bedf72..e95e7aa 100644
--- a/drivers/crypto/ccp/psp-dev.c
+++ b/drivers/crypto/ccp/psp-dev.c
@@ -13,6 +13,7 @@
#include "sp-dev.h"
#include "psp-dev.h"
#include "sev-dev.h"
+#include "tee-dev.h"
struct psp_device *psp_master;
@@ -45,6 +46,9 @@ static irqreturn_t psp_irq_handler(int irq, void *data)
if (status) {
if (psp->sev_irq_handler)
psp->sev_irq_handler(irq, psp->sev_irq_data, status);
+
+ if (psp->tee_irq_handler)
+ psp->tee_irq_handler(irq, psp->tee_irq_data, status);
}
/* Clear the interrupt status by writing the same value we read. */
@@ -109,6 +113,25 @@ static int psp_check_support(struct psp_device *psp,
return 0;
}
+static int psp_init(struct psp_device *psp, unsigned int capability)
+{
+ int ret;
+
+ if (!psp_check_sev_support(psp, capability)) {
+ ret = sev_dev_init(psp);
+ if (ret)
+ return ret;
+ }
+
+ if (!psp_check_tee_support(psp, capability)) {
+ ret = tee_dev_init(psp);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
int psp_dev_init(struct sp_device *sp)
{
struct device *dev = sp->dev;
@@ -151,7 +174,7 @@ int psp_dev_init(struct sp_device *sp)
goto e_err;
}
- ret = sev_dev_init(psp);
+ ret = psp_init(psp, capability);
if (ret)
goto e_irq;
@@ -189,6 +212,8 @@ void psp_dev_destroy(struct sp_device *sp)
sev_dev_destroy(psp);
+ tee_dev_destroy(psp);
+
sp_free_psp_irq(sp, psp);
}
@@ -204,6 +229,18 @@ void psp_clear_sev_irq_handler(struct psp_device *psp)
psp_set_sev_irq_handler(psp, NULL, NULL);
}
+void psp_set_tee_irq_handler(struct psp_device *psp, psp_irq_handler_t handler,
+ void *data)
+{
+ psp->tee_irq_data = data;
+ psp->tee_irq_handler = handler;
+}
+
+void psp_clear_tee_irq_handler(struct psp_device *psp)
+{
+ psp_set_tee_irq_handler(psp, NULL, NULL);
+}
+
struct psp_device *psp_get_master_device(void)
{
struct sp_device *sp = sp_get_psp_master_device();
diff --git a/drivers/crypto/ccp/psp-dev.h b/drivers/crypto/ccp/psp-dev.h
index 7c014ac..ef38e41 100644
--- a/drivers/crypto/ccp/psp-dev.h
+++ b/drivers/crypto/ccp/psp-dev.h
@@ -40,13 +40,21 @@ struct psp_device {
psp_irq_handler_t sev_irq_handler;
void *sev_irq_data;
+ psp_irq_handler_t tee_irq_handler;
+ void *tee_irq_data;
+
void *sev_data;
+ void *tee_data;
};
void psp_set_sev_irq_handler(struct psp_device *psp, psp_irq_handler_t handler,
void *data);
void psp_clear_sev_irq_handler(struct psp_device *psp);
+void psp_set_tee_irq_handler(struct psp_device *psp, psp_irq_handler_t handler,
+ void *data);
+void psp_clear_tee_irq_handler(struct psp_device *psp);
+
struct psp_device *psp_get_master_device(void);
#endif /* __PSP_DEV_H */
diff --git a/drivers/crypto/ccp/sp-dev.h b/drivers/crypto/ccp/sp-dev.h
index 0394c75..4235946 100644
--- a/drivers/crypto/ccp/sp-dev.h
+++ b/drivers/crypto/ccp/sp-dev.h
@@ -2,7 +2,7 @@
/*
* AMD Secure Processor driver
*
- * Copyright (C) 2017-2018 Advanced Micro Devices, Inc.
+ * Copyright (C) 2017-2019 Advanced Micro Devices, Inc.
*
* Author: Tom Lendacky <[email protected]>
* Author: Gary R Hook <[email protected]>
@@ -45,8 +45,17 @@ struct sev_vdata {
const unsigned int cmdbuff_addr_hi_reg;
};
+struct tee_vdata {
+ const unsigned int cmdresp_reg;
+ const unsigned int cmdbuff_addr_lo_reg;
+ const unsigned int cmdbuff_addr_hi_reg;
+ const unsigned int ring_wptr_reg;
+ const unsigned int ring_rptr_reg;
+};
+
struct psp_vdata {
const struct sev_vdata *sev;
+ const struct tee_vdata *tee;
const unsigned int feature_reg;
const unsigned int inten_reg;
const unsigned int intsts_reg;
diff --git a/drivers/crypto/ccp/sp-pci.c b/drivers/crypto/ccp/sp-pci.c
index 733693d..56c1f61 100644
--- a/drivers/crypto/ccp/sp-pci.c
+++ b/drivers/crypto/ccp/sp-pci.c
@@ -2,7 +2,7 @@
/*
* AMD Secure Processor device driver
*
- * Copyright (C) 2013,2018 Advanced Micro Devices, Inc.
+ * Copyright (C) 2013,2019 Advanced Micro Devices, Inc.
*
* Author: Tom Lendacky <[email protected]>
* Author: Gary R Hook <[email protected]>
@@ -274,6 +274,14 @@ static int sp_pci_resume(struct pci_dev *pdev)
.cmdbuff_addr_hi_reg = 0x109e4,
};
+static const struct tee_vdata teev1 = {
+ .cmdresp_reg = 0x10544,
+ .cmdbuff_addr_lo_reg = 0x10548,
+ .cmdbuff_addr_hi_reg = 0x1054c,
+ .ring_wptr_reg = 0x10550,
+ .ring_rptr_reg = 0x10554,
+};
+
static const struct psp_vdata pspv1 = {
.sev = &sevv1,
.feature_reg = 0x105fc,
@@ -287,6 +295,13 @@ static int sp_pci_resume(struct pci_dev *pdev)
.inten_reg = 0x10690,
.intsts_reg = 0x10694,
};
+
+static const struct psp_vdata pspv3 = {
+ .tee = &teev1,
+ .feature_reg = 0x109fc,
+ .inten_reg = 0x10690,
+ .intsts_reg = 0x10694,
+};
#endif
static const struct sp_dev_vdata dev_vdata[] = {
@@ -320,12 +335,22 @@ static int sp_pci_resume(struct pci_dev *pdev)
.psp_vdata = &pspv2,
#endif
},
+ { /* 4 */
+ .bar = 2,
+#ifdef CONFIG_CRYPTO_DEV_SP_CCP
+ .ccp_vdata = &ccpv5a,
+#endif
+#ifdef CONFIG_CRYPTO_DEV_SP_PSP
+ .psp_vdata = &pspv3,
+#endif
+ },
};
static const struct pci_device_id sp_pci_table[] = {
{ PCI_VDEVICE(AMD, 0x1537), (kernel_ulong_t)&dev_vdata[0] },
{ PCI_VDEVICE(AMD, 0x1456), (kernel_ulong_t)&dev_vdata[1] },
{ PCI_VDEVICE(AMD, 0x1468), (kernel_ulong_t)&dev_vdata[2] },
{ PCI_VDEVICE(AMD, 0x1486), (kernel_ulong_t)&dev_vdata[3] },
+ { PCI_VDEVICE(AMD, 0x15DF), (kernel_ulong_t)&dev_vdata[4] },
/* Last entry must be zero */
{ 0, }
};
diff --git a/drivers/crypto/ccp/tee-dev.c b/drivers/crypto/ccp/tee-dev.c
new file mode 100644
index 0000000..ccbc2ce
--- /dev/null
+++ b/drivers/crypto/ccp/tee-dev.c
@@ -0,0 +1,238 @@
+// SPDX-License-Identifier: MIT
+/*
+ * AMD Trusted Execution Environment (TEE) interface
+ *
+ * Author: Rijo Thomas <[email protected]>
+ * Author: Devaraj Rangasamy <[email protected]>
+ *
+ * Copyright 2019 Advanced Micro Devices, Inc.
+ */
+
+#include <linux/types.h>
+#include <linux/mutex.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/gfp.h>
+#include <linux/psp-sev.h>
+
+#include "psp-dev.h"
+#include "tee-dev.h"
+
+static bool psp_dead;
+
+static int tee_alloc_ring(struct psp_tee_device *tee, int ring_size)
+{
+ struct ring_buf_manager *rb_mgr = &tee->rb_mgr;
+ void *start_addr;
+
+ if (!ring_size)
+ return -EINVAL;
+
+ /* We need actual physical address instead of DMA address, since
+ * Trusted OS running on AMD Secure Processor will map this region
+ */
+ start_addr = (void *)__get_free_pages(GFP_KERNEL, get_order(ring_size));
+ if (!start_addr)
+ return -ENOMEM;
+
+ rb_mgr->ring_start = start_addr;
+ rb_mgr->ring_size = ring_size;
+ rb_mgr->ring_pa = __psp_pa(start_addr);
+
+ return 0;
+}
+
+static void tee_free_ring(struct psp_tee_device *tee)
+{
+ struct ring_buf_manager *rb_mgr = &tee->rb_mgr;
+
+ if (!rb_mgr->ring_start)
+ return;
+
+ free_pages((unsigned long)rb_mgr->ring_start,
+ get_order(rb_mgr->ring_size));
+
+ rb_mgr->ring_start = NULL;
+ rb_mgr->ring_size = 0;
+ rb_mgr->ring_pa = 0;
+}
+
+static int tee_wait_cmd_poll(struct psp_tee_device *tee, unsigned int timeout,
+ unsigned int *reg)
+{
+ /* ~10ms sleep per loop => nloop = timeout * 100 */
+ int nloop = timeout * 100;
+
+ while (--nloop) {
+ *reg = ioread32(tee->io_regs + tee->vdata->cmdresp_reg);
+ if (*reg & PSP_CMDRESP_RESP)
+ return 0;
+
+ usleep_range(10000, 10100);
+ }
+
+ dev_err(tee->dev, "tee: command timed out, disabling PSP\n");
+ psp_dead = true;
+
+ return -ETIMEDOUT;
+}
+
+static
+struct tee_init_ring_cmd *tee_alloc_cmd_buffer(struct psp_tee_device *tee)
+{
+ struct tee_init_ring_cmd *cmd;
+
+ cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
+ if (!cmd)
+ return NULL;
+
+ cmd->hi_addr = upper_32_bits(tee->rb_mgr.ring_pa);
+ cmd->low_addr = lower_32_bits(tee->rb_mgr.ring_pa);
+ cmd->size = tee->rb_mgr.ring_size;
+
+ dev_dbg(tee->dev, "tee: ring address: high = 0x%x low = 0x%x size = %u\n",
+ cmd->hi_addr, cmd->low_addr, cmd->size);
+
+ return cmd;
+}
+
+static inline void tee_free_cmd_buffer(struct tee_init_ring_cmd *cmd)
+{
+ kfree(cmd);
+}
+
+static int tee_init_ring(struct psp_tee_device *tee)
+{
+ int ring_size = MAX_RING_BUFFER_ENTRIES * sizeof(struct tee_ring_cmd);
+ struct tee_init_ring_cmd *cmd;
+ phys_addr_t cmd_buffer;
+ unsigned int reg;
+ int ret;
+
+ BUILD_BUG_ON(sizeof(struct tee_ring_cmd) != 1024);
+
+ ret = tee_alloc_ring(tee, ring_size);
+ if (ret) {
+ dev_err(tee->dev, "tee: ring allocation failed %d\n", ret);
+ return ret;
+ }
+
+ tee->rb_mgr.wptr = 0;
+
+ cmd = tee_alloc_cmd_buffer(tee);
+ if (!cmd) {
+ tee_free_ring(tee);
+ return -ENOMEM;
+ }
+
+ cmd_buffer = __psp_pa((void *)cmd);
+
+ /* Send command buffer details to Trusted OS by writing to
+ * CPU-PSP message registers
+ */
+
+ iowrite32(lower_32_bits(cmd_buffer),
+ tee->io_regs + tee->vdata->cmdbuff_addr_lo_reg);
+ iowrite32(upper_32_bits(cmd_buffer),
+ tee->io_regs + tee->vdata->cmdbuff_addr_hi_reg);
+ iowrite32(TEE_RING_INIT_CMD,
+ tee->io_regs + tee->vdata->cmdresp_reg);
+
+ ret = tee_wait_cmd_poll(tee, TEE_DEFAULT_TIMEOUT, ®);
+ if (ret) {
+ dev_err(tee->dev, "tee: ring init command timed out\n");
+ tee_free_ring(tee);
+ goto free_buf;
+ }
+
+ if (reg & PSP_CMDRESP_ERR_MASK) {
+ dev_err(tee->dev, "tee: ring init command failed (%#010x)\n",
+ reg & PSP_CMDRESP_ERR_MASK);
+ tee_free_ring(tee);
+ ret = -EIO;
+ }
+
+free_buf:
+ tee_free_cmd_buffer(cmd);
+
+ return ret;
+}
+
+static void tee_destroy_ring(struct psp_tee_device *tee)
+{
+ unsigned int reg;
+ int ret;
+
+ if (!tee->rb_mgr.ring_start)
+ return;
+
+ if (psp_dead)
+ goto free_ring;
+
+ iowrite32(TEE_RING_DESTROY_CMD,
+ tee->io_regs + tee->vdata->cmdresp_reg);
+
+ ret = tee_wait_cmd_poll(tee, TEE_DEFAULT_TIMEOUT, ®);
+ if (ret) {
+ dev_err(tee->dev, "tee: ring destroy command timed out\n");
+ } else if (reg & PSP_CMDRESP_ERR_MASK) {
+ dev_err(tee->dev, "tee: ring destroy command failed (%#010x)\n",
+ reg & PSP_CMDRESP_ERR_MASK);
+ }
+
+free_ring:
+ tee_free_ring(tee);
+}
+
+int tee_dev_init(struct psp_device *psp)
+{
+ struct device *dev = psp->dev;
+ struct psp_tee_device *tee;
+ int ret;
+
+ ret = -ENOMEM;
+ tee = devm_kzalloc(dev, sizeof(*tee), GFP_KERNEL);
+ if (!tee)
+ goto e_err;
+
+ psp->tee_data = tee;
+
+ tee->dev = dev;
+ tee->psp = psp;
+
+ tee->io_regs = psp->io_regs;
+
+ tee->vdata = (struct tee_vdata *)psp->vdata->tee;
+ if (!tee->vdata) {
+ ret = -ENODEV;
+ dev_err(dev, "tee: missing driver data\n");
+ goto e_err;
+ }
+
+ ret = tee_init_ring(tee);
+ if (ret) {
+ dev_err(dev, "tee: failed to init ring buffer\n");
+ goto e_err;
+ }
+
+ dev_notice(dev, "tee enabled\n");
+
+ return 0;
+
+e_err:
+ psp->tee_data = NULL;
+
+ dev_notice(dev, "tee initialization failed\n");
+
+ return ret;
+}
+
+void tee_dev_destroy(struct psp_device *psp)
+{
+ struct psp_tee_device *tee = psp->tee_data;
+
+ if (!tee)
+ return;
+
+ tee_destroy_ring(tee);
+}
diff --git a/drivers/crypto/ccp/tee-dev.h b/drivers/crypto/ccp/tee-dev.h
new file mode 100644
index 0000000..b3db0fc
--- /dev/null
+++ b/drivers/crypto/ccp/tee-dev.h
@@ -0,0 +1,109 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright 2019 Advanced Micro Devices, Inc.
+ *
+ * Author: Rijo Thomas <[email protected]>
+ * Author: Devaraj Rangasamy <[email protected]>
+ *
+ */
+
+/* This file describes the TEE communication interface between host and AMD
+ * Secure Processor
+ */
+
+#ifndef __TEE_DEV_H__
+#define __TEE_DEV_H__
+
+#include <linux/device.h>
+#include <linux/mutex.h>
+
+#define TEE_DEFAULT_TIMEOUT 10
+#define MAX_BUFFER_SIZE 992
+
+/**
+ * enum tee_ring_cmd_id - TEE interface commands for ring buffer configuration
+ * @TEE_RING_INIT_CMD: Initialize ring buffer
+ * @TEE_RING_DESTROY_CMD: Destroy ring buffer
+ * @TEE_RING_MAX_CMD: Maximum command id
+ */
+enum tee_ring_cmd_id {
+ TEE_RING_INIT_CMD = 0x00010000,
+ TEE_RING_DESTROY_CMD = 0x00020000,
+ TEE_RING_MAX_CMD = 0x000F0000,
+};
+
+/**
+ * struct tee_init_ring_cmd - Command to init TEE ring buffer
+ * @low_addr: bits [31:0] of the physical address of ring buffer
+ * @hi_addr: bits [63:32] of the physical address of ring buffer
+ * @size: size of ring buffer in bytes
+ */
+struct tee_init_ring_cmd {
+ u32 low_addr;
+ u32 hi_addr;
+ u32 size;
+};
+
+#define MAX_RING_BUFFER_ENTRIES 32
+
+/**
+ * struct ring_buf_manager - Helper structure to manage ring buffer.
+ * @ring_start: starting address of ring buffer
+ * @ring_size: size of ring buffer in bytes
+ * @ring_pa: physical address of ring buffer
+ * @wptr: index to the last written entry in ring buffer
+ */
+struct ring_buf_manager {
+ void *ring_start;
+ u32 ring_size;
+ phys_addr_t ring_pa;
+ u32 wptr;
+};
+
+struct psp_tee_device {
+ struct device *dev;
+ struct psp_device *psp;
+ void __iomem *io_regs;
+ struct tee_vdata *vdata;
+ struct ring_buf_manager rb_mgr;
+};
+
+/**
+ * enum tee_cmd_state - TEE command states for the ring buffer interface
+ * @TEE_CMD_STATE_INIT: initial state of command when sent from host
+ * @TEE_CMD_STATE_PROCESS: command being processed by TEE environment
+ * @TEE_CMD_STATE_COMPLETED: command processing completed
+ */
+enum tee_cmd_state {
+ TEE_CMD_STATE_INIT,
+ TEE_CMD_STATE_PROCESS,
+ TEE_CMD_STATE_COMPLETED,
+};
+
+/**
+ * struct tee_ring_cmd - Structure of the command buffer in TEE ring
+ * @cmd_id: refers to &enum tee_cmd_id. Command id for the ring buffer
+ * interface
+ * @cmd_state: refers to &enum tee_cmd_state
+ * @status: status of TEE command execution
+ * @res0: reserved region
+ * @pdata: private data (currently unused)
+ * @res1: reserved region
+ * @buf: TEE command specific buffer
+ */
+struct tee_ring_cmd {
+ u32 cmd_id;
+ u32 cmd_state;
+ u32 status;
+ u32 res0[1];
+ u64 pdata;
+ u32 res1[2];
+ u8 buf[MAX_BUFFER_SIZE];
+
+ /* Total size: 1024 bytes */
+} __packed;
+
+int tee_dev_init(struct psp_device *psp);
+void tee_dev_destroy(struct psp_device *psp);
+
+#endif /* __TEE_DEV_H__ */
--
1.9.1
The PSP (Platform Security Processor) provides support for key management
commands in Secure Encrypted Virtualization (SEV) mode, along with
software-based Trusted Execution Environment (TEE) to enable third-party
Trusted Applications.
Therefore, introduce psp-dev.c and psp-dev.h files, which can invoke
SEV (or TEE) initialization based on platform feature support.
TEE interface support will be introduced in a later patch.
Cc: Ard Biesheuvel <[email protected]>
Cc: Tom Lendacky <[email protected]>
Cc: Jens Wiklander <[email protected]>
Co-developed-by: Devaraj Rangasamy <[email protected]>
Signed-off-by: Devaraj Rangasamy <[email protected]>
Signed-off-by: Rijo Thomas <[email protected]>
---
drivers/crypto/ccp/Makefile | 3 +-
drivers/crypto/ccp/psp-dev.c | 194 ++++++++++++++++++++++++++++++
drivers/crypto/ccp/psp-dev.h | 52 +++++++++
drivers/crypto/ccp/sev-dev.c | 273 ++++++++++++++++---------------------------
drivers/crypto/ccp/sev-dev.h | 36 +++---
drivers/crypto/ccp/sp-pci.c | 2 +-
6 files changed, 367 insertions(+), 193 deletions(-)
create mode 100644 drivers/crypto/ccp/psp-dev.c
create mode 100644 drivers/crypto/ccp/psp-dev.h
diff --git a/drivers/crypto/ccp/Makefile b/drivers/crypto/ccp/Makefile
index 9dafcf2..3b29ea4 100644
--- a/drivers/crypto/ccp/Makefile
+++ b/drivers/crypto/ccp/Makefile
@@ -8,7 +8,8 @@ ccp-$(CONFIG_CRYPTO_DEV_SP_CCP) += ccp-dev.o \
ccp-dmaengine.o
ccp-$(CONFIG_CRYPTO_DEV_CCP_DEBUGFS) += ccp-debugfs.o
ccp-$(CONFIG_PCI) += sp-pci.o
-ccp-$(CONFIG_CRYPTO_DEV_SP_PSP) += sev-dev.o
+ccp-$(CONFIG_CRYPTO_DEV_SP_PSP) += psp-dev.o \
+ sev-dev.o
obj-$(CONFIG_CRYPTO_DEV_CCP_CRYPTO) += ccp-crypto.o
ccp-crypto-objs := ccp-crypto-main.o \
diff --git a/drivers/crypto/ccp/psp-dev.c b/drivers/crypto/ccp/psp-dev.c
new file mode 100644
index 0000000..2cd7a5e
--- /dev/null
+++ b/drivers/crypto/ccp/psp-dev.c
@@ -0,0 +1,194 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * AMD Platform Security Processor (PSP) interface
+ *
+ * Copyright (C) 2016,2019 Advanced Micro Devices, Inc.
+ *
+ * Author: Brijesh Singh <[email protected]>
+ */
+
+#include <linux/kernel.h>
+#include <linux/irqreturn.h>
+
+#include "sp-dev.h"
+#include "psp-dev.h"
+#include "sev-dev.h"
+
+struct psp_device *psp_master;
+
+static struct psp_device *psp_alloc_struct(struct sp_device *sp)
+{
+ struct device *dev = sp->dev;
+ struct psp_device *psp;
+
+ psp = devm_kzalloc(dev, sizeof(*psp), GFP_KERNEL);
+ if (!psp)
+ return NULL;
+
+ psp->dev = dev;
+ psp->sp = sp;
+
+ snprintf(psp->name, sizeof(psp->name), "psp-%u", sp->ord);
+
+ return psp;
+}
+
+static irqreturn_t psp_irq_handler(int irq, void *data)
+{
+ struct psp_device *psp = data;
+ unsigned int status;
+
+ /* Read the interrupt status: */
+ status = ioread32(psp->io_regs + psp->vdata->intsts_reg);
+
+ /* invoke subdevice interrupt handlers */
+ if (status) {
+ if (psp->sev_irq_handler)
+ psp->sev_irq_handler(irq, psp->sev_irq_data, status);
+ }
+
+ /* Clear the interrupt status by writing the same value we read. */
+ iowrite32(status, psp->io_regs + psp->vdata->intsts_reg);
+
+ return IRQ_HANDLED;
+}
+
+static int psp_check_sev_support(struct psp_device *psp)
+{
+ unsigned int val = ioread32(psp->io_regs + psp->vdata->feature_reg);
+
+ /*
+ * Check for a access to the registers. If this read returns
+ * 0xffffffff, it's likely that the system is running a broken
+ * BIOS which disallows access to the device. Stop here and
+ * fail the PSP initialization (but not the load, as the CCP
+ * could get properly initialized).
+ */
+ if (val == 0xffffffff) {
+ dev_notice(psp->dev, "psp: unable to access the device: you might be running a broken BIOS.\n");
+ return -ENODEV;
+ }
+
+ if (!(val & 1)) {
+ /* Device does not support the SEV feature */
+ dev_dbg(psp->dev, "psp does not support SEV\n");
+ return -ENODEV;
+ }
+
+ return 0;
+}
+
+int psp_dev_init(struct sp_device *sp)
+{
+ struct device *dev = sp->dev;
+ struct psp_device *psp;
+ int ret;
+
+ ret = -ENOMEM;
+ psp = psp_alloc_struct(sp);
+ if (!psp)
+ goto e_err;
+
+ sp->psp_data = psp;
+
+ psp->vdata = (struct psp_vdata *)sp->dev_vdata->psp_vdata;
+ if (!psp->vdata) {
+ ret = -ENODEV;
+ dev_err(dev, "missing driver data\n");
+ goto e_err;
+ }
+
+ psp->io_regs = sp->io_map;
+
+ ret = psp_check_sev_support(psp);
+ if (ret)
+ goto e_disable;
+
+ /* Disable and clear interrupts until ready */
+ iowrite32(0, psp->io_regs + psp->vdata->inten_reg);
+ iowrite32(-1, psp->io_regs + psp->vdata->intsts_reg);
+
+ /* Request an irq */
+ ret = sp_request_psp_irq(psp->sp, psp_irq_handler, psp->name, psp);
+ if (ret) {
+ dev_err(dev, "psp: unable to allocate an IRQ\n");
+ goto e_err;
+ }
+
+ ret = sev_dev_init(psp);
+ if (ret)
+ goto e_irq;
+
+ if (sp->set_psp_master_device)
+ sp->set_psp_master_device(sp);
+
+ /* Enable interrupt */
+ iowrite32(-1, psp->io_regs + psp->vdata->inten_reg);
+
+ dev_notice(dev, "psp enabled\n");
+
+ return 0;
+
+e_irq:
+ sp_free_psp_irq(psp->sp, psp);
+e_err:
+ sp->psp_data = NULL;
+
+ dev_notice(dev, "psp initialization failed\n");
+
+ return ret;
+
+e_disable:
+ sp->psp_data = NULL;
+
+ return ret;
+}
+
+void psp_dev_destroy(struct sp_device *sp)
+{
+ struct psp_device *psp = sp->psp_data;
+
+ if (!psp)
+ return;
+
+ sev_dev_destroy(psp);
+
+ sp_free_psp_irq(sp, psp);
+}
+
+void psp_set_sev_irq_handler(struct psp_device *psp, psp_irq_handler_t handler,
+ void *data)
+{
+ psp->sev_irq_data = data;
+ psp->sev_irq_handler = handler;
+}
+
+void psp_clear_sev_irq_handler(struct psp_device *psp)
+{
+ psp_set_sev_irq_handler(psp, NULL, NULL);
+}
+
+struct psp_device *psp_get_master_device(void)
+{
+ struct sp_device *sp = sp_get_psp_master_device();
+
+ return sp ? sp->psp_data : NULL;
+}
+
+void psp_pci_init(void)
+{
+ psp_master = psp_get_master_device();
+
+ if (!psp_master)
+ return;
+
+ sev_pci_init();
+}
+
+void psp_pci_exit(void)
+{
+ if (!psp_master)
+ return;
+
+ sev_pci_exit();
+}
diff --git a/drivers/crypto/ccp/psp-dev.h b/drivers/crypto/ccp/psp-dev.h
new file mode 100644
index 0000000..7c014ac
--- /dev/null
+++ b/drivers/crypto/ccp/psp-dev.h
@@ -0,0 +1,52 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * AMD Platform Security Processor (PSP) interface driver
+ *
+ * Copyright (C) 2017-2019 Advanced Micro Devices, Inc.
+ *
+ * Author: Brijesh Singh <[email protected]>
+ */
+
+#ifndef __PSP_DEV_H__
+#define __PSP_DEV_H__
+
+#include <linux/device.h>
+#include <linux/list.h>
+#include <linux/bits.h>
+#include <linux/interrupt.h>
+
+#include "sp-dev.h"
+
+#define PSP_CMDRESP_RESP BIT(31)
+#define PSP_CMDRESP_ERR_MASK 0xffff
+
+#define MAX_PSP_NAME_LEN 16
+
+extern struct psp_device *psp_master;
+
+typedef void (*psp_irq_handler_t)(int, void *, unsigned int);
+
+struct psp_device {
+ struct list_head entry;
+
+ struct psp_vdata *vdata;
+ char name[MAX_PSP_NAME_LEN];
+
+ struct device *dev;
+ struct sp_device *sp;
+
+ void __iomem *io_regs;
+
+ psp_irq_handler_t sev_irq_handler;
+ void *sev_irq_data;
+
+ void *sev_data;
+};
+
+void psp_set_sev_irq_handler(struct psp_device *psp, psp_irq_handler_t handler,
+ void *data);
+void psp_clear_sev_irq_handler(struct psp_device *psp);
+
+struct psp_device *psp_get_master_device(void);
+
+#endif /* __PSP_DEV_H */
diff --git a/drivers/crypto/ccp/sev-dev.c b/drivers/crypto/ccp/sev-dev.c
index 9a8c523..a608b52 100644
--- a/drivers/crypto/ccp/sev-dev.c
+++ b/drivers/crypto/ccp/sev-dev.c
@@ -21,7 +21,7 @@
#include <linux/ccp.h>
#include <linux/firmware.h>
-#include "sp-dev.h"
+#include "psp-dev.h"
#include "sev-dev.h"
#define DEVICE_NAME "sev"
@@ -30,7 +30,6 @@
static DEFINE_MUTEX(sev_cmd_mutex);
static struct sev_misc_dev *misc_dev;
-static struct psp_device *psp_master;
static int psp_cmd_timeout = 100;
module_param(psp_cmd_timeout, int, 0644);
@@ -45,68 +44,45 @@
static inline bool sev_version_greater_or_equal(u8 maj, u8 min)
{
- if (psp_master->api_major > maj)
- return true;
- if (psp_master->api_major == maj && psp_master->api_minor >= min)
- return true;
- return false;
-}
-
-static struct psp_device *psp_alloc_struct(struct sp_device *sp)
-{
- struct device *dev = sp->dev;
- struct psp_device *psp;
+ struct sev_device *sev = psp_master->sev_data;
- psp = devm_kzalloc(dev, sizeof(*psp), GFP_KERNEL);
- if (!psp)
- return NULL;
-
- psp->dev = dev;
- psp->sp = sp;
+ if (sev->api_major > maj)
+ return true;
- snprintf(psp->name, sizeof(psp->name), "psp-%u", sp->ord);
+ if (sev->api_major == maj && sev->api_minor >= min)
+ return true;
- return psp;
+ return false;
}
-static irqreturn_t psp_irq_handler(int irq, void *data)
+static void sev_irq_handler(int irq, void *data, unsigned int status)
{
- struct psp_device *psp = data;
- unsigned int status;
+ struct sev_device *sev = data;
int reg;
- /* Read the interrupt status: */
- status = ioread32(psp->io_regs + psp->vdata->intsts_reg);
-
/* Check if it is command completion: */
- if (!(status & PSP_CMD_COMPLETE))
- goto done;
+ if (!(status & SEV_CMD_COMPLETE))
+ return;
/* Check if it is SEV command completion: */
- reg = ioread32(psp->io_regs + psp->vdata->cmdresp_reg);
+ reg = ioread32(sev->io_regs + sev->psp->vdata->cmdresp_reg);
if (reg & PSP_CMDRESP_RESP) {
- psp->sev_int_rcvd = 1;
- wake_up(&psp->sev_int_queue);
+ sev->int_rcvd = 1;
+ wake_up(&sev->int_queue);
}
-
-done:
- /* Clear the interrupt status by writing the same value we read. */
- iowrite32(status, psp->io_regs + psp->vdata->intsts_reg);
-
- return IRQ_HANDLED;
}
-static int sev_wait_cmd_ioc(struct psp_device *psp,
+static int sev_wait_cmd_ioc(struct sev_device *sev,
unsigned int *reg, unsigned int timeout)
{
int ret;
- ret = wait_event_timeout(psp->sev_int_queue,
- psp->sev_int_rcvd, timeout * HZ);
+ ret = wait_event_timeout(sev->int_queue,
+ sev->int_rcvd, timeout * HZ);
if (!ret)
return -ETIMEDOUT;
- *reg = ioread32(psp->io_regs + psp->vdata->cmdresp_reg);
+ *reg = ioread32(sev->io_regs + sev->psp->vdata->cmdresp_reg);
return 0;
}
@@ -150,42 +126,45 @@ static int sev_cmd_buffer_len(int cmd)
static int __sev_do_cmd_locked(int cmd, void *data, int *psp_ret)
{
struct psp_device *psp = psp_master;
+ struct sev_device *sev;
unsigned int phys_lsb, phys_msb;
unsigned int reg, ret = 0;
- if (!psp)
+ if (!psp || !psp->sev_data)
return -ENODEV;
if (psp_dead)
return -EBUSY;
+ sev = psp->sev_data;
+
/* Get the physical address of the command buffer */
phys_lsb = data ? lower_32_bits(__psp_pa(data)) : 0;
phys_msb = data ? upper_32_bits(__psp_pa(data)) : 0;
- dev_dbg(psp->dev, "sev command id %#x buffer 0x%08x%08x timeout %us\n",
+ dev_dbg(sev->dev, "sev command id %#x buffer 0x%08x%08x timeout %us\n",
cmd, phys_msb, phys_lsb, psp_timeout);
print_hex_dump_debug("(in): ", DUMP_PREFIX_OFFSET, 16, 2, data,
sev_cmd_buffer_len(cmd), false);
- iowrite32(phys_lsb, psp->io_regs + psp->vdata->cmdbuff_addr_lo_reg);
- iowrite32(phys_msb, psp->io_regs + psp->vdata->cmdbuff_addr_hi_reg);
+ iowrite32(phys_lsb, sev->io_regs + psp->vdata->cmdbuff_addr_lo_reg);
+ iowrite32(phys_msb, sev->io_regs + psp->vdata->cmdbuff_addr_hi_reg);
- psp->sev_int_rcvd = 0;
+ sev->int_rcvd = 0;
reg = cmd;
- reg <<= PSP_CMDRESP_CMD_SHIFT;
- reg |= PSP_CMDRESP_IOC;
- iowrite32(reg, psp->io_regs + psp->vdata->cmdresp_reg);
+ reg <<= SEV_CMDRESP_CMD_SHIFT;
+ reg |= SEV_CMDRESP_IOC;
+ iowrite32(reg, sev->io_regs + psp->vdata->cmdresp_reg);
/* wait for command completion */
- ret = sev_wait_cmd_ioc(psp, ®, psp_timeout);
+ ret = sev_wait_cmd_ioc(sev, ®, psp_timeout);
if (ret) {
if (psp_ret)
*psp_ret = 0;
- dev_err(psp->dev, "sev command %#x timed out, disabling PSP \n", cmd);
+ dev_err(sev->dev, "sev command %#x timed out, disabling PSP\n", cmd);
psp_dead = true;
return ret;
@@ -197,7 +176,7 @@ static int __sev_do_cmd_locked(int cmd, void *data, int *psp_ret)
*psp_ret = reg & PSP_CMDRESP_ERR_MASK;
if (reg & PSP_CMDRESP_ERR_MASK) {
- dev_dbg(psp->dev, "sev command %#x failed (%#010x)\n",
+ dev_dbg(sev->dev, "sev command %#x failed (%#010x)\n",
cmd, reg & PSP_CMDRESP_ERR_MASK);
ret = -EIO;
}
@@ -222,20 +201,23 @@ static int sev_do_cmd(int cmd, void *data, int *psp_ret)
static int __sev_platform_init_locked(int *error)
{
struct psp_device *psp = psp_master;
+ struct sev_device *sev;
int rc = 0;
- if (!psp)
+ if (!psp || !psp->sev_data)
return -ENODEV;
- if (psp->sev_state == SEV_STATE_INIT)
+ sev = psp->sev_data;
+
+ if (sev->state == SEV_STATE_INIT)
return 0;
- rc = __sev_do_cmd_locked(SEV_CMD_INIT, &psp->init_cmd_buf, error);
+ rc = __sev_do_cmd_locked(SEV_CMD_INIT, &sev->init_cmd_buf, error);
if (rc)
return rc;
- psp->sev_state = SEV_STATE_INIT;
- dev_dbg(psp->dev, "SEV firmware initialized\n");
+ sev->state = SEV_STATE_INIT;
+ dev_dbg(sev->dev, "SEV firmware initialized\n");
return rc;
}
@@ -254,14 +236,15 @@ int sev_platform_init(int *error)
static int __sev_platform_shutdown_locked(int *error)
{
+ struct sev_device *sev = psp_master->sev_data;
int ret;
ret = __sev_do_cmd_locked(SEV_CMD_SHUTDOWN, NULL, error);
if (ret)
return ret;
- psp_master->sev_state = SEV_STATE_UNINIT;
- dev_dbg(psp_master->dev, "SEV firmware shutdown\n");
+ sev->state = SEV_STATE_UNINIT;
+ dev_dbg(sev->dev, "SEV firmware shutdown\n");
return ret;
}
@@ -279,14 +262,15 @@ static int sev_platform_shutdown(int *error)
static int sev_get_platform_state(int *state, int *error)
{
+ struct sev_device *sev = psp_master->sev_data;
int rc;
rc = __sev_do_cmd_locked(SEV_CMD_PLATFORM_STATUS,
- &psp_master->status_cmd_buf, error);
+ &sev->status_cmd_buf, error);
if (rc)
return rc;
- *state = psp_master->status_cmd_buf.state;
+ *state = sev->status_cmd_buf.state;
return rc;
}
@@ -324,7 +308,8 @@ static int sev_ioctl_do_reset(struct sev_issue_cmd *argp)
static int sev_ioctl_do_platform_status(struct sev_issue_cmd *argp)
{
- struct sev_user_data_status *data = &psp_master->status_cmd_buf;
+ struct sev_device *sev = psp_master->sev_data;
+ struct sev_user_data_status *data = &sev->status_cmd_buf;
int ret;
ret = __sev_do_cmd_locked(SEV_CMD_PLATFORM_STATUS, data, &argp->error);
@@ -339,12 +324,13 @@ static int sev_ioctl_do_platform_status(struct sev_issue_cmd *argp)
static int sev_ioctl_do_pek_pdh_gen(int cmd, struct sev_issue_cmd *argp)
{
+ struct sev_device *sev = psp_master->sev_data;
int rc;
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
- if (psp_master->sev_state == SEV_STATE_UNINIT) {
+ if (sev->state == SEV_STATE_UNINIT) {
rc = __sev_platform_init_locked(&argp->error);
if (rc)
return rc;
@@ -355,6 +341,7 @@ static int sev_ioctl_do_pek_pdh_gen(int cmd, struct sev_issue_cmd *argp)
static int sev_ioctl_do_pek_csr(struct sev_issue_cmd *argp)
{
+ struct sev_device *sev = psp_master->sev_data;
struct sev_user_data_pek_csr input;
struct sev_data_pek_csr *data;
void *blob = NULL;
@@ -391,7 +378,7 @@ static int sev_ioctl_do_pek_csr(struct sev_issue_cmd *argp)
data->len = input.length;
cmd:
- if (psp_master->sev_state == SEV_STATE_UNINIT) {
+ if (sev->state == SEV_STATE_UNINIT) {
ret = __sev_platform_init_locked(&argp->error);
if (ret)
goto e_free_blob;
@@ -434,21 +421,22 @@ void *psp_copy_user_blob(u64 __user uaddr, u32 len)
static int sev_get_api_version(void)
{
+ struct sev_device *sev = psp_master->sev_data;
struct sev_user_data_status *status;
int error = 0, ret;
- status = &psp_master->status_cmd_buf;
+ status = &sev->status_cmd_buf;
ret = sev_platform_status(status, &error);
if (ret) {
- dev_err(psp_master->dev,
+ dev_err(sev->dev,
"SEV: failed to get status. Error: %#x\n", error);
return 1;
}
- psp_master->api_major = status->api_major;
- psp_master->api_minor = status->api_minor;
- psp_master->build = status->build;
- psp_master->sev_state = status->state;
+ sev->api_major = status->api_major;
+ sev->api_minor = status->api_minor;
+ sev->build = status->build;
+ sev->state = status->state;
return 0;
}
@@ -544,6 +532,7 @@ static int sev_update_firmware(struct device *dev)
static int sev_ioctl_do_pek_import(struct sev_issue_cmd *argp)
{
+ struct sev_device *sev = psp_master->sev_data;
struct sev_user_data_pek_cert_import input;
struct sev_data_pek_cert_import *data;
void *pek_blob, *oca_blob;
@@ -580,7 +569,7 @@ static int sev_ioctl_do_pek_import(struct sev_issue_cmd *argp)
data->oca_cert_len = input.oca_cert_len;
/* If platform is not in INIT state then transition it to INIT */
- if (psp_master->sev_state != SEV_STATE_INIT) {
+ if (sev->state != SEV_STATE_INIT) {
ret = __sev_platform_init_locked(&argp->error);
if (ret)
goto e_free_oca;
@@ -702,13 +691,14 @@ static int sev_ioctl_do_get_id(struct sev_issue_cmd *argp)
static int sev_ioctl_do_pdh_export(struct sev_issue_cmd *argp)
{
+ struct sev_device *sev = psp_master->sev_data;
struct sev_user_data_pdh_cert_export input;
void *pdh_blob = NULL, *cert_blob = NULL;
struct sev_data_pdh_cert_export *data;
int ret;
/* If platform is not in INIT state then transition it to INIT. */
- if (psp_master->sev_state != SEV_STATE_INIT) {
+ if (sev->state != SEV_STATE_INIT) {
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
@@ -803,7 +793,7 @@ static long sev_ioctl(struct file *file, unsigned int ioctl, unsigned long arg)
struct sev_issue_cmd input;
int ret = -EFAULT;
- if (!psp_master)
+ if (!psp_master || !psp_master->sev_data)
return -ENODEV;
if (ioctl != SEV_ISSUE_CMD)
@@ -902,9 +892,9 @@ static void sev_exit(struct kref *ref)
misc_deregister(&misc_dev->misc);
}
-static int sev_misc_init(struct psp_device *psp)
+static int sev_misc_init(struct sev_device *sev)
{
- struct device *dev = psp->dev;
+ struct device *dev = sev->dev;
int ret;
/*
@@ -935,115 +925,61 @@ static int sev_misc_init(struct psp_device *psp)
kref_get(&misc_dev->refcount);
}
- init_waitqueue_head(&psp->sev_int_queue);
- psp->sev_misc = misc_dev;
+ init_waitqueue_head(&sev->int_queue);
+ sev->misc = misc_dev;
dev_dbg(dev, "registered SEV device\n");
return 0;
}
-static int psp_check_sev_support(struct psp_device *psp)
-{
- unsigned int val = ioread32(psp->io_regs + psp->vdata->feature_reg);
-
- /*
- * Check for a access to the registers. If this read returns
- * 0xffffffff, it's likely that the system is running a broken
- * BIOS which disallows access to the device. Stop here and
- * fail the PSP initialization (but not the load, as the CCP
- * could get properly initialized).
- */
- if (val == 0xffffffff) {
- dev_notice(psp->dev, "psp: unable to access the device: you might be running a broken BIOS.\n");
- return -ENODEV;
- }
-
- if (!(val & 1)) {
- /* Device does not support the SEV feature */
- dev_dbg(psp->dev, "psp does not support SEV\n");
- return -ENODEV;
- }
-
- return 0;
-}
-
-int psp_dev_init(struct sp_device *sp)
+int sev_dev_init(struct psp_device *psp)
{
- struct device *dev = sp->dev;
- struct psp_device *psp;
- int ret;
+ struct device *dev = psp->dev;
+ struct sev_device *sev;
+ int ret = -ENOMEM;
- ret = -ENOMEM;
- psp = psp_alloc_struct(sp);
- if (!psp)
+ sev = devm_kzalloc(dev, sizeof(*sev), GFP_KERNEL);
+ if (!sev)
goto e_err;
- sp->psp_data = psp;
+ psp->sev_data = sev;
- psp->vdata = (struct psp_vdata *)sp->dev_vdata->psp_vdata;
- if (!psp->vdata) {
- ret = -ENODEV;
- dev_err(dev, "missing driver data\n");
- goto e_err;
- }
+ sev->dev = dev;
+ sev->psp = psp;
- psp->io_regs = sp->io_map;
+ sev->io_regs = psp->io_regs;
- ret = psp_check_sev_support(psp);
- if (ret)
- goto e_disable;
+ psp_set_sev_irq_handler(psp, sev_irq_handler, sev);
- /* Disable and clear interrupts until ready */
- iowrite32(0, psp->io_regs + psp->vdata->inten_reg);
- iowrite32(-1, psp->io_regs + psp->vdata->intsts_reg);
-
- /* Request an irq */
- ret = sp_request_psp_irq(psp->sp, psp_irq_handler, psp->name, psp);
- if (ret) {
- dev_err(dev, "psp: unable to allocate an IRQ\n");
- goto e_err;
- }
-
- ret = sev_misc_init(psp);
+ ret = sev_misc_init(sev);
if (ret)
goto e_irq;
- if (sp->set_psp_master_device)
- sp->set_psp_master_device(sp);
-
- /* Enable interrupt */
- iowrite32(-1, psp->io_regs + psp->vdata->inten_reg);
-
- dev_notice(dev, "psp enabled\n");
+ dev_notice(dev, "sev enabled\n");
return 0;
e_irq:
- sp_free_psp_irq(psp->sp, psp);
+ psp_clear_sev_irq_handler(psp);
e_err:
- sp->psp_data = NULL;
+ psp->sev_data = NULL;
- dev_notice(dev, "psp initialization failed\n");
-
- return ret;
-
-e_disable:
- sp->psp_data = NULL;
+ dev_notice(dev, "sev initialization failed\n");
return ret;
}
-void psp_dev_destroy(struct sp_device *sp)
+void sev_dev_destroy(struct psp_device *psp)
{
- struct psp_device *psp = sp->psp_data;
+ struct sev_device *sev = psp->sev_data;
- if (!psp)
+ if (!sev)
return;
- if (psp->sev_misc)
+ if (sev->misc)
kref_put(&misc_dev->refcount, sev_exit);
- sp_free_psp_irq(sp, psp);
+ psp_clear_sev_irq_handler(psp);
}
int sev_issue_cmd_external_user(struct file *filep, unsigned int cmd,
@@ -1052,21 +988,18 @@ int sev_issue_cmd_external_user(struct file *filep, unsigned int cmd,
if (!filep || filep->f_op != &sev_fops)
return -EBADF;
- return sev_do_cmd(cmd, data, error);
+ return sev_do_cmd(cmd, data, error);
}
EXPORT_SYMBOL_GPL(sev_issue_cmd_external_user);
-void psp_pci_init(void)
+void sev_pci_init(void)
{
- struct sp_device *sp;
+ struct sev_device *sev = psp_master->sev_data;
int error, rc;
- sp = sp_get_psp_master_device();
- if (!sp)
+ if (!sev)
return;
- psp_master = sp->psp_data;
-
psp_timeout = psp_probe_timeout;
if (sev_get_api_version())
@@ -1082,13 +1015,13 @@ void psp_pci_init(void)
* firmware in INIT or WORKING state.
*/
- if (psp_master->sev_state != SEV_STATE_UNINIT) {
+ if (sev->state != SEV_STATE_UNINIT) {
sev_platform_shutdown(NULL);
- psp_master->sev_state = SEV_STATE_UNINIT;
+ sev->state = SEV_STATE_UNINIT;
}
if (sev_version_greater_or_equal(0, 15) &&
- sev_update_firmware(psp_master->dev) == 0)
+ sev_update_firmware(sev->dev) == 0)
sev_get_api_version();
/* Initialize the platform */
@@ -1101,27 +1034,27 @@ void psp_pci_init(void)
* failed and persistent state has been erased.
* Retrying INIT command here should succeed.
*/
- dev_dbg(sp->dev, "SEV: retrying INIT command");
+ dev_dbg(sev->dev, "SEV: retrying INIT command");
rc = sev_platform_init(&error);
}
if (rc) {
- dev_err(sp->dev, "SEV: failed to INIT error %#x\n", error);
+ dev_err(sev->dev, "SEV: failed to INIT error %#x\n", error);
return;
}
- dev_info(sp->dev, "SEV API:%d.%d build:%d\n", psp_master->api_major,
- psp_master->api_minor, psp_master->build);
+ dev_info(sev->dev, "SEV API:%d.%d build:%d\n", sev->api_major,
+ sev->api_minor, sev->build);
return;
err:
- psp_master = NULL;
+ psp_master->sev_data = NULL;
}
-void psp_pci_exit(void)
+void sev_pci_exit(void)
{
- if (!psp_master)
+ if (!psp_master->sev_data)
return;
sev_platform_shutdown(NULL);
diff --git a/drivers/crypto/ccp/sev-dev.h b/drivers/crypto/ccp/sev-dev.h
index e861647..3d84ac3 100644
--- a/drivers/crypto/ccp/sev-dev.h
+++ b/drivers/crypto/ccp/sev-dev.h
@@ -25,37 +25,25 @@
#include <linux/miscdevice.h>
#include <linux/capability.h>
-#include "sp-dev.h"
-
-#define PSP_CMD_COMPLETE BIT(1)
-
-#define PSP_CMDRESP_CMD_SHIFT 16
-#define PSP_CMDRESP_IOC BIT(0)
-#define PSP_CMDRESP_RESP BIT(31)
-#define PSP_CMDRESP_ERR_MASK 0xffff
-
-#define MAX_PSP_NAME_LEN 16
+#define SEV_CMD_COMPLETE BIT(1)
+#define SEV_CMDRESP_CMD_SHIFT 16
+#define SEV_CMDRESP_IOC BIT(0)
struct sev_misc_dev {
struct kref refcount;
struct miscdevice misc;
};
-struct psp_device {
- struct list_head entry;
-
- struct psp_vdata *vdata;
- char name[MAX_PSP_NAME_LEN];
-
+struct sev_device {
struct device *dev;
- struct sp_device *sp;
+ struct psp_device *psp;
void __iomem *io_regs;
- int sev_state;
- unsigned int sev_int_rcvd;
- wait_queue_head_t sev_int_queue;
- struct sev_misc_dev *sev_misc;
+ int state;
+ unsigned int int_rcvd;
+ wait_queue_head_t int_queue;
+ struct sev_misc_dev *misc;
struct sev_user_data_status status_cmd_buf;
struct sev_data_init init_cmd_buf;
@@ -64,4 +52,10 @@ struct psp_device {
u8 build;
};
+int sev_dev_init(struct psp_device *psp);
+void sev_dev_destroy(struct psp_device *psp);
+
+void sev_pci_init(void);
+void sev_pci_exit(void);
+
#endif /* __SEV_DEV_H */
diff --git a/drivers/crypto/ccp/sp-pci.c b/drivers/crypto/ccp/sp-pci.c
index 473cf14..b29d2e6 100644
--- a/drivers/crypto/ccp/sp-pci.c
+++ b/drivers/crypto/ccp/sp-pci.c
@@ -22,7 +22,7 @@
#include <linux/ccp.h>
#include "ccp-dev.h"
-#include "sev-dev.h"
+#include "psp-dev.h"
#define MSIX_VECTORS 2
--
1.9.1
This is a preliminary patch for creating a generic PSP device driver
file, which will have support for both SEV and TEE (Trusted Execution
Environment) interface.
This patch does not introduce any new functionality, but simply renames
psp-dev.c and psp-dev.h files to sev-dev.c and sev-dev.h files
respectively.
Cc: Ard Biesheuvel <[email protected]>
Cc: Tom Lendacky <[email protected]>
Cc: Jens Wiklander <[email protected]>
Co-developed-by: Devaraj Rangasamy <[email protected]>
Signed-off-by: Devaraj Rangasamy <[email protected]>
Signed-off-by: Rijo Thomas <[email protected]>
---
drivers/crypto/ccp/Makefile | 2 +-
drivers/crypto/ccp/{psp-dev.c => sev-dev.c} | 6 +++---
drivers/crypto/ccp/{psp-dev.h => sev-dev.h} | 8 ++++----
drivers/crypto/ccp/sp-pci.c | 2 +-
4 files changed, 9 insertions(+), 9 deletions(-)
rename drivers/crypto/ccp/{psp-dev.c => sev-dev.c} (99%)
rename drivers/crypto/ccp/{psp-dev.h => sev-dev.h} (90%)
diff --git a/drivers/crypto/ccp/Makefile b/drivers/crypto/ccp/Makefile
index 6b86f1e..9dafcf2 100644
--- a/drivers/crypto/ccp/Makefile
+++ b/drivers/crypto/ccp/Makefile
@@ -8,7 +8,7 @@ ccp-$(CONFIG_CRYPTO_DEV_SP_CCP) += ccp-dev.o \
ccp-dmaengine.o
ccp-$(CONFIG_CRYPTO_DEV_CCP_DEBUGFS) += ccp-debugfs.o
ccp-$(CONFIG_PCI) += sp-pci.o
-ccp-$(CONFIG_CRYPTO_DEV_SP_PSP) += psp-dev.o
+ccp-$(CONFIG_CRYPTO_DEV_SP_PSP) += sev-dev.o
obj-$(CONFIG_CRYPTO_DEV_CCP_CRYPTO) += ccp-crypto.o
ccp-crypto-objs := ccp-crypto-main.o \
diff --git a/drivers/crypto/ccp/psp-dev.c b/drivers/crypto/ccp/sev-dev.c
similarity index 99%
rename from drivers/crypto/ccp/psp-dev.c
rename to drivers/crypto/ccp/sev-dev.c
index 5ff842c..9a8c523 100644
--- a/drivers/crypto/ccp/psp-dev.c
+++ b/drivers/crypto/ccp/sev-dev.c
@@ -1,8 +1,8 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
- * AMD Platform Security Processor (PSP) interface
+ * AMD Secure Encrypted Virtualization (SEV) interface
*
- * Copyright (C) 2016,2018 Advanced Micro Devices, Inc.
+ * Copyright (C) 2016,2019 Advanced Micro Devices, Inc.
*
* Author: Brijesh Singh <[email protected]>
*/
@@ -22,7 +22,7 @@
#include <linux/firmware.h>
#include "sp-dev.h"
-#include "psp-dev.h"
+#include "sev-dev.h"
#define DEVICE_NAME "sev"
#define SEV_FW_FILE "amd/sev.fw"
diff --git a/drivers/crypto/ccp/psp-dev.h b/drivers/crypto/ccp/sev-dev.h
similarity index 90%
rename from drivers/crypto/ccp/psp-dev.h
rename to drivers/crypto/ccp/sev-dev.h
index dd516b3..e861647 100644
--- a/drivers/crypto/ccp/psp-dev.h
+++ b/drivers/crypto/ccp/sev-dev.h
@@ -2,13 +2,13 @@
/*
* AMD Platform Security Processor (PSP) interface driver
*
- * Copyright (C) 2017-2018 Advanced Micro Devices, Inc.
+ * Copyright (C) 2017-2019 Advanced Micro Devices, Inc.
*
* Author: Brijesh Singh <[email protected]>
*/
-#ifndef __PSP_DEV_H__
-#define __PSP_DEV_H__
+#ifndef __SEV_DEV_H__
+#define __SEV_DEV_H__
#include <linux/device.h>
#include <linux/spinlock.h>
@@ -64,4 +64,4 @@ struct psp_device {
u8 build;
};
-#endif /* __PSP_DEV_H */
+#endif /* __SEV_DEV_H */
diff --git a/drivers/crypto/ccp/sp-pci.c b/drivers/crypto/ccp/sp-pci.c
index b29d2e6..473cf14 100644
--- a/drivers/crypto/ccp/sp-pci.c
+++ b/drivers/crypto/ccp/sp-pci.c
@@ -22,7 +22,7 @@
#include <linux/ccp.h>
#include "ccp-dev.h"
-#include "psp-dev.h"
+#include "sev-dev.h"
#define MSIX_VECTORS 2
--
1.9.1
Extend the functionality of AMD Secure Processor (SP) driver by
providing an in-kernel API to submit commands to TEE ring buffer for
processing by Trusted OS running on AMD Secure Processor.
Following TEE commands are supported by Trusted OS:
* TEE_CMD_ID_LOAD_TA : Load Trusted Application (TA) binary into
TEE environment
* TEE_CMD_ID_UNLOAD_TA : Unload TA binary from TEE environment
* TEE_CMD_ID_OPEN_SESSION : Open session with loaded TA
* TEE_CMD_ID_CLOSE_SESSION : Close session with loaded TA
* TEE_CMD_ID_INVOKE_CMD : Invoke a command with loaded TA
* TEE_CMD_ID_MAP_SHARED_MEM : Map shared memory
* TEE_CMD_ID_UNMAP_SHARED_MEM : Unmap shared memory
Linux AMD-TEE driver will use this API to submit command buffers
for processing in Trusted Execution Environment. The AMD-TEE driver
shall be introduced in a separate patch.
Cc: Jens Wiklander <[email protected]>
Cc: Tom Lendacky <[email protected]>
Cc: Ard Biesheuvel <[email protected]>
Co-developed-by: Devaraj Rangasamy <[email protected]>
Signed-off-by: Devaraj Rangasamy <[email protected]>
Signed-off-by: Rijo Thomas <[email protected]>
---
drivers/crypto/ccp/tee-dev.c | 126 +++++++++++++++++++++++++++++++++++++++++++
drivers/crypto/ccp/tee-dev.h | 1 +
include/linux/psp-tee.h | 73 +++++++++++++++++++++++++
3 files changed, 200 insertions(+)
create mode 100644 include/linux/psp-tee.h
diff --git a/drivers/crypto/ccp/tee-dev.c b/drivers/crypto/ccp/tee-dev.c
index ccbc2ce..555c8a7 100644
--- a/drivers/crypto/ccp/tee-dev.c
+++ b/drivers/crypto/ccp/tee-dev.c
@@ -14,6 +14,7 @@
#include <linux/slab.h>
#include <linux/gfp.h>
#include <linux/psp-sev.h>
+#include <linux/psp-tee.h>
#include "psp-dev.h"
#include "tee-dev.h"
@@ -38,6 +39,7 @@ static int tee_alloc_ring(struct psp_tee_device *tee, int ring_size)
rb_mgr->ring_start = start_addr;
rb_mgr->ring_size = ring_size;
rb_mgr->ring_pa = __psp_pa(start_addr);
+ mutex_init(&rb_mgr->mutex);
return 0;
}
@@ -55,6 +57,7 @@ static void tee_free_ring(struct psp_tee_device *tee)
rb_mgr->ring_start = NULL;
rb_mgr->ring_size = 0;
rb_mgr->ring_pa = 0;
+ mutex_destroy(&rb_mgr->mutex);
}
static int tee_wait_cmd_poll(struct psp_tee_device *tee, unsigned int timeout,
@@ -236,3 +239,126 @@ void tee_dev_destroy(struct psp_device *psp)
tee_destroy_ring(tee);
}
+
+static int tee_submit_cmd(struct psp_tee_device *tee, enum tee_cmd_id cmd_id,
+ void *buf, size_t len, struct tee_ring_cmd **resp)
+{
+ struct tee_ring_cmd *cmd;
+ u32 rptr, wptr;
+ int nloop = 1000, ret = 0;
+
+ *resp = NULL;
+
+ mutex_lock(&tee->rb_mgr.mutex);
+
+ wptr = tee->rb_mgr.wptr;
+
+ /* Check if ring buffer is full */
+ do {
+ rptr = ioread32(tee->io_regs + tee->vdata->ring_rptr_reg);
+
+ if (!(wptr + sizeof(struct tee_ring_cmd) == rptr))
+ break;
+
+ dev_info(tee->dev, "tee: ring buffer full. rptr = %u wptr = %u\n",
+ rptr, wptr);
+
+ /* Wait if ring buffer is full */
+ mutex_unlock(&tee->rb_mgr.mutex);
+ schedule_timeout_interruptible(msecs_to_jiffies(10));
+ mutex_lock(&tee->rb_mgr.mutex);
+
+ } while (--nloop);
+
+ if (!nloop && (wptr + sizeof(struct tee_ring_cmd) == rptr)) {
+ dev_err(tee->dev, "tee: ring buffer full. rptr = %u wptr = %u\n",
+ rptr, wptr);
+ ret = -EBUSY;
+ goto unlock;
+ }
+
+ /* Pointer to empty data entry in ring buffer */
+ cmd = (struct tee_ring_cmd *)(tee->rb_mgr.ring_start + wptr);
+
+ /* Write command data into ring buffer */
+ cmd->cmd_id = cmd_id;
+ cmd->cmd_state = TEE_CMD_STATE_INIT;
+ memset(&cmd->buf[0], 0, sizeof(cmd->buf));
+ memcpy(&cmd->buf[0], buf, len);
+
+ /* Update local copy of write pointer */
+ tee->rb_mgr.wptr += sizeof(struct tee_ring_cmd);
+ if (tee->rb_mgr.wptr >= tee->rb_mgr.ring_size)
+ tee->rb_mgr.wptr = 0;
+
+ /* Trigger interrupt to Trusted OS */
+ iowrite32(tee->rb_mgr.wptr, tee->io_regs + tee->vdata->ring_wptr_reg);
+
+ /* The response is provided by Trusted OS in same
+ * location as submitted data entry within ring buffer.
+ */
+ *resp = cmd;
+
+unlock:
+ mutex_unlock(&tee->rb_mgr.mutex);
+
+ return ret;
+}
+
+static int tee_wait_cmd_completion(struct psp_tee_device *tee,
+ struct tee_ring_cmd *resp,
+ unsigned int timeout)
+{
+ /* ~5ms sleep per loop => nloop = timeout * 200 */
+ int nloop = timeout * 200;
+
+ while (--nloop) {
+ if (resp->cmd_state == TEE_CMD_STATE_COMPLETED)
+ return 0;
+
+ usleep_range(5000, 5100);
+ }
+
+ dev_err(tee->dev, "tee: command 0x%x timed out, disabling PSP\n",
+ resp->cmd_id);
+
+ psp_dead = true;
+
+ return -ETIMEDOUT;
+}
+
+int psp_tee_process_cmd(enum tee_cmd_id cmd_id, void *buf, size_t len,
+ u32 *status)
+{
+ struct psp_device *psp = psp_get_master_device();
+ struct psp_tee_device *tee;
+ struct tee_ring_cmd *resp;
+ int ret;
+
+ if (!buf || !status || !len || len > sizeof(resp->buf))
+ return -EINVAL;
+
+ *status = 0;
+
+ if (!psp || !psp->tee_data)
+ return -ENODEV;
+
+ if (psp_dead)
+ return -EBUSY;
+
+ tee = psp->tee_data;
+
+ ret = tee_submit_cmd(tee, cmd_id, buf, len, &resp);
+ if (ret)
+ return ret;
+
+ ret = tee_wait_cmd_completion(tee, resp, TEE_DEFAULT_TIMEOUT);
+ if (ret)
+ return ret;
+
+ memcpy(buf, &resp->buf[0], len);
+ *status = resp->status;
+
+ return 0;
+}
+EXPORT_SYMBOL(psp_tee_process_cmd);
diff --git a/drivers/crypto/ccp/tee-dev.h b/drivers/crypto/ccp/tee-dev.h
index b3db0fc..f099601 100644
--- a/drivers/crypto/ccp/tee-dev.h
+++ b/drivers/crypto/ccp/tee-dev.h
@@ -54,6 +54,7 @@ struct tee_init_ring_cmd {
* @wptr: index to the last written entry in ring buffer
*/
struct ring_buf_manager {
+ struct mutex mutex; /* synchronizes access to ring buffer */
void *ring_start;
u32 ring_size;
phys_addr_t ring_pa;
diff --git a/include/linux/psp-tee.h b/include/linux/psp-tee.h
new file mode 100644
index 0000000..63bb221
--- /dev/null
+++ b/include/linux/psp-tee.h
@@ -0,0 +1,73 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * AMD Trusted Execution Environment (TEE) interface
+ *
+ * Author: Rijo Thomas <[email protected]>
+ *
+ * Copyright 2019 Advanced Micro Devices, Inc.
+ *
+ */
+
+#ifndef __PSP_TEE_H_
+#define __PSP_TEE_H_
+
+#include <linux/types.h>
+#include <linux/errno.h>
+
+/* This file defines the Trusted Execution Environment (TEE) interface commands
+ * and the API exported by AMD Secure Processor driver to communicate with
+ * AMD-TEE Trusted OS.
+ */
+
+/**
+ * enum tee_cmd_id - TEE Interface Command IDs
+ * @TEE_CMD_ID_LOAD_TA: Load Trusted Application (TA) binary into
+ * TEE environment
+ * @TEE_CMD_ID_UNLOAD_TA: Unload TA binary from TEE environment
+ * @TEE_CMD_ID_OPEN_SESSION: Open session with loaded TA
+ * @TEE_CMD_ID_CLOSE_SESSION: Close session with loaded TA
+ * @TEE_CMD_ID_INVOKE_CMD: Invoke a command with loaded TA
+ * @TEE_CMD_ID_MAP_SHARED_MEM: Map shared memory
+ * @TEE_CMD_ID_UNMAP_SHARED_MEM: Unmap shared memory
+ */
+enum tee_cmd_id {
+ TEE_CMD_ID_LOAD_TA = 1,
+ TEE_CMD_ID_UNLOAD_TA,
+ TEE_CMD_ID_OPEN_SESSION,
+ TEE_CMD_ID_CLOSE_SESSION,
+ TEE_CMD_ID_INVOKE_CMD,
+ TEE_CMD_ID_MAP_SHARED_MEM,
+ TEE_CMD_ID_UNMAP_SHARED_MEM,
+};
+
+#ifdef CONFIG_CRYPTO_DEV_SP_PSP
+/**
+ * psp_tee_process_cmd() - Process command in Trusted Execution Environment
+ * @cmd_id: TEE command ID (&enum tee_cmd_id)
+ * @buf: Command buffer for TEE processing. On success, is updated
+ * with the response
+ * @len: Length of command buffer in bytes
+ * @status: On success, holds the TEE command execution status
+ *
+ * This function submits a command to the Trusted OS for processing in the
+ * TEE environment and waits for a response or until the command times out.
+ *
+ * Returns:
+ * 0 if TEE successfully processed the command
+ * -%ENODEV if PSP device not available
+ * -%EINVAL if invalid input
+ * -%ETIMEDOUT if TEE command timed out
+ * -%EBUSY if PSP device is not responsive
+ */
+int psp_tee_process_cmd(enum tee_cmd_id cmd_id, void *buf, size_t len,
+ u32 *status);
+
+#else /* !CONFIG_CRYPTO_DEV_SP_PSP */
+
+static inline int psp_tee_process_cmd(enum tee_cmd_id cmd_id, void *buf,
+ size_t len, u32 *status)
+{
+ return -ENODEV;
+}
+#endif /* CONFIG_CRYPTO_DEV_SP_PSP */
+#endif /* __PSP_TEE_H_ */
--
1.9.1
Hi Herbert,
Please let me know if you have any comment for this patch series.
Request you to consider these patches for next merge cycle.
This patch series exports an in-kernel API which will be used by
AMD-TEE driver. The patch series which introduces AMD-TEE driver can
be found at: https://lkml.org/lkml/2019/12/6/17
Thanks,
Rijo
On 04/12/19 11:48 am, Rijo Thomas wrote:
> The goal of this patch series is to introduce TEE (Trusted Execution
> Environment) interface support to AMD Secure Processor driver. The
> TEE is a secure area of a processor which ensures that sensitive data
> is stored, processed and protected in an isolated and trusted
> environment. The Platform Security Processor (PSP) is a dedicated
> processor which provides TEE to enable HW platform security. It offers
> protection against software attacks generated in Rich Operating System
> (Rich OS) such as Linux running on x86.
>
> Based on the platform feature support, the PSP is capable of supporting
> either SEV (Secure Encrypted Virtualization) and/or TEE. The first three
> patches in this series is about moving SEV specific functions and data
> structures from PSP device driver file to a dedicated SEV interface
> driver file. The last two patches add TEE interface support to AMD
> Secure Processor driver. This TEE interface will be used by AMD-TEE
> driver to submit command buffers for processing in PSP Trusted Execution
> Environment.
>
> v3:
> * Rebased the patches onto cryptodev-2.6 tree with base commit
> 4ee812f6143d (crypto: vmx - Avoid weird build failures)
>
> v2:
> * Rebased the patches on cryptodev-2.6 tree with base commit
> d158367682cd (crypto: atmel - Fix selection of CRYPTO_AUTHENC)
> * Regenerated patch with correct diff-stat to show file rename
> * Used Co-developed-by: tag to give proper credit to co-author
>
> Rijo Thomas (6):
> crypto: ccp - rename psp-dev files to sev-dev
> crypto: ccp - create a generic psp-dev file
> crypto: ccp - move SEV vdata to a dedicated data structure
> crypto: ccp - check whether PSP supports SEV or TEE before
> initialization
> crypto: ccp - add TEE support for Raven Ridge
> crypto: ccp - provide in-kernel API to submit TEE commands
>
> drivers/crypto/ccp/Makefile | 4 +-
> drivers/crypto/ccp/psp-dev.c | 1033 ++++------------------------------------
> drivers/crypto/ccp/psp-dev.h | 51 +-
> drivers/crypto/ccp/sev-dev.c | 1068 ++++++++++++++++++++++++++++++++++++++++++
> drivers/crypto/ccp/sev-dev.h | 63 +++
> drivers/crypto/ccp/sp-dev.h | 17 +-
> drivers/crypto/ccp/sp-pci.c | 43 +-
> drivers/crypto/ccp/tee-dev.c | 364 ++++++++++++++
> drivers/crypto/ccp/tee-dev.h | 110 +++++
> include/linux/psp-tee.h | 73 +++
> 10 files changed, 1842 insertions(+), 984 deletions(-)
> create mode 100644 drivers/crypto/ccp/sev-dev.c
> create mode 100644 drivers/crypto/ccp/sev-dev.h
> create mode 100644 drivers/crypto/ccp/tee-dev.c
> create mode 100644 drivers/crypto/ccp/tee-dev.h
> create mode 100644 include/linux/psp-tee.h
>
> --
> 1.9.1
>
On 12/4/19 12:18 AM, Rijo Thomas wrote:
> This is a preliminary patch for creating a generic PSP device driver
> file, which will have support for both SEV and TEE (Trusted Execution
> Environment) interface.
>
> This patch does not introduce any new functionality, but simply renames
> psp-dev.c and psp-dev.h files to sev-dev.c and sev-dev.h files
> respectively.
>
> Cc: Ard Biesheuvel <[email protected]>
> Cc: Tom Lendacky <[email protected]>
> Cc: Jens Wiklander <[email protected]>
> Co-developed-by: Devaraj Rangasamy <[email protected]>
> Signed-off-by: Devaraj Rangasamy <[email protected]>
> Signed-off-by: Rijo Thomas <[email protected]>
Acked-by: Gary R Hook <[email protected]>
> ---
> drivers/crypto/ccp/Makefile | 2 +-
> drivers/crypto/ccp/{psp-dev.c => sev-dev.c} | 6 +++---
> drivers/crypto/ccp/{psp-dev.h => sev-dev.h} | 8 ++++----
> drivers/crypto/ccp/sp-pci.c | 2 +-
> 4 files changed, 9 insertions(+), 9 deletions(-)
> rename drivers/crypto/ccp/{psp-dev.c => sev-dev.c} (99%)
> rename drivers/crypto/ccp/{psp-dev.h => sev-dev.h} (90%)
>
> diff --git a/drivers/crypto/ccp/Makefile b/drivers/crypto/ccp/Makefile
> index 6b86f1e..9dafcf2 100644
> --- a/drivers/crypto/ccp/Makefile
> +++ b/drivers/crypto/ccp/Makefile
> @@ -8,7 +8,7 @@ ccp-$(CONFIG_CRYPTO_DEV_SP_CCP) += ccp-dev.o \
> ccp-dmaengine.o
> ccp-$(CONFIG_CRYPTO_DEV_CCP_DEBUGFS) += ccp-debugfs.o
> ccp-$(CONFIG_PCI) += sp-pci.o
> -ccp-$(CONFIG_CRYPTO_DEV_SP_PSP) += psp-dev.o
> +ccp-$(CONFIG_CRYPTO_DEV_SP_PSP) += sev-dev.o
>
> obj-$(CONFIG_CRYPTO_DEV_CCP_CRYPTO) += ccp-crypto.o
> ccp-crypto-objs := ccp-crypto-main.o \
> diff --git a/drivers/crypto/ccp/psp-dev.c b/drivers/crypto/ccp/sev-dev.c
> similarity index 99%
> rename from drivers/crypto/ccp/psp-dev.c
> rename to drivers/crypto/ccp/sev-dev.c
> index 5ff842c..9a8c523 100644
> --- a/drivers/crypto/ccp/psp-dev.c
> +++ b/drivers/crypto/ccp/sev-dev.c
> @@ -1,8 +1,8 @@
> // SPDX-License-Identifier: GPL-2.0-only
> /*
> - * AMD Platform Security Processor (PSP) interface
> + * AMD Secure Encrypted Virtualization (SEV) interface
> *
> - * Copyright (C) 2016,2018 Advanced Micro Devices, Inc.
> + * Copyright (C) 2016,2019 Advanced Micro Devices, Inc.
> *
> * Author: Brijesh Singh <[email protected]>
> */
> @@ -22,7 +22,7 @@
> #include <linux/firmware.h>
>
> #include "sp-dev.h"
> -#include "psp-dev.h"
> +#include "sev-dev.h"
>
> #define DEVICE_NAME "sev"
> #define SEV_FW_FILE "amd/sev.fw"
> diff --git a/drivers/crypto/ccp/psp-dev.h b/drivers/crypto/ccp/sev-dev.h
> similarity index 90%
> rename from drivers/crypto/ccp/psp-dev.h
> rename to drivers/crypto/ccp/sev-dev.h
> index dd516b3..e861647 100644
> --- a/drivers/crypto/ccp/psp-dev.h
> +++ b/drivers/crypto/ccp/sev-dev.h
> @@ -2,13 +2,13 @@
> /*
> * AMD Platform Security Processor (PSP) interface driver
> *
> - * Copyright (C) 2017-2018 Advanced Micro Devices, Inc.
> + * Copyright (C) 2017-2019 Advanced Micro Devices, Inc.
> *
> * Author: Brijesh Singh <[email protected]>
> */
>
> -#ifndef __PSP_DEV_H__
> -#define __PSP_DEV_H__
> +#ifndef __SEV_DEV_H__
> +#define __SEV_DEV_H__
>
> #include <linux/device.h>
> #include <linux/spinlock.h>
> @@ -64,4 +64,4 @@ struct psp_device {
> u8 build;
> };
>
> -#endif /* __PSP_DEV_H */
> +#endif /* __SEV_DEV_H */
> diff --git a/drivers/crypto/ccp/sp-pci.c b/drivers/crypto/ccp/sp-pci.c
> index b29d2e6..473cf14 100644
> --- a/drivers/crypto/ccp/sp-pci.c
> +++ b/drivers/crypto/ccp/sp-pci.c
> @@ -22,7 +22,7 @@
> #include <linux/ccp.h>
>
> #include "ccp-dev.h"
> -#include "psp-dev.h"
> +#include "sev-dev.h"
>
> #define MSIX_VECTORS 2
>
>
On 12/4/19 12:19 AM, Rijo Thomas wrote:
> PSP can support both SEV and TEE interface. Therefore, move
> SEV specific registers to a dedicated data structure.
> TEE interface specific registers will be added in a later
> patch.
>
> Cc: Ard Biesheuvel <[email protected]>
> Cc: Tom Lendacky <[email protected]>
> Cc: Jens Wiklander <[email protected]>
> Co-developed-by: Devaraj Rangasamy <[email protected]>
> Signed-off-by: Devaraj Rangasamy <[email protected]>
> Signed-off-by: Rijo Thomas <[email protected]>
Acked-by: Gary R Hook <[email protected]>
> ---
> drivers/crypto/ccp/sev-dev.c | 17 ++++++++++++-----
> drivers/crypto/ccp/sev-dev.h | 2 ++
> drivers/crypto/ccp/sp-dev.h | 6 +++++-
> drivers/crypto/ccp/sp-pci.c | 16 ++++++++++++----
> 4 files changed, 31 insertions(+), 10 deletions(-)
>
> diff --git a/drivers/crypto/ccp/sev-dev.c b/drivers/crypto/ccp/sev-dev.c
> index a608b52..e68fa48 100644
> --- a/drivers/crypto/ccp/sev-dev.c
> +++ b/drivers/crypto/ccp/sev-dev.c
> @@ -65,7 +65,7 @@ static void sev_irq_handler(int irq, void *data, unsigned int status)
> return;
>
> /* Check if it is SEV command completion: */
> - reg = ioread32(sev->io_regs + sev->psp->vdata->cmdresp_reg);
> + reg = ioread32(sev->io_regs + sev->vdata->cmdresp_reg);
> if (reg & PSP_CMDRESP_RESP) {
> sev->int_rcvd = 1;
> wake_up(&sev->int_queue);
> @@ -82,7 +82,7 @@ static int sev_wait_cmd_ioc(struct sev_device *sev,
> if (!ret)
> return -ETIMEDOUT;
>
> - *reg = ioread32(sev->io_regs + sev->psp->vdata->cmdresp_reg);
> + *reg = ioread32(sev->io_regs + sev->vdata->cmdresp_reg);
>
> return 0;
> }
> @@ -148,15 +148,15 @@ static int __sev_do_cmd_locked(int cmd, void *data, int *psp_ret)
> print_hex_dump_debug("(in): ", DUMP_PREFIX_OFFSET, 16, 2, data,
> sev_cmd_buffer_len(cmd), false);
>
> - iowrite32(phys_lsb, sev->io_regs + psp->vdata->cmdbuff_addr_lo_reg);
> - iowrite32(phys_msb, sev->io_regs + psp->vdata->cmdbuff_addr_hi_reg);
> + iowrite32(phys_lsb, sev->io_regs + sev->vdata->cmdbuff_addr_lo_reg);
> + iowrite32(phys_msb, sev->io_regs + sev->vdata->cmdbuff_addr_hi_reg);
>
> sev->int_rcvd = 0;
>
> reg = cmd;
> reg <<= SEV_CMDRESP_CMD_SHIFT;
> reg |= SEV_CMDRESP_IOC;
> - iowrite32(reg, sev->io_regs + psp->vdata->cmdresp_reg);
> + iowrite32(reg, sev->io_regs + sev->vdata->cmdresp_reg);
>
> /* wait for command completion */
> ret = sev_wait_cmd_ioc(sev, ®, psp_timeout);
> @@ -949,6 +949,13 @@ int sev_dev_init(struct psp_device *psp)
>
> sev->io_regs = psp->io_regs;
>
> + sev->vdata = (struct sev_vdata *)psp->vdata->sev;
> + if (!sev->vdata) {
> + ret = -ENODEV;
> + dev_err(dev, "sev: missing driver data\n");
> + goto e_err;
> + }
> +
> psp_set_sev_irq_handler(psp, sev_irq_handler, sev);
>
> ret = sev_misc_init(sev);
> diff --git a/drivers/crypto/ccp/sev-dev.h b/drivers/crypto/ccp/sev-dev.h
> index 3d84ac3..dd5c4fe 100644
> --- a/drivers/crypto/ccp/sev-dev.h
> +++ b/drivers/crypto/ccp/sev-dev.h
> @@ -40,6 +40,8 @@ struct sev_device {
>
> void __iomem *io_regs;
>
> + struct sev_vdata *vdata;
> +
> int state;
> unsigned int int_rcvd;
> wait_queue_head_t int_queue;
> diff --git a/drivers/crypto/ccp/sp-dev.h b/drivers/crypto/ccp/sp-dev.h
> index 53c1256..0394c75 100644
> --- a/drivers/crypto/ccp/sp-dev.h
> +++ b/drivers/crypto/ccp/sp-dev.h
> @@ -39,10 +39,14 @@ struct ccp_vdata {
> const unsigned int rsamax;
> };
>
> -struct psp_vdata {
> +struct sev_vdata {
> const unsigned int cmdresp_reg;
> const unsigned int cmdbuff_addr_lo_reg;
> const unsigned int cmdbuff_addr_hi_reg;
> +};
> +
> +struct psp_vdata {
> + const struct sev_vdata *sev;
> const unsigned int feature_reg;
> const unsigned int inten_reg;
> const unsigned int intsts_reg;
> diff --git a/drivers/crypto/ccp/sp-pci.c b/drivers/crypto/ccp/sp-pci.c
> index b29d2e6..733693d 100644
> --- a/drivers/crypto/ccp/sp-pci.c
> +++ b/drivers/crypto/ccp/sp-pci.c
> @@ -262,19 +262,27 @@ static int sp_pci_resume(struct pci_dev *pdev)
> #endif
>
> #ifdef CONFIG_CRYPTO_DEV_SP_PSP
> -static const struct psp_vdata pspv1 = {
> +static const struct sev_vdata sevv1 = {
> .cmdresp_reg = 0x10580,
> .cmdbuff_addr_lo_reg = 0x105e0,
> .cmdbuff_addr_hi_reg = 0x105e4,
> +};
> +
> +static const struct sev_vdata sevv2 = {
> + .cmdresp_reg = 0x10980,
> + .cmdbuff_addr_lo_reg = 0x109e0,
> + .cmdbuff_addr_hi_reg = 0x109e4,
> +};
> +
> +static const struct psp_vdata pspv1 = {
> + .sev = &sevv1,
> .feature_reg = 0x105fc,
> .inten_reg = 0x10610,
> .intsts_reg = 0x10614,
> };
>
> static const struct psp_vdata pspv2 = {
> - .cmdresp_reg = 0x10980,
> - .cmdbuff_addr_lo_reg = 0x109e0,
> - .cmdbuff_addr_hi_reg = 0x109e4,
> + .sev = &sevv2,
> .feature_reg = 0x109fc,
> .inten_reg = 0x10690,
> .intsts_reg = 0x10694,
>
On 12/4/19 12:19 AM, Rijo Thomas wrote:
> Adds a PCI device entry for Raven Ridge. Raven Ridge is an APU with a
> dedicated AMD Secure Processor having Trusted Execution Environment (TEE)
> support. The TEE provides a secure environment for running Trusted
> Applications (TAs) which implement security-sensitive parts of a feature.
>
> This patch configures AMD Secure Processor's TEE interface by initializing
> a ring buffer (shared memory between Rich OS and Trusted OS) which can hold
> multiple command buffer entries. The TEE interface is facilitated by a set
> of CPU to PSP mailbox registers.
>
> The next patch will address how commands are submitted to the ring buffer.
>
> Cc: Jens Wiklander <[email protected]>
> Cc: Tom Lendacky <[email protected]>
> Cc: Ard Biesheuvel <[email protected]>
> Co-developed-by: Devaraj Rangasamy <[email protected]>
> Signed-off-by: Devaraj Rangasamy <[email protected]>
> Signed-off-by: Rijo Thomas <[email protected]>
Acked-by: Gary R Hook <[email protected]>
> ---
> drivers/crypto/ccp/Makefile | 3 +-
> drivers/crypto/ccp/psp-dev.c | 39 ++++++-
> drivers/crypto/ccp/psp-dev.h | 8 ++
> drivers/crypto/ccp/sp-dev.h | 11 +-
> drivers/crypto/ccp/sp-pci.c | 27 ++++-
> drivers/crypto/ccp/tee-dev.c | 238 +++++++++++++++++++++++++++++++++++++++++++
> drivers/crypto/ccp/tee-dev.h | 109 ++++++++++++++++++++
> 7 files changed, 431 insertions(+), 4 deletions(-)
> create mode 100644 drivers/crypto/ccp/tee-dev.c
> create mode 100644 drivers/crypto/ccp/tee-dev.h
>
> diff --git a/drivers/crypto/ccp/Makefile b/drivers/crypto/ccp/Makefile
> index 3b29ea4..db362fe 100644
> --- a/drivers/crypto/ccp/Makefile
> +++ b/drivers/crypto/ccp/Makefile
> @@ -9,7 +9,8 @@ ccp-$(CONFIG_CRYPTO_DEV_SP_CCP) += ccp-dev.o \
> ccp-$(CONFIG_CRYPTO_DEV_CCP_DEBUGFS) += ccp-debugfs.o
> ccp-$(CONFIG_PCI) += sp-pci.o
> ccp-$(CONFIG_CRYPTO_DEV_SP_PSP) += psp-dev.o \
> - sev-dev.o
> + sev-dev.o \
> + tee-dev.o
>
> obj-$(CONFIG_CRYPTO_DEV_CCP_CRYPTO) += ccp-crypto.o
> ccp-crypto-objs := ccp-crypto-main.o \
> diff --git a/drivers/crypto/ccp/psp-dev.c b/drivers/crypto/ccp/psp-dev.c
> index 3bedf72..e95e7aa 100644
> --- a/drivers/crypto/ccp/psp-dev.c
> +++ b/drivers/crypto/ccp/psp-dev.c
> @@ -13,6 +13,7 @@
> #include "sp-dev.h"
> #include "psp-dev.h"
> #include "sev-dev.h"
> +#include "tee-dev.h"
>
> struct psp_device *psp_master;
>
> @@ -45,6 +46,9 @@ static irqreturn_t psp_irq_handler(int irq, void *data)
> if (status) {
> if (psp->sev_irq_handler)
> psp->sev_irq_handler(irq, psp->sev_irq_data, status);
> +
> + if (psp->tee_irq_handler)
> + psp->tee_irq_handler(irq, psp->tee_irq_data, status);
> }
>
> /* Clear the interrupt status by writing the same value we read. */
> @@ -109,6 +113,25 @@ static int psp_check_support(struct psp_device *psp,
> return 0;
> }
>
> +static int psp_init(struct psp_device *psp, unsigned int capability)
> +{
> + int ret;
> +
> + if (!psp_check_sev_support(psp, capability)) {
> + ret = sev_dev_init(psp);
> + if (ret)
> + return ret;
> + }
> +
> + if (!psp_check_tee_support(psp, capability)) {
> + ret = tee_dev_init(psp);
> + if (ret)
> + return ret;
> + }
> +
> + return 0;
> +}
> +
> int psp_dev_init(struct sp_device *sp)
> {
> struct device *dev = sp->dev;
> @@ -151,7 +174,7 @@ int psp_dev_init(struct sp_device *sp)
> goto e_err;
> }
>
> - ret = sev_dev_init(psp);
> + ret = psp_init(psp, capability);
> if (ret)
> goto e_irq;
>
> @@ -189,6 +212,8 @@ void psp_dev_destroy(struct sp_device *sp)
>
> sev_dev_destroy(psp);
>
> + tee_dev_destroy(psp);
> +
> sp_free_psp_irq(sp, psp);
> }
>
> @@ -204,6 +229,18 @@ void psp_clear_sev_irq_handler(struct psp_device *psp)
> psp_set_sev_irq_handler(psp, NULL, NULL);
> }
>
> +void psp_set_tee_irq_handler(struct psp_device *psp, psp_irq_handler_t handler,
> + void *data)
> +{
> + psp->tee_irq_data = data;
> + psp->tee_irq_handler = handler;
> +}
> +
> +void psp_clear_tee_irq_handler(struct psp_device *psp)
> +{
> + psp_set_tee_irq_handler(psp, NULL, NULL);
> +}
> +
> struct psp_device *psp_get_master_device(void)
> {
> struct sp_device *sp = sp_get_psp_master_device();
> diff --git a/drivers/crypto/ccp/psp-dev.h b/drivers/crypto/ccp/psp-dev.h
> index 7c014ac..ef38e41 100644
> --- a/drivers/crypto/ccp/psp-dev.h
> +++ b/drivers/crypto/ccp/psp-dev.h
> @@ -40,13 +40,21 @@ struct psp_device {
> psp_irq_handler_t sev_irq_handler;
> void *sev_irq_data;
>
> + psp_irq_handler_t tee_irq_handler;
> + void *tee_irq_data;
> +
> void *sev_data;
> + void *tee_data;
> };
>
> void psp_set_sev_irq_handler(struct psp_device *psp, psp_irq_handler_t handler,
> void *data);
> void psp_clear_sev_irq_handler(struct psp_device *psp);
>
> +void psp_set_tee_irq_handler(struct psp_device *psp, psp_irq_handler_t handler,
> + void *data);
> +void psp_clear_tee_irq_handler(struct psp_device *psp);
> +
> struct psp_device *psp_get_master_device(void);
>
> #endif /* __PSP_DEV_H */
> diff --git a/drivers/crypto/ccp/sp-dev.h b/drivers/crypto/ccp/sp-dev.h
> index 0394c75..4235946 100644
> --- a/drivers/crypto/ccp/sp-dev.h
> +++ b/drivers/crypto/ccp/sp-dev.h
> @@ -2,7 +2,7 @@
> /*
> * AMD Secure Processor driver
> *
> - * Copyright (C) 2017-2018 Advanced Micro Devices, Inc.
> + * Copyright (C) 2017-2019 Advanced Micro Devices, Inc.
> *
> * Author: Tom Lendacky <[email protected]>
> * Author: Gary R Hook <[email protected]>
> @@ -45,8 +45,17 @@ struct sev_vdata {
> const unsigned int cmdbuff_addr_hi_reg;
> };
>
> +struct tee_vdata {
> + const unsigned int cmdresp_reg;
> + const unsigned int cmdbuff_addr_lo_reg;
> + const unsigned int cmdbuff_addr_hi_reg;
> + const unsigned int ring_wptr_reg;
> + const unsigned int ring_rptr_reg;
> +};
> +
> struct psp_vdata {
> const struct sev_vdata *sev;
> + const struct tee_vdata *tee;
> const unsigned int feature_reg;
> const unsigned int inten_reg;
> const unsigned int intsts_reg;
> diff --git a/drivers/crypto/ccp/sp-pci.c b/drivers/crypto/ccp/sp-pci.c
> index 733693d..56c1f61 100644
> --- a/drivers/crypto/ccp/sp-pci.c
> +++ b/drivers/crypto/ccp/sp-pci.c
> @@ -2,7 +2,7 @@
> /*
> * AMD Secure Processor device driver
> *
> - * Copyright (C) 2013,2018 Advanced Micro Devices, Inc.
> + * Copyright (C) 2013,2019 Advanced Micro Devices, Inc.
> *
> * Author: Tom Lendacky <[email protected]>
> * Author: Gary R Hook <[email protected]>
> @@ -274,6 +274,14 @@ static int sp_pci_resume(struct pci_dev *pdev)
> .cmdbuff_addr_hi_reg = 0x109e4,
> };
>
> +static const struct tee_vdata teev1 = {
> + .cmdresp_reg = 0x10544,
> + .cmdbuff_addr_lo_reg = 0x10548,
> + .cmdbuff_addr_hi_reg = 0x1054c,
> + .ring_wptr_reg = 0x10550,
> + .ring_rptr_reg = 0x10554,
> +};
> +
> static const struct psp_vdata pspv1 = {
> .sev = &sevv1,
> .feature_reg = 0x105fc,
> @@ -287,6 +295,13 @@ static int sp_pci_resume(struct pci_dev *pdev)
> .inten_reg = 0x10690,
> .intsts_reg = 0x10694,
> };
> +
> +static const struct psp_vdata pspv3 = {
> + .tee = &teev1,
> + .feature_reg = 0x109fc,
> + .inten_reg = 0x10690,
> + .intsts_reg = 0x10694,
> +};
> #endif
>
> static const struct sp_dev_vdata dev_vdata[] = {
> @@ -320,12 +335,22 @@ static int sp_pci_resume(struct pci_dev *pdev)
> .psp_vdata = &pspv2,
> #endif
> },
> + { /* 4 */
> + .bar = 2,
> +#ifdef CONFIG_CRYPTO_DEV_SP_CCP
> + .ccp_vdata = &ccpv5a,
> +#endif
> +#ifdef CONFIG_CRYPTO_DEV_SP_PSP
> + .psp_vdata = &pspv3,
> +#endif
> + },
> };
> static const struct pci_device_id sp_pci_table[] = {
> { PCI_VDEVICE(AMD, 0x1537), (kernel_ulong_t)&dev_vdata[0] },
> { PCI_VDEVICE(AMD, 0x1456), (kernel_ulong_t)&dev_vdata[1] },
> { PCI_VDEVICE(AMD, 0x1468), (kernel_ulong_t)&dev_vdata[2] },
> { PCI_VDEVICE(AMD, 0x1486), (kernel_ulong_t)&dev_vdata[3] },
> + { PCI_VDEVICE(AMD, 0x15DF), (kernel_ulong_t)&dev_vdata[4] },
> /* Last entry must be zero */
> { 0, }
> };
> diff --git a/drivers/crypto/ccp/tee-dev.c b/drivers/crypto/ccp/tee-dev.c
> new file mode 100644
> index 0000000..ccbc2ce
> --- /dev/null
> +++ b/drivers/crypto/ccp/tee-dev.c
> @@ -0,0 +1,238 @@
> +// SPDX-License-Identifier: MIT
> +/*
> + * AMD Trusted Execution Environment (TEE) interface
> + *
> + * Author: Rijo Thomas <[email protected]>
> + * Author: Devaraj Rangasamy <[email protected]>
> + *
> + * Copyright 2019 Advanced Micro Devices, Inc.
> + */
> +
> +#include <linux/types.h>
> +#include <linux/mutex.h>
> +#include <linux/delay.h>
> +#include <linux/slab.h>
> +#include <linux/gfp.h>
> +#include <linux/psp-sev.h>
> +
> +#include "psp-dev.h"
> +#include "tee-dev.h"
> +
> +static bool psp_dead;
> +
> +static int tee_alloc_ring(struct psp_tee_device *tee, int ring_size)
> +{
> + struct ring_buf_manager *rb_mgr = &tee->rb_mgr;
> + void *start_addr;
> +
> + if (!ring_size)
> + return -EINVAL;
> +
> + /* We need actual physical address instead of DMA address, since
> + * Trusted OS running on AMD Secure Processor will map this region
> + */
> + start_addr = (void *)__get_free_pages(GFP_KERNEL, get_order(ring_size));
> + if (!start_addr)
> + return -ENOMEM;
> +
> + rb_mgr->ring_start = start_addr;
> + rb_mgr->ring_size = ring_size;
> + rb_mgr->ring_pa = __psp_pa(start_addr);
> +
> + return 0;
> +}
> +
> +static void tee_free_ring(struct psp_tee_device *tee)
> +{
> + struct ring_buf_manager *rb_mgr = &tee->rb_mgr;
> +
> + if (!rb_mgr->ring_start)
> + return;
> +
> + free_pages((unsigned long)rb_mgr->ring_start,
> + get_order(rb_mgr->ring_size));
> +
> + rb_mgr->ring_start = NULL;
> + rb_mgr->ring_size = 0;
> + rb_mgr->ring_pa = 0;
> +}
> +
> +static int tee_wait_cmd_poll(struct psp_tee_device *tee, unsigned int timeout,
> + unsigned int *reg)
> +{
> + /* ~10ms sleep per loop => nloop = timeout * 100 */
> + int nloop = timeout * 100;
> +
> + while (--nloop) {
> + *reg = ioread32(tee->io_regs + tee->vdata->cmdresp_reg);
> + if (*reg & PSP_CMDRESP_RESP)
> + return 0;
> +
> + usleep_range(10000, 10100);
> + }
> +
> + dev_err(tee->dev, "tee: command timed out, disabling PSP\n");
> + psp_dead = true;
> +
> + return -ETIMEDOUT;
> +}
> +
> +static
> +struct tee_init_ring_cmd *tee_alloc_cmd_buffer(struct psp_tee_device *tee)
> +{
> + struct tee_init_ring_cmd *cmd;
> +
> + cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
> + if (!cmd)
> + return NULL;
> +
> + cmd->hi_addr = upper_32_bits(tee->rb_mgr.ring_pa);
> + cmd->low_addr = lower_32_bits(tee->rb_mgr.ring_pa);
> + cmd->size = tee->rb_mgr.ring_size;
> +
> + dev_dbg(tee->dev, "tee: ring address: high = 0x%x low = 0x%x size = %u\n",
> + cmd->hi_addr, cmd->low_addr, cmd->size);
> +
> + return cmd;
> +}
> +
> +static inline void tee_free_cmd_buffer(struct tee_init_ring_cmd *cmd)
> +{
> + kfree(cmd);
> +}
> +
> +static int tee_init_ring(struct psp_tee_device *tee)
> +{
> + int ring_size = MAX_RING_BUFFER_ENTRIES * sizeof(struct tee_ring_cmd);
> + struct tee_init_ring_cmd *cmd;
> + phys_addr_t cmd_buffer;
> + unsigned int reg;
> + int ret;
> +
> + BUILD_BUG_ON(sizeof(struct tee_ring_cmd) != 1024);
> +
> + ret = tee_alloc_ring(tee, ring_size);
> + if (ret) {
> + dev_err(tee->dev, "tee: ring allocation failed %d\n", ret);
> + return ret;
> + }
> +
> + tee->rb_mgr.wptr = 0;
> +
> + cmd = tee_alloc_cmd_buffer(tee);
> + if (!cmd) {
> + tee_free_ring(tee);
> + return -ENOMEM;
> + }
> +
> + cmd_buffer = __psp_pa((void *)cmd);
> +
> + /* Send command buffer details to Trusted OS by writing to
> + * CPU-PSP message registers
> + */
> +
> + iowrite32(lower_32_bits(cmd_buffer),
> + tee->io_regs + tee->vdata->cmdbuff_addr_lo_reg);
> + iowrite32(upper_32_bits(cmd_buffer),
> + tee->io_regs + tee->vdata->cmdbuff_addr_hi_reg);
> + iowrite32(TEE_RING_INIT_CMD,
> + tee->io_regs + tee->vdata->cmdresp_reg);
> +
> + ret = tee_wait_cmd_poll(tee, TEE_DEFAULT_TIMEOUT, ®);
> + if (ret) {
> + dev_err(tee->dev, "tee: ring init command timed out\n");
> + tee_free_ring(tee);
> + goto free_buf;
> + }
> +
> + if (reg & PSP_CMDRESP_ERR_MASK) {
> + dev_err(tee->dev, "tee: ring init command failed (%#010x)\n",
> + reg & PSP_CMDRESP_ERR_MASK);
> + tee_free_ring(tee);
> + ret = -EIO;
> + }
> +
> +free_buf:
> + tee_free_cmd_buffer(cmd);
> +
> + return ret;
> +}
> +
> +static void tee_destroy_ring(struct psp_tee_device *tee)
> +{
> + unsigned int reg;
> + int ret;
> +
> + if (!tee->rb_mgr.ring_start)
> + return;
> +
> + if (psp_dead)
> + goto free_ring;
> +
> + iowrite32(TEE_RING_DESTROY_CMD,
> + tee->io_regs + tee->vdata->cmdresp_reg);
> +
> + ret = tee_wait_cmd_poll(tee, TEE_DEFAULT_TIMEOUT, ®);
> + if (ret) {
> + dev_err(tee->dev, "tee: ring destroy command timed out\n");
> + } else if (reg & PSP_CMDRESP_ERR_MASK) {
> + dev_err(tee->dev, "tee: ring destroy command failed (%#010x)\n",
> + reg & PSP_CMDRESP_ERR_MASK);
> + }
> +
> +free_ring:
> + tee_free_ring(tee);
> +}
> +
> +int tee_dev_init(struct psp_device *psp)
> +{
> + struct device *dev = psp->dev;
> + struct psp_tee_device *tee;
> + int ret;
> +
> + ret = -ENOMEM;
> + tee = devm_kzalloc(dev, sizeof(*tee), GFP_KERNEL);
> + if (!tee)
> + goto e_err;
> +
> + psp->tee_data = tee;
> +
> + tee->dev = dev;
> + tee->psp = psp;
> +
> + tee->io_regs = psp->io_regs;
> +
> + tee->vdata = (struct tee_vdata *)psp->vdata->tee;
> + if (!tee->vdata) {
> + ret = -ENODEV;
> + dev_err(dev, "tee: missing driver data\n");
> + goto e_err;
> + }
> +
> + ret = tee_init_ring(tee);
> + if (ret) {
> + dev_err(dev, "tee: failed to init ring buffer\n");
> + goto e_err;
> + }
> +
> + dev_notice(dev, "tee enabled\n");
> +
> + return 0;
> +
> +e_err:
> + psp->tee_data = NULL;
> +
> + dev_notice(dev, "tee initialization failed\n");
> +
> + return ret;
> +}
> +
> +void tee_dev_destroy(struct psp_device *psp)
> +{
> + struct psp_tee_device *tee = psp->tee_data;
> +
> + if (!tee)
> + return;
> +
> + tee_destroy_ring(tee);
> +}
> diff --git a/drivers/crypto/ccp/tee-dev.h b/drivers/crypto/ccp/tee-dev.h
> new file mode 100644
> index 0000000..b3db0fc
> --- /dev/null
> +++ b/drivers/crypto/ccp/tee-dev.h
> @@ -0,0 +1,109 @@
> +/* SPDX-License-Identifier: MIT */
> +/*
> + * Copyright 2019 Advanced Micro Devices, Inc.
> + *
> + * Author: Rijo Thomas <[email protected]>
> + * Author: Devaraj Rangasamy <[email protected]>
> + *
> + */
> +
> +/* This file describes the TEE communication interface between host and AMD
> + * Secure Processor
> + */
> +
> +#ifndef __TEE_DEV_H__
> +#define __TEE_DEV_H__
> +
> +#include <linux/device.h>
> +#include <linux/mutex.h>
> +
> +#define TEE_DEFAULT_TIMEOUT 10
> +#define MAX_BUFFER_SIZE 992
> +
> +/**
> + * enum tee_ring_cmd_id - TEE interface commands for ring buffer configuration
> + * @TEE_RING_INIT_CMD: Initialize ring buffer
> + * @TEE_RING_DESTROY_CMD: Destroy ring buffer
> + * @TEE_RING_MAX_CMD: Maximum command id
> + */
> +enum tee_ring_cmd_id {
> + TEE_RING_INIT_CMD = 0x00010000,
> + TEE_RING_DESTROY_CMD = 0x00020000,
> + TEE_RING_MAX_CMD = 0x000F0000,
> +};
> +
> +/**
> + * struct tee_init_ring_cmd - Command to init TEE ring buffer
> + * @low_addr: bits [31:0] of the physical address of ring buffer
> + * @hi_addr: bits [63:32] of the physical address of ring buffer
> + * @size: size of ring buffer in bytes
> + */
> +struct tee_init_ring_cmd {
> + u32 low_addr;
> + u32 hi_addr;
> + u32 size;
> +};
> +
> +#define MAX_RING_BUFFER_ENTRIES 32
> +
> +/**
> + * struct ring_buf_manager - Helper structure to manage ring buffer.
> + * @ring_start: starting address of ring buffer
> + * @ring_size: size of ring buffer in bytes
> + * @ring_pa: physical address of ring buffer
> + * @wptr: index to the last written entry in ring buffer
> + */
> +struct ring_buf_manager {
> + void *ring_start;
> + u32 ring_size;
> + phys_addr_t ring_pa;
> + u32 wptr;
> +};
> +
> +struct psp_tee_device {
> + struct device *dev;
> + struct psp_device *psp;
> + void __iomem *io_regs;
> + struct tee_vdata *vdata;
> + struct ring_buf_manager rb_mgr;
> +};
> +
> +/**
> + * enum tee_cmd_state - TEE command states for the ring buffer interface
> + * @TEE_CMD_STATE_INIT: initial state of command when sent from host
> + * @TEE_CMD_STATE_PROCESS: command being processed by TEE environment
> + * @TEE_CMD_STATE_COMPLETED: command processing completed
> + */
> +enum tee_cmd_state {
> + TEE_CMD_STATE_INIT,
> + TEE_CMD_STATE_PROCESS,
> + TEE_CMD_STATE_COMPLETED,
> +};
> +
> +/**
> + * struct tee_ring_cmd - Structure of the command buffer in TEE ring
> + * @cmd_id: refers to &enum tee_cmd_id. Command id for the ring buffer
> + * interface
> + * @cmd_state: refers to &enum tee_cmd_state
> + * @status: status of TEE command execution
> + * @res0: reserved region
> + * @pdata: private data (currently unused)
> + * @res1: reserved region
> + * @buf: TEE command specific buffer
> + */
> +struct tee_ring_cmd {
> + u32 cmd_id;
> + u32 cmd_state;
> + u32 status;
> + u32 res0[1];
> + u64 pdata;
> + u32 res1[2];
> + u8 buf[MAX_BUFFER_SIZE];
> +
> + /* Total size: 1024 bytes */
> +} __packed;
> +
> +int tee_dev_init(struct psp_device *psp);
> +void tee_dev_destroy(struct psp_device *psp);
> +
> +#endif /* __TEE_DEV_H__ */
>
On Wed, Dec 04, 2019 at 11:48:57AM +0530, Rijo Thomas wrote:
> The goal of this patch series is to introduce TEE (Trusted Execution
> Environment) interface support to AMD Secure Processor driver. The
> TEE is a secure area of a processor which ensures that sensitive data
> is stored, processed and protected in an isolated and trusted
> environment. The Platform Security Processor (PSP) is a dedicated
> processor which provides TEE to enable HW platform security. It offers
> protection against software attacks generated in Rich Operating System
> (Rich OS) such as Linux running on x86.
>
> Based on the platform feature support, the PSP is capable of supporting
> either SEV (Secure Encrypted Virtualization) and/or TEE. The first three
> patches in this series is about moving SEV specific functions and data
> structures from PSP device driver file to a dedicated SEV interface
> driver file. The last two patches add TEE interface support to AMD
> Secure Processor driver. This TEE interface will be used by AMD-TEE
> driver to submit command buffers for processing in PSP Trusted Execution
> Environment.
>
> v3:
> * Rebased the patches onto cryptodev-2.6 tree with base commit
> 4ee812f6143d (crypto: vmx - Avoid weird build failures)
>
> v2:
> * Rebased the patches on cryptodev-2.6 tree with base commit
> d158367682cd (crypto: atmel - Fix selection of CRYPTO_AUTHENC)
> * Regenerated patch with correct diff-stat to show file rename
> * Used Co-developed-by: tag to give proper credit to co-author
>
> Rijo Thomas (6):
> crypto: ccp - rename psp-dev files to sev-dev
> crypto: ccp - create a generic psp-dev file
> crypto: ccp - move SEV vdata to a dedicated data structure
> crypto: ccp - check whether PSP supports SEV or TEE before
> initialization
> crypto: ccp - add TEE support for Raven Ridge
> crypto: ccp - provide in-kernel API to submit TEE commands
>
> drivers/crypto/ccp/Makefile | 4 +-
> drivers/crypto/ccp/psp-dev.c | 1033 ++++------------------------------------
> drivers/crypto/ccp/psp-dev.h | 51 +-
> drivers/crypto/ccp/sev-dev.c | 1068 ++++++++++++++++++++++++++++++++++++++++++
> drivers/crypto/ccp/sev-dev.h | 63 +++
> drivers/crypto/ccp/sp-dev.h | 17 +-
> drivers/crypto/ccp/sp-pci.c | 43 +-
> drivers/crypto/ccp/tee-dev.c | 364 ++++++++++++++
> drivers/crypto/ccp/tee-dev.h | 110 +++++
> include/linux/psp-tee.h | 73 +++
> 10 files changed, 1842 insertions(+), 984 deletions(-)
> create mode 100644 drivers/crypto/ccp/sev-dev.c
> create mode 100644 drivers/crypto/ccp/sev-dev.h
> create mode 100644 drivers/crypto/ccp/tee-dev.c
> create mode 100644 drivers/crypto/ccp/tee-dev.h
> create mode 100644 include/linux/psp-tee.h
All applied. Thanks.
--
Email: Herbert Xu <[email protected]>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
Hi Herbert,
On 20/12/19 12:34 pm, Herbert Xu wrote:
> On Wed, Dec 04, 2019 at 11:48:57AM +0530, Rijo Thomas wrote:
>> The goal of this patch series is to introduce TEE (Trusted Execution
>> Environment) interface support to AMD Secure Processor driver. The
>> TEE is a secure area of a processor which ensures that sensitive data
>> is stored, processed and protected in an isolated and trusted
>> environment. The Platform Security Processor (PSP) is a dedicated
>> processor which provides TEE to enable HW platform security. It offers
>> protection against software attacks generated in Rich Operating System
>> (Rich OS) such as Linux running on x86.
>>
>> Based on the platform feature support, the PSP is capable of supporting
>> either SEV (Secure Encrypted Virtualization) and/or TEE. The first three
>> patches in this series is about moving SEV specific functions and data
>> structures from PSP device driver file to a dedicated SEV interface
>> driver file. The last two patches add TEE interface support to AMD
>> Secure Processor driver. This TEE interface will be used by AMD-TEE
>> driver to submit command buffers for processing in PSP Trusted Execution
>> Environment.
>>
>> v3:
>> * Rebased the patches onto cryptodev-2.6 tree with base commit
>> 4ee812f6143d (crypto: vmx - Avoid weird build failures)
>>
>> v2:
>> * Rebased the patches on cryptodev-2.6 tree with base commit
>> d158367682cd (crypto: atmel - Fix selection of CRYPTO_AUTHENC)
>> * Regenerated patch with correct diff-stat to show file rename
>> * Used Co-developed-by: tag to give proper credit to co-author
>>
>> Rijo Thomas (6):
>> crypto: ccp - rename psp-dev files to sev-dev
>> crypto: ccp - create a generic psp-dev file
>> crypto: ccp - move SEV vdata to a dedicated data structure
>> crypto: ccp - check whether PSP supports SEV or TEE before
>> initialization
>> crypto: ccp - add TEE support for Raven Ridge
>> crypto: ccp - provide in-kernel API to submit TEE commands
>>
>> drivers/crypto/ccp/Makefile | 4 +-
>> drivers/crypto/ccp/psp-dev.c | 1033 ++++------------------------------------
>> drivers/crypto/ccp/psp-dev.h | 51 +-
>> drivers/crypto/ccp/sev-dev.c | 1068 ++++++++++++++++++++++++++++++++++++++++++
>> drivers/crypto/ccp/sev-dev.h | 63 +++
>> drivers/crypto/ccp/sp-dev.h | 17 +-
>> drivers/crypto/ccp/sp-pci.c | 43 +-
>> drivers/crypto/ccp/tee-dev.c | 364 ++++++++++++++
>> drivers/crypto/ccp/tee-dev.h | 110 +++++
>> include/linux/psp-tee.h | 73 +++
>> 10 files changed, 1842 insertions(+), 984 deletions(-)
>> create mode 100644 drivers/crypto/ccp/sev-dev.c
>> create mode 100644 drivers/crypto/ccp/sev-dev.h
>> create mode 100644 drivers/crypto/ccp/tee-dev.c
>> create mode 100644 drivers/crypto/ccp/tee-dev.h
>> create mode 100644 include/linux/psp-tee.h
>
> All applied. Thanks.
>
Thank you for pulling in the changes!
Can you also pull in the patch series titled - TEE driver for AMD APUs? It is
related to this patch series.
Jens who is the TEE subsystem maintainer has given an Acked-by for the
patch series. Please refer link: https://lkml.org/lkml/2019/12/16/608
Thanks,
Rijo
On Tue, Dec 24, 2019 at 04:25:55PM +0530, Thomas, Rijo-john wrote:
>
> Thank you for pulling in the changes!
> Can you also pull in the patch series titled - TEE driver for AMD APUs? It is
> related to this patch series.
>
> Jens who is the TEE subsystem maintainer has given an Acked-by for the
> patch series. Please refer link: https://lkml.org/lkml/2019/12/16/608
Please resubmit the patches with the acks attached to linux-crypto.
Thanks,
--
Email: Herbert Xu <[email protected]>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt