Skip to content

Commit

Permalink
crypto: ccp - Introduce the AMD Secure Processor device
Browse files Browse the repository at this point in the history
The CCP device is part of the AMD Secure Processor. In order to expand
the usage of the AMD Secure Processor, create a framework that allows
functional components of the AMD Secure Processor to be initialized and
handled appropriately.

Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
Acked-by: Gary R Hook <gary.hook@amd.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
  • Loading branch information
Brijesh Singh authored and Herbert Xu committed Jul 18, 2017
1 parent 970e830 commit 720419f
Show file tree
Hide file tree
Showing 12 changed files with 463 additions and 164 deletions.
6 changes: 3 additions & 3 deletions drivers/crypto/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -540,11 +540,11 @@ config CRYPTO_DEV_ATMEL_ECC
will be called atmel-ecc.

config CRYPTO_DEV_CCP
bool "Support for AMD Cryptographic Coprocessor"
bool "Support for AMD Secure Processor"
depends on ((X86 && PCI) || (ARM64 && (OF_ADDRESS || ACPI))) && HAS_IOMEM
help
The AMD Cryptographic Coprocessor provides hardware offload support
for encryption, hashing and related operations.
The AMD Secure Processor provides support for the Cryptographic Coprocessor
(CCP) and the Platform Security Processor (PSP) devices.

if CRYPTO_DEV_CCP
source "drivers/crypto/ccp/Kconfig"
Expand Down
21 changes: 14 additions & 7 deletions drivers/crypto/ccp/Kconfig
Original file line number Diff line number Diff line change
@@ -1,22 +1,29 @@
config CRYPTO_DEV_CCP_DD
tristate "Cryptographic Coprocessor device driver"
depends on CRYPTO_DEV_CCP
tristate "Secure Processor device driver"
default m
help
Provides AMD Secure Processor device driver.
If you choose 'M' here, this module will be called ccp.

config CRYPTO_DEV_SP_CCP
bool "Cryptographic Coprocessor device"
default y
depends on CRYPTO_DEV_CCP_DD
select HW_RANDOM
select DMA_ENGINE
select DMADEVICES
select CRYPTO_SHA1
select CRYPTO_SHA256
help
Provides the interface to use the AMD Cryptographic Coprocessor
which can be used to offload encryption operations such as SHA,
AES and more. If you choose 'M' here, this module will be called
ccp.
Provides the support for AMD Cryptographic Coprocessor (CCP) device
which can be used to offload encryption operations such as SHA, AES
and more.

config CRYPTO_DEV_CCP_CRYPTO
tristate "Encryption and hashing offload support"
depends on CRYPTO_DEV_CCP_DD
default m
depends on CRYPTO_DEV_CCP_DD
depends on CRYPTO_DEV_SP_CCP
select CRYPTO_HASH
select CRYPTO_BLKCIPHER
select CRYPTO_AUTHENC
Expand Down
4 changes: 2 additions & 2 deletions drivers/crypto/ccp/Makefile
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
obj-$(CONFIG_CRYPTO_DEV_CCP_DD) += ccp.o
ccp-objs := ccp-dev.o \
ccp-objs := sp-dev.o ccp-platform.o
ccp-$(CONFIG_CRYPTO_DEV_SP_CCP) += ccp-dev.o \
ccp-ops.o \
ccp-dev-v3.o \
ccp-dev-v5.o \
ccp-platform.o \
ccp-dmaengine.o \
ccp-debugfs.o
ccp-$(CONFIG_PCI) += ccp-pci.o
Expand Down
4 changes: 1 addition & 3 deletions drivers/crypto/ccp/ccp-dev-v3.c
Original file line number Diff line number Diff line change
Expand Up @@ -359,8 +359,7 @@ static void ccp_irq_bh(unsigned long data)

