crypto: ccp - Move direct access to some PSP registers out of TEE
authorTom Lendacky <thomas.lendacky@amd.com>
Thu, 7 Sep 2023 18:48:42 +0000 (13:48 -0500)
committerHerbert Xu <herbert@gondor.apana.org.au>
Fri, 15 Sep 2023 10:29:45 +0000 (18:29 +0800)
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.

Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
Reviewed-by: Rijo Thomas <Rijo-john.Thomas@amd.com>
Tested-by: Rijo Thomas <Rijo-john.Thomas@amd.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
drivers/crypto/ccp/psp-dev.c
drivers/crypto/ccp/psp-dev.h
drivers/crypto/ccp/sp-dev.h
drivers/crypto/ccp/sp-pci.c
drivers/crypto/ccp/tee-dev.c
drivers/crypto/ccp/tee-dev.h

index d42d7bc623523dad25f4665d18405b499be2bee9..3258c4612e1444cd8ac28aceb61a8d09871cfe3c 100644 (file)
@@ -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"
 
 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)
index 8a4de69399c59abc8271ca346c88c30e0dc2682f..d917657c6085ad25346741eff01537ac49050039 100644 (file)
@@ -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 */
index 2329ad524b4945b29bac80e1b0843c4de6a72a54..c4e125efe6c706147f35dc605871912199e0405f 100644 (file)
@@ -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;
index b6ab56abeb682f89f913558e957ac364d57fbeec..d1aedc5c1a681d0ba8d80e6c407a7f19f54eda70 100644 (file)
@@ -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 */
index 5560bf8329a127eb335683514aee86a08d868162..5e1d80724678d03f7fc75e89c3f50ae867087dde 100644 (file)
@@ -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, &reg);
+       ret = psp_mailbox_command(tee->psp, PSP_CMD_TEE_RING_INIT, cmd,
+                                 TEE_DEFAULT_CMD_TIMEOUT, &reg);
        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, &reg);
+       ret = psp_mailbox_command(tee->psp, PSP_CMD_TEE_RING_DESTROY, NULL,
+                                 TEE_DEFAULT_CMD_TIMEOUT, &reg);
        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;
index 49d26158b71e31635557d971ad19a148b9859043..ea9a2b7c05f577c9919836e68ff92dc7de8bc10e 100644 (file)
 #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