crypto: ccp: Add another mailbox interrupt support for PSP sending command to X86
Upstream: no The existing kernel supports only interrupt for the mailbox interface for X86 sending commands to PSP and PSP to ack, e.g. the SEV commands. However, some PSP-based security modules in Hygon CPU, such as TPCM and TDM(Trusted Dynamic Measuring), needs sending commands/notifications proactively to X86 core via interrupt and a 2nd mailbox interface. Similar to the existing one, the 2nd mailbox consists of a 32-bits command register and two 32-bits data registers. The PSP interrupt handling needs to add this interrupt support; besides, in order to support user defined command handler, a callback registration function is also provided. Up to 16 command callbacks is supported, which are indexed by command IDs. Currently, command ID 0 is assigned to TPCM and 1 to TDM, while others are reserved. Currently, Hygon PSP does not support bootloader info reg, remove the value of bootloader_info_reg. Signed-off-by: chench <chench@hygon.cn> Signed-off-by: hanliyang <hanliyang@hygon.cn>
This commit is contained in:
parent
f94ca9e54f
commit
88a4c829d3
|
@ -60,3 +60,10 @@ config CRYPTO_DEV_CCP_DEBUGFS
|
|||
help
|
||||
Expose CCP device information such as operation statistics, feature
|
||||
information, and descriptor queue contents.
|
||||
|
||||
config HYGON_PSP2CPU_CMD
|
||||
bool "Hygon PSP2CPU Command Interface"
|
||||
default y
|
||||
depends on CRYPTO_DEV_SP_PSP
|
||||
help
|
||||
Hygon PSP2CPU Command Support
|
||||
|
|
|
@ -104,3 +104,122 @@ int psp_do_cmd(int cmd, void *data, int *psp_ret)
|
|||
return rc;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(psp_do_cmd);
|
||||
|
||||
#ifdef CONFIG_HYGON_PSP2CPU_CMD
|
||||
|
||||
static DEFINE_SPINLOCK(p2c_notifier_lock);
|
||||
static p2c_notifier_t p2c_notifiers[P2C_NOTIFIERS_MAX] = {NULL};
|
||||
|
||||
int psp_register_cmd_notifier(uint32_t cmd_id, p2c_notifier_t notifier)
|
||||
{
|
||||
int ret = -ENODEV;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&p2c_notifier_lock, flags);
|
||||
|
||||
if (cmd_id < P2C_NOTIFIERS_MAX && !p2c_notifiers[cmd_id]) {
|
||||
p2c_notifiers[cmd_id] = notifier;
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&p2c_notifier_lock, flags);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(psp_register_cmd_notifier);
|
||||
|
||||
int psp_unregister_cmd_notifier(uint32_t cmd_id, p2c_notifier_t notifier)
|
||||
{
|
||||
int ret = -ENODEV;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&p2c_notifier_lock, flags);
|
||||
|
||||
if (cmd_id < P2C_NOTIFIERS_MAX && p2c_notifiers[cmd_id] == notifier) {
|
||||
p2c_notifiers[cmd_id] = NULL;
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&p2c_notifier_lock, flags);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(psp_unregister_cmd_notifier);
|
||||
|
||||
#define PSP2CPU_MAX_LOOP 100
|
||||
|
||||
static irqreturn_t psp_irq_handler_hygon(int irq, void *data)
|
||||
{
|
||||
struct psp_device *psp = data;
|
||||
struct sev_device *sev = psp->sev_irq_data;
|
||||
unsigned int status;
|
||||
int reg;
|
||||
unsigned long flags;
|
||||
int count = 0;
|
||||
uint32_t p2c_cmd;
|
||||
uint32_t p2c_lo_data;
|
||||
uint32_t p2c_hi_data;
|
||||
uint64_t p2c_data;
|
||||
|
||||
/* Read the interrupt status: */
|
||||
status = ioread32(psp->io_regs + psp->vdata->intsts_reg);
|
||||
|
||||
while (status && (count++ < PSP2CPU_MAX_LOOP)) {
|
||||
/* Clear the interrupt status by writing the same value we read. */
|
||||
iowrite32(status, psp->io_regs + psp->vdata->intsts_reg);
|
||||
|
||||
/* Check if it is command completion: */
|
||||
if (status & SEV_CMD_COMPLETE) {
|
||||
/* Check if it is SEV command completion: */
|
||||
reg = ioread32(psp->io_regs + psp->vdata->sev->cmdresp_reg);
|
||||
if (reg & PSP_CMDRESP_RESP) {
|
||||
sev->int_rcvd = 1;
|
||||
wake_up(&sev->int_queue);
|
||||
}
|
||||
}
|
||||
|
||||
if (status & PSP_X86_CMD) {
|
||||
/* Check if it is P2C command completion: */
|
||||
reg = ioread32(psp->io_regs + psp->vdata->p2c_cmdresp_reg);
|
||||
if (!(reg & PSP_CMDRESP_RESP)) {
|
||||
p2c_lo_data = ioread32(psp->io_regs +
|
||||
psp->vdata->p2c_cmdbuff_addr_lo_reg);
|
||||
p2c_hi_data = ioread32(psp->io_regs +
|
||||
psp->vdata->p2c_cmdbuff_addr_hi_reg);
|
||||
p2c_data = (((uint64_t)(p2c_hi_data) << 32) +
|
||||
((uint64_t)(p2c_lo_data)));
|
||||
p2c_cmd = (uint32_t)(reg & SEV_CMDRESP_IOC);
|
||||
if (p2c_cmd < P2C_NOTIFIERS_MAX) {
|
||||
spin_lock_irqsave(&p2c_notifier_lock, flags);
|
||||
|
||||
if (p2c_notifiers[p2c_cmd])
|
||||
p2c_notifiers[p2c_cmd](p2c_cmd, p2c_data);
|
||||
|
||||
spin_unlock_irqrestore(&p2c_notifier_lock, flags);
|
||||
}
|
||||
|
||||
reg |= PSP_CMDRESP_RESP;
|
||||
iowrite32(reg, psp->io_regs + psp->vdata->p2c_cmdresp_reg);
|
||||
}
|
||||
}
|
||||
status = ioread32(psp->io_regs + psp->vdata->intsts_reg);
|
||||
}
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
int sp_request_hygon_psp_irq(struct sp_device *sp, irq_handler_t handler,
|
||||
const char *name, void *data)
|
||||
{
|
||||
return sp_request_psp_irq(sp, psp_irq_handler_hygon, name, data);
|
||||
}
|
||||
|
||||
#else /* !CONFIG_HYGON_PSP2CPU_CMD */
|
||||
|
||||
int sp_request_hygon_psp_irq(struct sp_device *sp, irq_handler_t handler,
|
||||
const char *name, void *data)
|
||||
{
|
||||
return sp_request_psp_irq(sp, handler, name, data);
|
||||
}
|
||||
|
||||
#endif /* CONFIG_HYGON_PSP2CPU_CMD */
|
||||
|
|
|
@ -11,12 +11,18 @@
|
|||
#define __CCP_HYGON_PSP_DEV_H__
|
||||
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/bits.h>
|
||||
|
||||
#include "sp-dev.h"
|
||||
|
||||
#include "../psp-dev.h"
|
||||
#include "../sev-dev.h"
|
||||
|
||||
#ifdef CONFIG_HYGON_PSP2CPU_CMD
|
||||
#define PSP_X86_CMD BIT(2)
|
||||
#define P2C_NOTIFIERS_MAX 16
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Hooks table: a table of function and variable pointers filled in
|
||||
* when psp init.
|
||||
|
@ -37,5 +43,7 @@ extern struct hygon_psp_hooks_table {
|
|||
} hygon_psp_hooks;
|
||||
|
||||
int fixup_hygon_psp_caps(struct psp_device *psp);
|
||||
int sp_request_hygon_psp_irq(struct sp_device *sp, irq_handler_t handler,
|
||||
const char *name, void *data);
|
||||
|
||||
#endif /* __CCP_HYGON_PSP_DEV_H__ */
|
||||
|
|
|
@ -22,10 +22,14 @@ static const struct sev_vdata csvv1 = {
|
|||
|
||||
static const struct psp_vdata pspv1 = {
|
||||
.sev = &csvv1,
|
||||
.bootloader_info_reg = 0x105ec, /* C2PMSG_59 */
|
||||
.feature_reg = 0x105fc, /* C2PMSG_63 */
|
||||
.inten_reg = 0x10610, /* P2CMSG_INTEN */
|
||||
.intsts_reg = 0x10614, /* P2CMSG_INTSTS */
|
||||
#ifdef CONFIG_HYGON_PSP2CPU_CMD
|
||||
.p2c_cmdresp_reg = 0x105e8,
|
||||
.p2c_cmdbuff_addr_lo_reg = 0x105ec,
|
||||
.p2c_cmdbuff_addr_hi_reg = 0x105f0,
|
||||
#endif
|
||||
};
|
||||
|
||||
static const struct psp_vdata pspv2 = {
|
||||
|
@ -33,6 +37,11 @@ static const struct psp_vdata pspv2 = {
|
|||
.feature_reg = 0x105fc,
|
||||
.inten_reg = 0x10670,
|
||||
.intsts_reg = 0x10674,
|
||||
#ifdef CONFIG_HYGON_PSP2CPU_CMD
|
||||
.p2c_cmdresp_reg = 0x105e8,
|
||||
.p2c_cmdbuff_addr_lo_reg = 0x105ec,
|
||||
.p2c_cmdbuff_addr_hi_reg = 0x105f0,
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -187,7 +187,11 @@ int psp_dev_init(struct sp_device *sp)
|
|||
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 (is_vendor_hygon()) {
|
||||
ret = sp_request_hygon_psp_irq(psp->sp, psp_irq_handler, psp->name, psp);
|
||||
} else {
|
||||
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;
|
||||
|
|
|
@ -76,6 +76,11 @@ struct psp_vdata {
|
|||
const unsigned int intsts_reg;
|
||||
const unsigned int bootloader_info_reg;
|
||||
const unsigned int platform_features;
|
||||
#ifdef CONFIG_HYGON_PSP2CPU_CMD
|
||||
const unsigned int p2c_cmdresp_reg;
|
||||
const unsigned int p2c_cmdbuff_addr_lo_reg;
|
||||
const unsigned int p2c_cmdbuff_addr_hi_reg;
|
||||
#endif
|
||||
};
|
||||
|
||||
/* Structure to hold SP device data */
|
||||
|
|
|
@ -156,4 +156,18 @@ csv_issue_ringbuf_cmds_external_user(struct file *filep, int *psp_ret) { return
|
|||
|
||||
#endif /* CONFIG_CRYPTO_DEV_SP_PSP */
|
||||
|
||||
typedef int (*p2c_notifier_t)(uint32_t id, uint64_t data);
|
||||
|
||||
#ifdef CONFIG_HYGON_PSP2CPU_CMD
|
||||
|
||||
int psp_register_cmd_notifier(uint32_t cmd_id, p2c_notifier_t notifier);
|
||||
int psp_unregister_cmd_notifier(uint32_t cmd_id, p2c_notifier_t notifier);
|
||||
|
||||
#else /* !CONFIG_HYGON_PSP2CPU_CMD */
|
||||
|
||||
int psp_register_cmd_notifier(uint32_t cmd_id, p2c_notifier_t notifier) { return -ENODEV; }
|
||||
int psp_unregister_cmd_notifier(uint32_t cmd_id, p2c_notifier_t notifier) { return -ENODEV; }
|
||||
|
||||
#endif /* CONFIG_HYGON_PSP2CPU_CMD */
|
||||
|
||||
#endif /* __PSP_HYGON_H__ */
|
||||
|
|
Loading…
Reference in New Issue