mirror of
https://github.com/nxp-imx/linux-imx.git
synced 2025-09-03 10:33:11 +02:00
MLK-17841: crypto: caam: Correct bugs in Secure Memory
This patch perform following modifications: - Send and receive SM command regrouped in 1 function - Verify that the JR device to use is valid - Modification of the error handling in the probe Signed-off-by: Franck LENORMAND <franck.lenormand@nxp.com> (Vipul: Fixed merge conflicts) Signed-off-by: Vipul Kumar <vipul_kumar@mentor.com>
This commit is contained in:
parent
02bcf5b98b
commit
345ead4338
|
@ -59,51 +59,43 @@ void sm_show_page(struct device *dev, struct sm_page_descriptor *pgdesc)
|
||||||
|
|
||||||
#define INITIAL_DESCSZ 16 /* size of tmp buffer for descriptor const. */
|
#define INITIAL_DESCSZ 16 /* size of tmp buffer for descriptor const. */
|
||||||
|
|
||||||
static __always_inline int sm_set_cmd_reg(struct caam_drv_private_sm *smpriv,
|
static __always_inline u32 sm_send_cmd(struct caam_drv_private_sm *smpriv,
|
||||||
struct caam_drv_private_jr *jrpriv,
|
|
||||||
u32 val)
|
|
||||||
{
|
|
||||||
|
|
||||||
if (smpriv->sm_reg_offset == SM_V1_OFFSET) {
|
|
||||||
struct caam_secure_mem_v1 *sm_regs_v1;
|
|
||||||
|
|
||||||
sm_regs_v1 = (struct caam_secure_mem_v1 *)
|
|
||||||
((void *)jrpriv->rregs + SM_V1_OFFSET);
|
|
||||||
wr_reg32(&sm_regs_v1->sm_cmd, val);
|
|
||||||
|
|
||||||
} else if (smpriv->sm_reg_offset == SM_V2_OFFSET) {
|
|
||||||
struct caam_secure_mem_v2 *sm_regs_v2;
|
|
||||||
|
|
||||||
sm_regs_v2 = (struct caam_secure_mem_v2 *)
|
|
||||||
((void *)jrpriv->rregs + SM_V2_OFFSET);
|
|
||||||
wr_reg32(&sm_regs_v2->sm_cmd, val);
|
|
||||||
} else {
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static __always_inline u32 sm_get_status_reg(struct caam_drv_private_sm *smpriv,
|
|
||||||
struct caam_drv_private_jr *jrpriv,
|
struct caam_drv_private_jr *jrpriv,
|
||||||
u32 *val)
|
u32 cmd, u32 *status)
|
||||||
{
|
{
|
||||||
|
void __iomem *write_address;
|
||||||
|
void __iomem *read_address;
|
||||||
|
|
||||||
if (smpriv->sm_reg_offset == SM_V1_OFFSET) {
|
if (smpriv->sm_reg_offset == SM_V1_OFFSET) {
|
||||||
struct caam_secure_mem_v1 *sm_regs_v1;
|
struct caam_secure_mem_v1 *sm_regs_v1;
|
||||||
|
|
||||||
sm_regs_v1 = (struct caam_secure_mem_v1 *)
|
sm_regs_v1 = (struct caam_secure_mem_v1 *)
|
||||||
((void *)jrpriv->rregs + SM_V1_OFFSET);
|
((void *)jrpriv->rregs + SM_V1_OFFSET);
|
||||||
*val = rd_reg32(&sm_regs_v1->sm_status);
|
write_address = &sm_regs_v1->sm_cmd;
|
||||||
|
read_address = &sm_regs_v1->sm_status;
|
||||||
|
|
||||||
} else if (smpriv->sm_reg_offset == SM_V2_OFFSET) {
|
} else if (smpriv->sm_reg_offset == SM_V2_OFFSET) {
|
||||||
struct caam_secure_mem_v2 *sm_regs_v2;
|
struct caam_secure_mem_v2 *sm_regs_v2;
|
||||||
|
|
||||||
sm_regs_v2 = (struct caam_secure_mem_v2 *)
|
sm_regs_v2 = (struct caam_secure_mem_v2 *)
|
||||||
((void *)jrpriv->rregs + SM_V2_OFFSET);
|
((void *)jrpriv->rregs + SM_V2_OFFSET);
|
||||||
*val = rd_reg32(&sm_regs_v2->sm_status);
|
write_address = &sm_regs_v2->sm_cmd;
|
||||||
|
read_address = &sm_regs_v2->sm_status;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
wr_reg32(write_address, cmd);
|
||||||
|
|
||||||
|
udelay(10);
|
||||||
|
|
||||||
|
/* Read until the command has terminated and the status is correct */
|
||||||
|
do {
|
||||||
|
*status = rd_reg32(read_address);
|
||||||
|
} while (((*status & SMCS_CMDERR_MASK) >> SMCS_CMDERR_SHIFT)
|
||||||
|
== SMCS_CMDERR_INCOMP);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -997,6 +989,7 @@ int caam_sm_startup(struct platform_device *pdev)
|
||||||
struct platform_device *sm_pdev;
|
struct platform_device *sm_pdev;
|
||||||
struct sm_page_descriptor *lpagedesc;
|
struct sm_page_descriptor *lpagedesc;
|
||||||
u32 page, pgstat, lpagect, detectedpage, smvid, smpart;
|
u32 page, pgstat, lpagect, detectedpage, smvid, smpart;
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
struct device_node *np;
|
struct device_node *np;
|
||||||
ctrldev = &pdev->dev;
|
ctrldev = &pdev->dev;
|
||||||
|
@ -1006,8 +999,10 @@ int caam_sm_startup(struct platform_device *pdev)
|
||||||
* If ctrlpriv is NULL, it's probably because the caam driver wasn't
|
* If ctrlpriv is NULL, it's probably because the caam driver wasn't
|
||||||
* properly initialized (e.g. RNG4 init failed). Thus, bail out here.
|
* properly initialized (e.g. RNG4 init failed). Thus, bail out here.
|
||||||
*/
|
*/
|
||||||
if (!ctrlpriv)
|
if (!ctrlpriv) {
|
||||||
return -ENODEV;
|
ret = -ENODEV;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Set up the private block for secure memory
|
* Set up the private block for secure memory
|
||||||
|
@ -1016,7 +1011,8 @@ int caam_sm_startup(struct platform_device *pdev)
|
||||||
smpriv = kzalloc(sizeof(struct caam_drv_private_sm), GFP_KERNEL);
|
smpriv = kzalloc(sizeof(struct caam_drv_private_sm), GFP_KERNEL);
|
||||||
if (smpriv == NULL) {
|
if (smpriv == NULL) {
|
||||||
dev_err(ctrldev, "can't alloc private mem for secure memory\n");
|
dev_err(ctrldev, "can't alloc private mem for secure memory\n");
|
||||||
return -ENOMEM;
|
ret = -ENOMEM;
|
||||||
|
goto exit;
|
||||||
}
|
}
|
||||||
smpriv->parentdev = ctrldev; /* copy of parent dev is handy */
|
smpriv->parentdev = ctrldev; /* copy of parent dev is handy */
|
||||||
spin_lock_init(&smpriv->kslock);
|
spin_lock_init(&smpriv->kslock);
|
||||||
|
@ -1028,8 +1024,8 @@ int caam_sm_startup(struct platform_device *pdev)
|
||||||
sm_pdev = of_platform_device_create(np, "caam_sm", ctrldev);
|
sm_pdev = of_platform_device_create(np, "caam_sm", ctrldev);
|
||||||
|
|
||||||
if (sm_pdev == NULL) {
|
if (sm_pdev == NULL) {
|
||||||
kfree(smpriv);
|
ret = -EINVAL;
|
||||||
return -EINVAL;
|
goto free_smpriv;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Save a pointer to the platform device for Secure Memory */
|
/* Save a pointer to the platform device for Secure Memory */
|
||||||
|
@ -1090,26 +1086,37 @@ int caam_sm_startup(struct platform_device *pdev)
|
||||||
* an SM instance to any ring instance).
|
* an SM instance to any ring instance).
|
||||||
*/
|
*/
|
||||||
smpriv->smringdev = caam_jr_alloc();
|
smpriv->smringdev = caam_jr_alloc();
|
||||||
|
if (!smpriv->smringdev) {
|
||||||
|
dev_err(smdev, "Device for job ring not created\n");
|
||||||
|
ret = -ENODEV;
|
||||||
|
goto unregister_smpdev;
|
||||||
|
}
|
||||||
|
|
||||||
jrpriv = dev_get_drvdata(smpriv->smringdev);
|
jrpriv = dev_get_drvdata(smpriv->smringdev);
|
||||||
lpagect = 0;
|
lpagect = 0;
|
||||||
pgstat = 0;
|
pgstat = 0;
|
||||||
lpagedesc = kzalloc(sizeof(struct sm_page_descriptor)
|
lpagedesc = kzalloc(sizeof(struct sm_page_descriptor)
|
||||||
* smpriv->max_pages, GFP_KERNEL);
|
* smpriv->max_pages, GFP_KERNEL);
|
||||||
if (lpagedesc == NULL) {
|
if (lpagedesc == NULL) {
|
||||||
kfree(smpriv);
|
ret = -ENOMEM;
|
||||||
return -ENOMEM;
|
goto free_smringdev;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (page = 0; page < smpriv->max_pages; page++) {
|
for (page = 0; page < smpriv->max_pages; page++) {
|
||||||
if (sm_set_cmd_reg(smpriv, jrpriv,
|
u32 page_ownership;
|
||||||
((page << SMC_PAGE_SHIFT) & SMC_PAGE_MASK) |
|
|
||||||
(SMC_CMD_PAGE_INQUIRY & SMC_CMD_MASK)))
|
|
||||||
return -EINVAL;
|
|
||||||
if (sm_get_status_reg(smpriv, jrpriv, &pgstat))
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
if (((pgstat & SMCS_PGWON_MASK) >> SMCS_PGOWN_SHIFT)
|
if (sm_send_cmd(smpriv, jrpriv,
|
||||||
== SMCS_PGOWN_OWNED) { /* our page? */
|
((page << SMC_PAGE_SHIFT) & SMC_PAGE_MASK) |
|
||||||
|
(SMC_CMD_PAGE_INQUIRY & SMC_CMD_MASK),
|
||||||
|
&pgstat)) {
|
||||||
|
ret = -EINVAL;
|
||||||
|
goto free_lpagedesc;
|
||||||
|
}
|
||||||
|
|
||||||
|
page_ownership = (pgstat & SMCS_PGWON_MASK) >> SMCS_PGOWN_SHIFT;
|
||||||
|
if ((page_ownership == SMCS_PGOWN_OWNED)
|
||||||
|
|| (page_ownership == SMCS_PGOWN_NOOWN)) {
|
||||||
|
/* page allocated */
|
||||||
lpagedesc[page].phys_pagenum =
|
lpagedesc[page].phys_pagenum =
|
||||||
(pgstat & SMCS_PAGE_MASK) >> SMCS_PAGE_SHIFT;
|
(pgstat & SMCS_PAGE_MASK) >> SMCS_PAGE_SHIFT;
|
||||||
lpagedesc[page].own_part =
|
lpagedesc[page].own_part =
|
||||||
|
@ -1140,9 +1147,8 @@ int caam_sm_startup(struct platform_device *pdev)
|
||||||
smpriv->pagedesc = kzalloc(sizeof(struct sm_page_descriptor) * lpagect,
|
smpriv->pagedesc = kzalloc(sizeof(struct sm_page_descriptor) * lpagect,
|
||||||
GFP_KERNEL);
|
GFP_KERNEL);
|
||||||
if (smpriv->pagedesc == NULL) {
|
if (smpriv->pagedesc == NULL) {
|
||||||
kfree(lpagedesc);
|
ret = -ENOMEM;
|
||||||
kfree(smpriv);
|
goto free_lpagedesc;
|
||||||
return -ENOMEM;
|
|
||||||
}
|
}
|
||||||
smpriv->localpages = lpagect;
|
smpriv->localpages = lpagect;
|
||||||
|
|
||||||
|
@ -1163,7 +1169,19 @@ int caam_sm_startup(struct platform_device *pdev)
|
||||||
|
|
||||||
sm_init_keystore(smdev);
|
sm_init_keystore(smdev);
|
||||||
|
|
||||||
return 0;
|
goto exit;
|
||||||
|
|
||||||
|
free_lpagedesc:
|
||||||
|
kfree(lpagedesc);
|
||||||
|
free_smringdev:
|
||||||
|
caam_jr_free(smpriv->smringdev);
|
||||||
|
unregister_smpdev:
|
||||||
|
of_device_unregister(smpriv->sm_pdev);
|
||||||
|
free_smpriv:
|
||||||
|
kfree(smpriv);
|
||||||
|
|
||||||
|
exit:
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void caam_sm_shutdown(struct platform_device *pdev)
|
void caam_sm_shutdown(struct platform_device *pdev)
|
||||||
|
@ -1182,6 +1200,8 @@ void caam_sm_shutdown(struct platform_device *pdev)
|
||||||
|
|
||||||
smpriv = dev_get_drvdata(smdev);
|
smpriv = dev_get_drvdata(smdev);
|
||||||
|
|
||||||
|
caam_jr_free(smpriv->smringdev);
|
||||||
|
|
||||||
/* Remove Secure Memory Platform Device */
|
/* Remove Secure Memory Platform Device */
|
||||||
of_device_unregister(smpriv->sm_pdev);
|
of_device_unregister(smpriv->sm_pdev);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user