[PATCH 5/5] crypto: ccp: Add support for DBC over PSP mailbox

From: Mario Limonciello
Date: Thu Sep 07 2023 - 14:50:04 EST


On some SOCs DBC is supported through the PSP mailbox instead of
the platform mailbox. This capability is advertised in the PSP
capabilities register. Allow using this communication path if
supported.

Signed-off-by: Mario Limonciello <mario.limonciello@xxxxxxx>
---
drivers/crypto/ccp/dbc.c | 43 +++++++++++++++++++++++++++---------
drivers/crypto/ccp/dbc.h | 2 ++
drivers/crypto/ccp/psp-dev.c | 32 +++++++++++----------------
drivers/crypto/ccp/psp-dev.h | 16 ++++++++++++++
4 files changed, 64 insertions(+), 29 deletions(-)

diff --git a/drivers/crypto/ccp/dbc.c b/drivers/crypto/ccp/dbc.c
index ebd7279d4001..d373caab52f8 100644
--- a/drivers/crypto/ccp/dbc.c
+++ b/drivers/crypto/ccp/dbc.c
@@ -9,6 +9,7 @@

#include "dbc.h"

+#define DBC_DEFAULT_TIMEOUT (10 * MSEC_PER_SEC)
struct error_map {
u32 psp;
int ret;
@@ -37,13 +38,28 @@ static struct error_map error_codes[] = {
{0x0, 0x0},
};

-static int send_dbc_cmd(struct psp_dbc_device *dbc_dev,
- enum psp_platform_access_msg msg)
+static inline int send_dbc_cmd_thru_ext(struct psp_dbc_device *dbc_dev, int msg)
+{
+ dbc_dev->mbox->ext_req.header.sub_cmd_id = msg;
+
+ return psp_extended_mailbox_cmd(dbc_dev->psp,
+ DBC_DEFAULT_TIMEOUT,
+ (struct psp_ext_request *)dbc_dev->mbox);
+}
+
+static inline int send_dbc_cmd_thru_pa(struct psp_dbc_device *dbc_dev, int msg)
+{
+ return psp_send_platform_access_msg(msg,
+ (struct psp_request *)dbc_dev->mbox);
+}
+
+static int send_dbc_cmd(struct psp_dbc_device *dbc_dev, int msg)
{
int ret;

*dbc_dev->result = 0;
- ret = psp_send_platform_access_msg(msg, (struct psp_request *)dbc_dev->mbox);
+ ret = dbc_dev->use_ext ? send_dbc_cmd_thru_ext(dbc_dev, msg) :
+ send_dbc_cmd_thru_pa(dbc_dev, msg);
if (ret == -EIO) {
int i;

@@ -192,9 +208,6 @@ int dbc_dev_init(struct psp_device *psp)
struct psp_dbc_device *dbc_dev;
int ret;

- if (!PSP_FEATURE(psp, DBC))
- return 0;
-
dbc_dev = devm_kzalloc(dev, sizeof(*dbc_dev), GFP_KERNEL);
if (!dbc_dev)
return -ENOMEM;
@@ -208,10 +221,20 @@ int dbc_dev_init(struct psp_device *psp)

psp->dbc_data = dbc_dev;
dbc_dev->dev = dev;
- dbc_dev->payload_size = &dbc_dev->mbox->pa_req.header.payload_size;
- dbc_dev->result = &dbc_dev->mbox->pa_req.header.status;
- dbc_dev->payload = &dbc_dev->mbox->pa_req.buf;
- dbc_dev->header_size = sizeof(struct psp_req_buffer_hdr);
+ dbc_dev->psp = psp;
+
+ if (PSP_CAPABILITY(psp, DBC_THRU_EXT)) {
+ dbc_dev->use_ext = true;
+ dbc_dev->payload_size = &dbc_dev->mbox->ext_req.header.payload_size;
+ dbc_dev->result = &dbc_dev->mbox->ext_req.header.status;
+ dbc_dev->payload = &dbc_dev->mbox->ext_req.buf;
+ dbc_dev->header_size = sizeof(struct psp_ext_req_buffer_hdr);
+ } else {
+ dbc_dev->payload_size = &dbc_dev->mbox->pa_req.header.payload_size;
+ dbc_dev->result = &dbc_dev->mbox->pa_req.header.status;
+ dbc_dev->payload = &dbc_dev->mbox->pa_req.buf;
+ dbc_dev->header_size = sizeof(struct psp_req_buffer_hdr);
+ }

ret = send_dbc_nonce(dbc_dev);
if (ret == -EACCES) {
diff --git a/drivers/crypto/ccp/dbc.h b/drivers/crypto/ccp/dbc.h
index 184646ee55bb..e0fecbe92eb1 100644
--- a/drivers/crypto/ccp/dbc.h
+++ b/drivers/crypto/ccp/dbc.h
@@ -20,6 +20,7 @@

struct psp_dbc_device {
struct device *dev;
+ struct psp_device *psp;

union dbc_buffer *mbox;

@@ -37,6 +38,7 @@ struct psp_dbc_device {

union dbc_buffer {
struct psp_request pa_req;
+ struct psp_ext_request ext_req;
};

void dbc_dev_destroy(struct psp_device *psp);
diff --git a/drivers/crypto/ccp/psp-dev.c b/drivers/crypto/ccp/psp-dev.c
index 5f61b23695d5..124a2e0c8999 100644
--- a/drivers/crypto/ccp/psp-dev.c
+++ b/drivers/crypto/ccp/psp-dev.c
@@ -187,23 +187,6 @@ static int psp_check_tee_support(struct psp_device *psp)
return 0;
}

-static void psp_init_platform_access(struct psp_device *psp)
-{
- int ret;
-
- ret = platform_access_dev_init(psp);
- if (ret) {
- dev_warn(psp->dev, "platform access init failed: %d\n", ret);
- return;
- }
-
- /* dbc must come after platform access as it tests the feature */
- ret = dbc_dev_init(psp);
- if (ret)
- dev_warn(psp->dev, "failed to init dynamic boost control: %d\n",
- ret);
-}
-
static int psp_init(struct psp_device *psp)
{
int ret;
@@ -220,8 +203,19 @@ static int psp_init(struct psp_device *psp)
return ret;
}

- if (psp->vdata->platform_access)
- psp_init_platform_access(psp);
+ if (psp->vdata->platform_access) {
+ ret = platform_access_dev_init(psp);
+ if (ret)
+ return ret;
+ }
+
+ /* dbc must come after platform access as it tests the feature */
+ if (PSP_FEATURE(psp, DBC) ||
+ PSP_CAPABILITY(psp, DBC_THRU_EXT)) {
+ ret = dbc_dev_init(psp);
+ if (ret)
+ return ret;
+ }

return 0;
}
diff --git a/drivers/crypto/ccp/psp-dev.h b/drivers/crypto/ccp/psp-dev.h
index 396a80d846c0..ae582ba63729 100644
--- a/drivers/crypto/ccp/psp-dev.h
+++ b/drivers/crypto/ccp/psp-dev.h
@@ -16,6 +16,7 @@
#include <linux/interrupt.h>
#include <linux/mutex.h>
#include <linux/psp.h>
+#include <linux/psp-platform-access.h>

#include "sp-dev.h"

@@ -56,6 +57,7 @@ struct psp_device *psp_get_master_device(void);

#define PSP_CAPABILITY_SEV BIT(0)
#define PSP_CAPABILITY_TEE BIT(1)
+#define PSP_CAPABILITY_DBC_THRU_EXT BIT(2)
#define PSP_CAPABILITY_PSP_SECURITY_REPORTING BIT(7)

#define PSP_CAPABILITY_PSP_SECURITY_OFFSET 8
@@ -108,6 +110,20 @@ struct psp_ext_request {
void *buf;
} __packed;

+/**
+ * enum psp_sub_cmd - PSP mailbox sub commands
+ * @PSP_SUB_CMD_DBC_GET_NONCE: Get nonce from DBC
+ * @PSP_SUB_CMD_DBC_SET_UID: Set UID for DBC
+ * @PSP_SUB_CMD_DBC_GET_PARAMETER: Get parameter from DBC
+ * @PSP_SUB_CMD_DBC_SET_PARAMETER: Set parameter for DBC
+ */
+enum psp_sub_cmd {
+ PSP_SUB_CMD_DBC_GET_NONCE = PSP_DYNAMIC_BOOST_GET_NONCE,
+ PSP_SUB_CMD_DBC_SET_UID = PSP_DYNAMIC_BOOST_SET_UID,
+ PSP_SUB_CMD_DBC_GET_PARAMETER = PSP_DYNAMIC_BOOST_GET_PARAMETER,
+ PSP_SUB_CMD_DBC_SET_PARAMETER = PSP_DYNAMIC_BOOST_SET_PARAMETER,
+};
+
int psp_extended_mailbox_cmd(struct psp_device *psp, unsigned int timeout_msecs,
struct psp_ext_request *req);
#endif /* __PSP_DEV_H */
--
2.34.1