static irqreturn_t ccp_irq_handler(int irq, void *data)
{
struct device *dev = data;
struct ccp_device *ccp = dev_get_drvdata(dev);
struct ccp_device *ccp = (struct ccp_device *)data;

ccp_disable_queue_interrupts(ccp);
if (ccp->use_tasklet)
Expand Down Expand Up @@ -597,6 +596,5 @@ const struct ccp_vdata ccpv3 = {
.version = CCP_VERSION(3, 0),
.setup = NULL,
.perform = &ccp3_actions,
.bar = 2,
.offset = 0x20000,
};
5 changes: 1 addition & 4 deletions drivers/crypto/ccp/ccp-dev-v5.c
Original file line number Diff line number Diff line change
Expand Up @@ -769,8 +769,7 @@ static void ccp5_irq_bh(unsigned long data)

static irqreturn_t ccp5_irq_handler(int irq, void *data)
{
struct device *dev = data;
struct ccp_device *ccp = dev_get_drvdata(dev);
struct ccp_device *ccp = (struct ccp_device *)data;

ccp5_disable_queue_interrupts(ccp);
ccp->total_interrupts++;
Expand Down Expand Up @@ -1113,7 +1112,6 @@ const struct ccp_vdata ccpv5a = {
.version = CCP_VERSION(5, 0),
.setup = ccp5_config,
.perform = &ccp5_actions,
.bar = 2,
.offset = 0x0,
};

Expand All @@ -1122,6 +1120,5 @@ const struct ccp_vdata ccpv5b = {
.dma_chan_attr = DMA_PRIVATE,
.setup = ccp5other_config,
.perform = &ccp5_actions,
.bar = 2,
.offset = 0x0,
};
106 changes: 43 additions & 63 deletions drivers/crypto/ccp/ccp-dev.c
Original file line number Diff line number Diff line change
Expand Up @@ -111,13 +111,6 @@ static LIST_HEAD(ccp_units);
static DEFINE_SPINLOCK(ccp_rr_lock);
static struct ccp_device *ccp_rr;

/* Ever-increasing value to produce unique unit numbers */
static atomic_t ccp_unit_ordinal;
static unsigned int ccp_increment_unit_ordinal(void)
{
return atomic_inc_return(&ccp_unit_ordinal);
}

/**
* ccp_add_device - add a CCP device to the list
*
Expand Down Expand Up @@ -465,14 +458,17 @@ int ccp_cmd_queue_thread(void *data)
*
* @dev: device struct of the CCP
*/
struct ccp_device *ccp_alloc_struct(struct device *dev)
struct ccp_device *ccp_alloc_struct(struct sp_device *sp)
{
struct device *dev = sp->dev;
struct ccp_device *ccp;

ccp = devm_kzalloc(dev, sizeof(*ccp), GFP_KERNEL);
if (!ccp)
return NULL;
ccp->dev = dev;
ccp->sp = sp;
ccp->axcache = sp->axcache;

INIT_LIST_HEAD(&ccp->cmd);
INIT_LIST_HEAD(&ccp->backlog);
Expand All @@ -487,9 +483,8 @@ struct ccp_device *ccp_alloc_struct(struct device *dev)
init_waitqueue_head(&ccp->sb_queue);
init_waitqueue_head(&ccp->suspend_queue);

ccp->ord = ccp_increment_unit_ordinal();
snprintf(ccp->name, MAX_CCP_NAME_LEN, "ccp-%u", ccp->ord);
snprintf(ccp->rngname, MAX_CCP_NAME_LEN, "ccp-%u-rng", ccp->ord);
snprintf(ccp->name, MAX_CCP_NAME_LEN, "ccp-%u", sp->ord);
snprintf(ccp->rngname, MAX_CCP_NAME_LEN, "ccp-%u-rng", sp->ord);

return ccp;
}
Expand Down Expand Up @@ -540,8 +535,9 @@ bool ccp_queues_suspended(struct ccp_device *ccp)
return ccp->cmd_q_count == suspended;
}

int ccp_dev_suspend(struct ccp_device *ccp, pm_message_t state)
int ccp_dev_suspend(struct sp_device *sp, pm_message_t state)
{
struct ccp_device *ccp = sp->ccp_data;
unsigned long flags;
unsigned int i;

Expand All @@ -563,8 +559,9 @@ int ccp_dev_suspend(struct ccp_device *ccp, pm_message_t state)
return 0;
}

int ccp_dev_resume(struct ccp_device *ccp)
int ccp_dev_resume(struct sp_device *sp)
{
struct ccp_device *ccp = sp->ccp_data;
unsigned long flags;
unsigned int i;

Expand All @@ -584,71 +581,54 @@ int ccp_dev_resume(struct ccp_device *ccp)
}
#endif

int ccp_dev_init(struct ccp_device *ccp)
int ccp_dev_init(struct sp_device *sp)
{
ccp->io_regs = ccp->io_map + ccp->vdata->offset;

if (ccp->vdata->setup)
ccp->vdata->setup(ccp);

return ccp->vdata->perform->init(ccp);
}
struct device *dev = sp->dev;
struct ccp_device *ccp;
int ret;

void ccp_dev_destroy(struct ccp_device *ccp)
{
ret = -ENOMEM;
ccp = ccp_alloc_struct(sp);
if (!ccp)
return;
goto e_err;
sp->ccp_data = ccp;

ccp->vdata = (struct ccp_vdata *)sp->dev_vdata->ccp_vdata;
if (!ccp->vdata || !ccp->vdata->version) {
ret = -ENODEV;
dev_err(dev, "missing driver data\n");
goto e_err;
}

ccp->vdata->perform->destroy(ccp);
}
ccp->get_irq = sp->get_irq;
ccp->free_irq = sp->free_irq;

static int __init ccp_mod_init(void)
{
#ifdef CONFIG_X86
int ret;
ccp->io_regs = sp->io_map + ccp->vdata->offset;
if (ccp->vdata->setup)
ccp->vdata->setup(ccp);

ret = ccp_pci_init();
ret = ccp->vdata->perform->init(ccp);
if (ret)
return ret;
goto e_err;

/* Don't leave the driver loaded if init failed */
if (ccp_present() != 0) {
ccp_pci_exit();
return -ENODEV;
}
dev_notice(dev, "ccp enabled\n");

return 0;
#endif

#ifdef CONFIG_ARM64
int ret;

ret = ccp_platform_init();
if (ret)
return ret;
e_err:
sp->ccp_data = NULL;

/* Don't leave the driver loaded if init failed */
if (ccp_present() != 0) {
ccp_platform_exit();
return -ENODEV;
}

return 0;
#endif
dev_notice(dev, "ccp initialization failed\n");

return -ENODEV;
return ret;
}

static void __exit ccp_mod_exit(void)
void ccp_dev_destroy(struct sp_device *sp)
{
#ifdef CONFIG_X86
ccp_pci_exit();
#endif
struct ccp_device *ccp = sp->ccp_data;

#ifdef CONFIG_ARM64
ccp_platform_exit();
#endif
}
if (!ccp)
return;

module_init(ccp_mod_init);
module_exit(ccp_mod_exit);
ccp->vdata->perform->destroy(ccp);
}
21 changes: 4 additions & 17 deletions drivers/crypto/ccp/ccp-dev.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@
#include <linux/irqreturn.h>
#include <linux/dmaengine.h>

