On 9/8/2023 12:18 AM, Mario Limonciello wrote: > From: Tom Lendacky <thomas.lendacky@xxxxxxx> > > With the PSP mailbox registers supporting more than just TEE, access to > them must be maintained and serialized by the PSP device support. Remove > TEE support direct access and create an interface in the PSP support > where the register access can be controlled/serialized. > Reviewed-by: Rijo Thomas <Rijo-john.Thomas@xxxxxxx> Tested-by: Rijo Thomas <Rijo-john.Thomas@xxxxxxx> > Signed-off-by: Tom Lendacky <thomas.lendacky@xxxxxxx> > Signed-off-by: Mario Limonciello <mario.limonciello@xxxxxxx> > --- > drivers/crypto/ccp/psp-dev.c | 60 ++++++++++++++++++++++++++++++++++++ > drivers/crypto/ccp/psp-dev.h | 18 +++++++++++ > drivers/crypto/ccp/sp-dev.h | 3 ++ > drivers/crypto/ccp/sp-pci.c | 18 +++++++---- > drivers/crypto/ccp/tee-dev.c | 48 ++++++----------------------- > drivers/crypto/ccp/tee-dev.h | 15 ++------- > 6 files changed, 104 insertions(+), 58 deletions(-) > > diff --git a/drivers/crypto/ccp/psp-dev.c b/drivers/crypto/ccp/psp-dev.c > index d42d7bc62352..3258c4612e14 100644 > --- a/drivers/crypto/ccp/psp-dev.c > +++ b/drivers/crypto/ccp/psp-dev.c > @@ -9,6 +9,9 @@ > > #include <linux/kernel.h> > #include <linux/irqreturn.h> > +#include <linux/mutex.h> > +#include <linux/bitfield.h> > +#include <linux/delay.h> > > #include "sp-dev.h" > #include "psp-dev.h" > @@ -19,6 +22,62 @@ > > struct psp_device *psp_master; > > +#define PSP_C2PMSG_17_CMDRESP_CMD GENMASK(19, 16) > + > +static int psp_mailbox_poll(const void __iomem *cmdresp_reg, unsigned int *cmdresp, > + unsigned int timeout_msecs) > +{ > + while (true) { > + *cmdresp = ioread32(cmdresp_reg); > + if (FIELD_GET(PSP_CMDRESP_RESP, *cmdresp)) > + return 0; > + > + if (!timeout_msecs--) > + break; > + > + usleep_range(1000, 1100); > + } > + > + return -ETIMEDOUT; > +} > + > +int psp_mailbox_command(struct psp_device *psp, enum psp_cmd cmd, void *cmdbuff, > + unsigned int timeout_msecs, unsigned int *cmdresp) > +{ > + void __iomem *cmdresp_reg, *cmdbuff_lo_reg, *cmdbuff_hi_reg; > + int ret; > + > + if (!psp || !psp->vdata || !psp->vdata->cmdresp_reg || > + !psp->vdata->cmdbuff_addr_lo_reg || !psp->vdata->cmdbuff_addr_hi_reg) > + return -ENODEV; > + > + cmdresp_reg = psp->io_regs + psp->vdata->cmdresp_reg; > + cmdbuff_lo_reg = psp->io_regs + psp->vdata->cmdbuff_addr_lo_reg; > + cmdbuff_hi_reg = psp->io_regs + psp->vdata->cmdbuff_addr_hi_reg; > + > + mutex_lock(&psp->mailbox_mutex); > + > + /* Ensure mailbox is ready for a command */ > + ret = -EBUSY; > + if (psp_mailbox_poll(cmdresp_reg, cmdresp, 0)) > + goto unlock; > + > + if (cmdbuff) { > + iowrite32(lower_32_bits(__psp_pa(cmdbuff)), cmdbuff_lo_reg); > + iowrite32(upper_32_bits(__psp_pa(cmdbuff)), cmdbuff_hi_reg); > + } > + > + *cmdresp = FIELD_PREP(PSP_C2PMSG_17_CMDRESP_CMD, cmd); > + iowrite32(*cmdresp, cmdresp_reg); > + > + ret = psp_mailbox_poll(cmdresp_reg, cmdresp, timeout_msecs); > + > +unlock: > + mutex_unlock(&psp->mailbox_mutex); > + > + return ret; > +} > + > static struct psp_device *psp_alloc_struct(struct sp_device *sp) > { > struct device *dev = sp->dev; > @@ -164,6 +223,7 @@ int psp_dev_init(struct sp_device *sp) > } > > psp->io_regs = sp->io_map; > + mutex_init(&psp->mailbox_mutex); > > ret = psp_get_capability(psp); > if (ret) > diff --git a/drivers/crypto/ccp/psp-dev.h b/drivers/crypto/ccp/psp-dev.h > index 8a4de69399c5..d917657c6085 100644 > --- a/drivers/crypto/ccp/psp-dev.h > +++ b/drivers/crypto/ccp/psp-dev.h > @@ -14,6 +14,8 @@ > #include <linux/list.h> > #include <linux/bits.h> > #include <linux/interrupt.h> > +#include <linux/mutex.h> > +#include <linux/psp.h> > > #include "sp-dev.h" > > @@ -33,6 +35,7 @@ struct psp_device { > struct sp_device *sp; > > void __iomem *io_regs; > + struct mutex mailbox_mutex; > > psp_irq_handler_t sev_irq_handler; > void *sev_irq_data; > @@ -71,4 +74,19 @@ struct psp_device *psp_get_master_device(void); > #define PSP_SECURITY_HSP_TPM_AVAILABLE BIT(10) > #define PSP_SECURITY_ROM_ARMOR_ENFORCED BIT(11) > > +/** > + * enum psp_cmd - PSP mailbox commands > + * @PSP_CMD_TEE_RING_INIT: Initialize TEE ring buffer > + * @PSP_CMD_TEE_RING_DESTROY: Destroy TEE ring buffer > + * @PSP_CMD_MAX: Maximum command id > + */ > +enum psp_cmd { > + PSP_CMD_TEE_RING_INIT = 1, > + PSP_CMD_TEE_RING_DESTROY = 2, > + PSP_CMD_MAX = 15, > +}; > + > +int psp_mailbox_command(struct psp_device *psp, enum psp_cmd cmd, void *cmdbuff, > + unsigned int timeout_msecs, unsigned int *cmdresp); > + > #endif /* __PSP_DEV_H */ > diff --git a/drivers/crypto/ccp/sp-dev.h b/drivers/crypto/ccp/sp-dev.h > index 2329ad524b49..c4e125efe6c7 100644 > --- a/drivers/crypto/ccp/sp-dev.h > +++ b/drivers/crypto/ccp/sp-dev.h > @@ -71,6 +71,9 @@ struct psp_vdata { > const struct sev_vdata *sev; > const struct tee_vdata *tee; > const struct platform_access_vdata *platform_access; > + const unsigned int cmdresp_reg; > + const unsigned int cmdbuff_addr_lo_reg; > + const unsigned int cmdbuff_addr_hi_reg; > 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 b6ab56abeb68..d1aedc5c1a68 100644 > --- a/drivers/crypto/ccp/sp-pci.c > +++ b/drivers/crypto/ccp/sp-pci.c > @@ -418,18 +418,12 @@ static const struct sev_vdata sevv2 = { > }; > > static const struct tee_vdata teev1 = { > - .cmdresp_reg = 0x10544, /* C2PMSG_17 */ > - .cmdbuff_addr_lo_reg = 0x10548, /* C2PMSG_18 */ > - .cmdbuff_addr_hi_reg = 0x1054c, /* C2PMSG_19 */ > .ring_wptr_reg = 0x10550, /* C2PMSG_20 */ > .ring_rptr_reg = 0x10554, /* C2PMSG_21 */ > .info_reg = 0x109e8, /* C2PMSG_58 */ > }; > > static const struct tee_vdata teev2 = { > - .cmdresp_reg = 0x10944, /* C2PMSG_17 */ > - .cmdbuff_addr_lo_reg = 0x10948, /* C2PMSG_18 */ > - .cmdbuff_addr_hi_reg = 0x1094c, /* C2PMSG_19 */ > .ring_wptr_reg = 0x10950, /* C2PMSG_20 */ > .ring_rptr_reg = 0x10954, /* C2PMSG_21 */ > }; > @@ -466,6 +460,9 @@ static const struct psp_vdata pspv2 = { > static const struct psp_vdata pspv3 = { > .tee = &teev1, > .platform_access = &pa_v1, > + .cmdresp_reg = 0x10544, /* C2PMSG_17 */ > + .cmdbuff_addr_lo_reg = 0x10548, /* C2PMSG_18 */ > + .cmdbuff_addr_hi_reg = 0x1054c, /* C2PMSG_19 */ > .bootloader_info_reg = 0x109ec, /* C2PMSG_59 */ > .feature_reg = 0x109fc, /* C2PMSG_63 */ > .inten_reg = 0x10690, /* P2CMSG_INTEN */ > @@ -476,6 +473,9 @@ static const struct psp_vdata pspv3 = { > static const struct psp_vdata pspv4 = { > .sev = &sevv2, > .tee = &teev1, > + .cmdresp_reg = 0x10544, /* C2PMSG_17 */ > + .cmdbuff_addr_lo_reg = 0x10548, /* C2PMSG_18 */ > + .cmdbuff_addr_hi_reg = 0x1054c, /* C2PMSG_19 */ > .bootloader_info_reg = 0x109ec, /* C2PMSG_59 */ > .feature_reg = 0x109fc, /* C2PMSG_63 */ > .inten_reg = 0x10690, /* P2CMSG_INTEN */ > @@ -485,6 +485,9 @@ static const struct psp_vdata pspv4 = { > static const struct psp_vdata pspv5 = { > .tee = &teev2, > .platform_access = &pa_v2, > + .cmdresp_reg = 0x10944, /* C2PMSG_17 */ > + .cmdbuff_addr_lo_reg = 0x10948, /* C2PMSG_18 */ > + .cmdbuff_addr_hi_reg = 0x1094c, /* C2PMSG_19 */ > .feature_reg = 0x109fc, /* C2PMSG_63 */ > .inten_reg = 0x10510, /* P2CMSG_INTEN */ > .intsts_reg = 0x10514, /* P2CMSG_INTSTS */ > @@ -493,6 +496,9 @@ static const struct psp_vdata pspv5 = { > static const struct psp_vdata pspv6 = { > .sev = &sevv2, > .tee = &teev2, > + .cmdresp_reg = 0x10944, /* C2PMSG_17 */ > + .cmdbuff_addr_lo_reg = 0x10948, /* C2PMSG_18 */ > + .cmdbuff_addr_hi_reg = 0x1094c, /* C2PMSG_19 */ > .feature_reg = 0x109fc, /* C2PMSG_63 */ > .inten_reg = 0x10510, /* P2CMSG_INTEN */ > .intsts_reg = 0x10514, /* P2CMSG_INTSTS */ > diff --git a/drivers/crypto/ccp/tee-dev.c b/drivers/crypto/ccp/tee-dev.c > index 5560bf8329a1..5e1d80724678 100644 > --- a/drivers/crypto/ccp/tee-dev.c > +++ b/drivers/crypto/ccp/tee-dev.c > @@ -62,26 +62,6 @@ static void tee_free_ring(struct psp_tee_device *tee) > mutex_destroy(&rb_mgr->mutex); > } > > -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 (FIELD_GET(PSP_CMDRESP_RESP, *reg)) > - 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) > { > @@ -110,7 +90,6 @@ 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; > > @@ -130,23 +109,15 @@ static int tee_init_ring(struct psp_tee_device *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, ®); > + ret = psp_mailbox_command(tee->psp, PSP_CMD_TEE_RING_INIT, cmd, > + TEE_DEFAULT_CMD_TIMEOUT, ®); > if (ret) { > - dev_err(tee->dev, "tee: ring init command timed out\n"); > + dev_err(tee->dev, "tee: ring init command timed out, disabling TEE support\n"); > tee_free_ring(tee); > + psp_dead = true; > goto free_buf; > } > > @@ -174,12 +145,11 @@ static void tee_destroy_ring(struct psp_tee_device *tee) > 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, ®); > + ret = psp_mailbox_command(tee->psp, PSP_CMD_TEE_RING_DESTROY, NULL, > + TEE_DEFAULT_CMD_TIMEOUT, ®); > if (ret) { > - dev_err(tee->dev, "tee: ring destroy command timed out\n"); > + dev_err(tee->dev, "tee: ring destroy command timed out, disabling TEE support\n"); > + psp_dead = true; > } else if (FIELD_GET(PSP_CMDRESP_STS, reg)) { > dev_err(tee->dev, "tee: ring destroy command failed (%#010lx)\n", > FIELD_GET(PSP_CMDRESP_STS, reg)); > @@ -370,7 +340,7 @@ int psp_tee_process_cmd(enum tee_cmd_id cmd_id, void *buf, size_t len, > if (ret) > return ret; > > - ret = tee_wait_cmd_completion(tee, resp, TEE_DEFAULT_TIMEOUT); > + ret = tee_wait_cmd_completion(tee, resp, TEE_DEFAULT_RING_TIMEOUT); > if (ret) { > resp->flag = CMD_RESPONSE_TIMEDOUT; > return ret; > diff --git a/drivers/crypto/ccp/tee-dev.h b/drivers/crypto/ccp/tee-dev.h > index 49d26158b71e..ea9a2b7c05f5 100644 > --- a/drivers/crypto/ccp/tee-dev.h > +++ b/drivers/crypto/ccp/tee-dev.h > @@ -17,21 +17,10 @@ > #include <linux/device.h> > #include <linux/mutex.h> > > -#define TEE_DEFAULT_TIMEOUT 10 > +#define TEE_DEFAULT_CMD_TIMEOUT (10 * MSEC_PER_SEC) > +#define TEE_DEFAULT_RING_TIMEOUT 10 > #define MAX_BUFFER_SIZE 988 > > -/** > - * 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