#include "sp-dev.h"

#define MAX_CCP_NAME_LEN 16
#define MAX_DMAPOOL_NAME_LEN 32

Expand Down Expand Up @@ -344,6 +346,7 @@ struct ccp_device {
char rngname[MAX_CCP_NAME_LEN];

struct device *dev;
struct sp_device *sp;

/* Bus specific device information
*/
Expand All @@ -362,7 +365,6 @@ struct ccp_device {
* them.
*/
struct mutex req_mutex ____cacheline_aligned;
void __iomem *io_map;
void __iomem *io_regs;

/* Master lists that all cmds are queued on. Because there can be
Expand Down Expand Up @@ -637,7 +639,7 @@ void ccp_del_device(struct ccp_device *ccp);

extern void ccp_log_error(struct ccp_device *, int);

struct ccp_device *ccp_alloc_struct(struct device *dev);
struct ccp_device *ccp_alloc_struct(struct sp_device *sp);
bool ccp_queues_suspended(struct ccp_device *ccp);
int ccp_cmd_queue_thread(void *data);
int ccp_trng_read(struct hwrng *rng, void *data, size_t max, bool wait);
Expand All @@ -652,11 +654,6 @@ void ccp_dmaengine_unregister(struct ccp_device *ccp);
void ccp5_debugfs_setup(struct ccp_device *ccp);
void ccp5_debugfs_destroy(void);

int ccp_dev_init(struct ccp_device *ccp);
void ccp_dev_destroy(struct ccp_device *ccp);
int ccp_dev_suspend(struct ccp_device *ccp, pm_message_t state);
int ccp_dev_resume(struct ccp_device *ccp);

/* Structure for computation functions that are device-specific */
struct ccp_actions {
int (*aes)(struct ccp_op *);
Expand All @@ -674,16 +671,6 @@ struct ccp_actions {
irqreturn_t (*irqhandler)(int, void *);
};

/* Structure to hold CCP version-specific values */
struct ccp_vdata {
const unsigned int version;
const unsigned int dma_chan_attr;
void (*setup)(struct ccp_device *);
const struct ccp_actions *perform;
const unsigned int bar;
const unsigned int offset;
};

extern const struct ccp_vdata ccpv3_platform;
extern const struct ccp_vdata ccpv3;
extern const struct ccp_vdata ccpv5a;
Expand Down
Loading

0 comments on commit 720419f

Please sign in to comment.