Add TEE interface support to AMD Secure Processor driver
Subsystems (3)
v2 cover Add TEE interface support to AMD Secure Processor driver
The goal of this patch series is to introduce TEE (Trusted Execution Environment) interface support to AMD Secure Processor driver. The TEE is a secure area of a processor which ensures that sensitive data is stored, processed and protected in an isolated and trusted environment. The Platform Security Processor (PSP) is a dedicated processor which provides TEE to enable HW platform security. It offers protection against software attacks generated in Rich Operating System (Rich OS) such as Linux running on x86.
Based on the platform feature support, the PSP is capable of supporting either SEV (Secure Encrypted Virtualization) and/or TEE. The first three patches in this series is about moving SEV specific functions and data structures from PSP device driver file to a dedicated SEV interface driver file. The last two patches add TEE interface support to AMD Secure Processor driver. This TEE interface will be used by AMD-TEE driver to submit command buffers for processing in PSP Trusted Execution Environment.
v2:
* Rebased the patches on cryptodev-2.6 tree with base commit d158367682cd (crypto: atmel - Fix selection of CRYPTO_AUTHENC)
* Regenerated patch with correct diff-stat to show file rename
* Used Co-developed-by: tag to give proper credit to co-author
Rijo Thomas (6):
crypto: ccp - rename psp-dev files to sev-dev
crypto: ccp - create a generic psp-dev file
crypto: ccp - move SEV vdata to a dedicated data structure
crypto: ccp - check whether PSP supports SEV or TEE before
initialization
crypto: ccp - add TEE support for Raven Ridge
crypto: ccp - provide in-kernel API to submit TEE commands
drivers/crypto/ccp/Makefile | 4 +- drivers/crypto/ccp/psp-dev.c | 1020 ++++------------------------------------ drivers/crypto/ccp/psp-dev.h | 50 +- drivers/crypto/ccp/sev-dev.c | 1053 ++++++++++++++++++++++++++++++++++++++++++ drivers/crypto/ccp/sev-dev.h | 62 +++ drivers/crypto/ccp/sp-dev.h | 17 +- drivers/crypto/ccp/sp-pci.c | 43 +- drivers/crypto/ccp/tee-dev.c | 364 +++++++++++++++ drivers/crypto/ccp/tee-dev.h | 110 +++++ include/linux/psp-tee.h | 73 +++ 10 files changed, 1827 insertions(+), 969 deletions(-) create mode 100644 drivers/crypto/ccp/sev-dev.c create mode 100644 drivers/crypto/ccp/sev-dev.h create mode 100644 drivers/crypto/ccp/tee-dev.c create mode 100644 drivers/crypto/ccp/tee-dev.h create mode 100644 include/linux/psp-tee.h
--
1.9.1
RFC PATCH v2 1/6 crypto: ccp - rename psp-dev files to sev-dev
This is a preliminary patch for creating a generic PSP device driver file, which will have support for both SEV and TEE (Trusted Execution Environment) interface.
This patch does not introduce any new functionality, but simply renames psp-dev.c and psp-dev.h files to sev-dev.c and sev-dev.h files respectively.
---
drivers/crypto/ccp/Makefile | 2 +-
drivers/crypto/ccp/{psp-dev.c => sev-dev.c} | 6 +++---
drivers/crypto/ccp/{psp-dev.h => sev-dev.h} | 8 ++++----
drivers/crypto/ccp/sp-pci.c | 2 +-
4 files changed, 9 insertions(+), 9 deletions(-)
rename drivers/crypto/ccp/{psp-dev.c => sev-dev.c} (99%)
rename drivers/crypto/ccp/{psp-dev.h => sev-dev.h} (90%)drivers/crypto/ccp/Makefile +1 -1
@@ -8,7 +8,7 @@ ccp-$(CONFIG_CRYPTO_DEV_SP_CCP) += ccp-dev.o \ ccp-dmaengine.o ccp-$(CONFIG_CRYPTO_DEV_CCP_DEBUGFS) += ccp-debugfs.o ccp-$(CONFIG_PCI) += sp-pci.o -ccp-$(CONFIG_CRYPTO_DEV_SP_PSP) += psp-dev.o +ccp-$(CONFIG_CRYPTO_DEV_SP_PSP) += sev-dev.o obj-$(CONFIG_CRYPTO_DEV_CCP_CRYPTO) += ccp-crypto.o ccp-crypto-objs := ccp-crypto-main.o \
drivers/crypto/ccp/sev-dev.c renamed from drivers/crypto/ccp/psp-dev.c +3 -3
@@ -1,8 +1,8 @@// SPDX-License-Identifier: GPL-2.0-only /* -* AMD Platform Security Processor (PSP) interface +* AMD Secure Encrypted Virtualization (SEV) interface * -* Copyright (C) 2016,2018 Advanced Micro Devices, Inc. +* Copyright (C) 2016,2019 Advanced Micro Devices, Inc. * * Author: Brijesh Singh <[email protected]> */
@@ -22,7 +22,7 @@#include <linux/firmware.h> #include "sp-dev.h" -#include "psp-dev.h" +#include "sev-dev.h" #define DEVICE_NAME "sev"#define SEV_FW_FILE "amd/sev.fw"
drivers/crypto/ccp/sev-dev.h renamed from drivers/crypto/ccp/psp-dev.h +4 -4
@@ -2,13 +2,13 @@/* * AMD Platform Security Processor (PSP) interface driver * -* Copyright (C) 2017-2018 Advanced Micro Devices, Inc. +* Copyright (C) 2017-2019 Advanced Micro Devices, Inc. * * Author: Brijesh Singh <[email protected]> */ -#ifndef __PSP_DEV_H__ -#define __PSP_DEV_H__ +#ifndef __SEV_DEV_H__ +#define __SEV_DEV_H__#include <linux/device.h> #include <linux/spinlock.h>
@@ -63,4 +63,4 @@ struct psp_device { u8 build; }; -#endif /* __PSP_DEV_H */ +#endif /* __SEV_DEV_H */
drivers/crypto/ccp/sp-pci.c +1 -1
@@ -22,7 +22,7 @@#include <linux/ccp.h> #include "ccp-dev.h" -#include "psp-dev.h" +#include "sev-dev.h" #define MSIX_VECTORS 2
Signature · 1 line
1.9.1
RFC PATCH v2 2/6 crypto: ccp - create a generic psp-dev file
In reply to Rijo ThomasThe PSP (Platform Security Processor) provides support for key management commands in Secure Encrypted Virtualization (SEV) mode, along with software-based Trusted Execution Environment (TEE) to enable third-party Trusted Applications.
Therefore, introduce psp-dev.c and psp-dev.h files, which can invoke SEV (or TEE) initialization based on platform feature support.
TEE interface support will be introduced in a later patch.
--- drivers/crypto/ccp/Makefile | 3 +- drivers/crypto/ccp/psp-dev.c | 194 ++++++++++++++++++++++++++++++ drivers/crypto/ccp/psp-dev.h | 52 +++++++++ drivers/crypto/ccp/sev-dev.c | 273 ++++++++++++++++--------------------------- drivers/crypto/ccp/sev-dev.h | 36 +++--- drivers/crypto/ccp/sp-pci.c | 2 +- 6 files changed, 367 insertions(+), 193 deletions(-) create mode 100644 drivers/crypto/ccp/psp-dev.c create mode 100644 drivers/crypto/ccp/psp-dev.h
drivers/crypto/ccp/Makefile +2 -1
@@ -8,7 +8,8 @@ ccp-$(CONFIG_CRYPTO_DEV_SP_CCP) += ccp-dev.o \ ccp-dmaengine.o ccp-$(CONFIG_CRYPTO_DEV_CCP_DEBUGFS) += ccp-debugfs.o ccp-$(CONFIG_PCI) += sp-pci.o -ccp-$(CONFIG_CRYPTO_DEV_SP_PSP) += sev-dev.o +ccp-$(CONFIG_CRYPTO_DEV_SP_PSP) += psp-dev.o \ + sev-dev.o obj-$(CONFIG_CRYPTO_DEV_CCP_CRYPTO) += ccp-crypto.o ccp-crypto-objs := ccp-crypto-main.o \
drivers/crypto/ccp/psp-dev.c new file +194 -0
194 lines not on this page · raw message
drivers/crypto/ccp/psp-dev.h new file +52 -0
52 lines not on this page · raw message
drivers/crypto/ccp/sev-dev.c +103 -170
550 lines not on this page · raw message
drivers/crypto/ccp/sev-dev.h +15 -21
@@ -24,37 +24,25 @@#include <linux/psp-sev.h> #include <linux/miscdevice.h> -#include "sp-dev.h" - -#define PSP_CMD_COMPLETE BIT(1) - -#define PSP_CMDRESP_CMD_SHIFT 16 -#define PSP_CMDRESP_IOC BIT(0) -#define PSP_CMDRESP_RESP BIT(31) -#define PSP_CMDRESP_ERR_MASK 0xffff - -#define MAX_PSP_NAME_LEN 16 +#define SEV_CMD_COMPLETE BIT(1) +#define SEV_CMDRESP_CMD_SHIFT 16 +#define SEV_CMDRESP_IOC BIT(0)struct sev_misc_dev {struct kref refcount;struct miscdevice misc; }; -struct psp_device { -struct list_head entry; - -struct psp_vdata *vdata; -char name[MAX_PSP_NAME_LEN ]; - +struct sev_device {struct device *dev; -struct sp_device *sp; +struct psp_device *psp;void __iomem *io_regs; -int sev_state; -unsigned int sev_int_rcvd; -wait_queue_head_t sev_int_queue; -struct sev_misc_dev *sev_misc; +int state; +unsigned int int_rcvd; +wait_queue_head_t int_queue; +struct sev_misc_dev *misc;struct sev_user_data_status status_cmd_buf;struct sev_data_init init_cmd_buf;
@@ -63,4 +51,10 @@ struct psp_device { u8 build; }; +int sev_dev_init (struct psp_device *psp); +void sev_dev_destroy (struct psp_device *psp); + +void sev_pci_init (void ); +void sev_pci_exit (void ); +#endif /* __SEV_DEV_H */
drivers/crypto/ccp/sp-pci.c +1 -1
@@ -22,7 +22,7 @@#include <linux/ccp.h> #include "ccp-dev.h" -#include "sev-dev.h" +#include "psp-dev.h" #define MSIX_VECTORS 2
Signature · 1 line
1.9.1
Re: [RFC PATCH v2 2/6] crypto: ccp - create a generic psp-dev file
Quoted 9 lines · Rijo Thomas
The PSP (Platform Security Processor) provides support for key management commands in Secure Encrypted Virtualization (SEV) mode, along with software-based Trusted Execution Environment (TEE) to enable third-party Trusted Applications.
Therefore, introduce
psp-dev.candpsp-dev.hfiles, which can invoke SEV (or TEE) initialization based on platform feature support.TEE interface support will be introduced in a later patch.
This patch does not cleanly apply to the current cryptodev-2.6 tree. Please ensure that you have pulled and rebased, built, and tested just prior to sending out your patches.
grh
Quoted 943 lines
Cc Ard Biesheuvel <[email protected]>Cc Tom Lendacky <[email protected]>Cc Jens Wiklander <[email protected]>Co-developed-by Devaraj Rangasamy <[email protected]>Signed-off-by Devaraj Rangasamy <[email protected]>Signed-off-by Rijo Thomas <[email protected]>--- drivers/crypto/ccp/Makefile | 3 +- drivers/crypto/ccp/psp-dev.c | 194 ++++++++++++++++++++++++++++++ drivers/crypto/ccp/psp-dev.h | 52 +++++++++ drivers/crypto/ccp/sev-dev.c | 273 ++++++++++++++++--------------------------- drivers/crypto/ccp/sev-dev.h | 36 +++--- drivers/crypto/ccp/sp-pci.c | 2 +- 6 files changed, 367 insertions(+), 193 deletions(-)create mode 100644
drivers/crypto/ccp/psp-dev.c
create mode 100644drivers/crypto/ccp/psp-dev.hdrivers/crypto/ccp/Makefile +2
-1@@ -8,7 +8,8 @@ ccp-$(CONFIG_CRYPTO_DEV_SP_CCP) += ccp-dev.o \ ccp-dmaengine.o ccp-$(CONFIG_CRYPTO_DEV_CCP_DEBUGFS) += ccp-debugfs.o ccp-$(CONFIG_PCI) += sp-pci.o -ccp-$(CONFIG_CRYPTO_DEV_SP_PSP) += sev-dev.o +ccp-$(CONFIG_CRYPTO_DEV_SP_PSP) += psp-dev.o \ + sev-dev.o obj-$(CONFIG_CRYPTO_DEV_CCP_CRYPTO) += ccp-crypto.o ccp-crypto-objs := ccp-crypto-main.o \drivers/crypto/ccp/psp-dev.c new file +194
-0@@ -0,0 +1,194 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* +* AMD Platform Security Processor (PSP) interface +* +* Copyright (C) 2016,2019 Advanced Micro Devices, Inc. +* +* Author: Brijesh Singh <[email protected]> +*/ + +#include <linux/kernel.h> +#include <linux/irqreturn.h> + +#include "sp-dev.h" +#include "psp-dev.h" +#include "sev-dev.h" + +struct psp_device *psp_master; + +static struct psp_device *psp_alloc_struct (struct sp_device *sp) +{ +struct device *dev = sp->dev; +struct psp_device *psp; + + psp =devm_kzalloc (dev,sizeof (*psp),GFP_KERNEL ); +if (!psp) +return NULL ; + + psp->dev = dev; + psp->sp = sp; + +snprintf (psp->name,sizeof (psp->name),"psp-%u" , sp->ord); + +return psp; +} + +static irqreturn_t psp_irq_handler (int irq,void *data) +{ +struct psp_device *psp = data; +unsigned int status; + +/* Read the interrupt status: */ + status =ioread32 (psp->io_regs + psp->vdata->intsts_reg); + +/* invoke subdevice interrupt handlers */ +if (status) { +if (psp->sev_irq_handler) + psp->sev_irq_handler (irq, psp->sev_irq_data, status); + } + +/* Clear the interrupt status by writing the same value we read. */ +iowrite32 (status, psp->io_regs + psp->vdata->intsts_reg); + +return IRQ_HANDLED ; +} + +static int psp_check_sev_support (struct psp_device *psp) +{ +unsigned int val =ioread32 (psp->io_regs + psp->vdata->feature_reg); + +/* +* Check for a access to the registers. If this read returns +* 0xffffffff, it's likely that the system is running a broken +* BIOS which disallows access to the device. Stop here and +* fail the PSP initialization (but not the load, as the CCP +* could get properly initialized). +*/ +if (val ==0xffffffff ) { +dev_notice (psp->dev,"psp: unable to access the device: you might be running a broken BIOS.\n" ); +return -ENODEV ; + } + +if (!(val &1 )) { +/* Device does not support the SEV feature */ +dev_dbg (psp->dev,"psp does not support SEV\n" ); +return -ENODEV ; + } + +return 0 ; +} + +int psp_dev_init (struct sp_device *sp) +{ +struct device *dev = sp->dev; +struct psp_device *psp; +int ret; + + ret = -ENOMEM ; + psp =psp_alloc_struct (sp); +if (!psp) + goto e_err; + + sp->psp_data = psp; + + psp->vdata = (struct psp_vdata *)sp->dev_vdata->psp_vdata; +if (!psp->vdata) { + ret = -ENODEV ; +dev_err (dev,"missing driver data\n" ); + goto e_err; + } + + psp->io_regs = sp->io_map; + + ret =psp_check_sev_support (psp); +if (ret) + goto e_disable; + +/* Disable and clear interrupts until ready */ +iowrite32 (0 , psp->io_regs + psp->vdata->inten_reg); +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 (ret) { +dev_err (dev,"psp: unable to allocate an IRQ\n" ); + goto e_err; + } + + ret =sev_dev_init (psp); +if (ret) + goto e_irq; + +if (sp->set_psp_master_device) + sp->set_psp_master_device (sp); + +/* Enable interrupt */ +iowrite32 (-1 , psp->io_regs + psp->vdata->inten_reg); + +dev_notice (dev,"psp enabled\n" ); + +return 0 ; + +e_irq: +sp_free_psp_irq (psp->sp, psp); +e_err: + sp->psp_data =NULL ; + +dev_notice (dev,"psp initialization failed\n" ); + +return ret; + +e_disable: + sp->psp_data =NULL ; + +return ret; +} + +void psp_dev_destroy (struct sp_device *sp) +{ +struct psp_device *psp = sp->psp_data; + +if (!psp) +return ; + +sev_dev_destroy (psp); + +sp_free_psp_irq (sp, psp); +} + +void psp_set_sev_irq_handler (struct psp_device *psp,psp_irq_handler_t handler, +void *data) +{ + psp->sev_irq_data = data; + psp->sev_irq_handler = handler; +} + +void psp_clear_sev_irq_handler (struct psp_device *psp) +{ +psp_set_sev_irq_handler (psp,NULL ,NULL ); +} + +struct psp_device *psp_get_master_device (void ) +{ +struct sp_device *sp =sp_get_psp_master_device (); + +return sp ? sp->psp_data :NULL ; +} + +void psp_pci_init (void ) +{ + psp_master =psp_get_master_device (); + +if (!psp_master) +return ; + +sev_pci_init (); +} + +void psp_pci_exit (void ) +{ +if (!psp_master) +return ; + +sev_pci_exit (); +}drivers/crypto/ccp/psp-dev.h new file +52
-0@@ -0,0 +1,52 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* +* AMD Platform Security Processor (PSP) interface driver +* +* Copyright (C) 2017-2019 Advanced Micro Devices, Inc. +* +* Author: Brijesh Singh <[email protected]> +*/ + +#ifndef __PSP_DEV_H__ +#define __PSP_DEV_H__ + +#include <linux/device.h> +#include <linux/list.h> +#include <linux/bits.h> +#include <linux/interrupt.h> + +#include "sp-dev.h" + +#define PSP_CMDRESP_RESP BIT(31) +#define PSP_CMDRESP_ERR_MASK 0xffff + +#define MAX_PSP_NAME_LEN 16 + +extern struct psp_device *psp_master; + +typedef void (*psp_irq_handler_t )(int ,void *,unsigned int ); + +struct psp_device { +struct list_head entry; + +struct psp_vdata *vdata; +char name[MAX_PSP_NAME_LEN ]; + +struct device *dev; +struct sp_device *sp; + +void __iomem *io_regs; + +psp_irq_handler_t sev_irq_handler; +void *sev_irq_data; + +void *sev_data; +}; + +void psp_set_sev_irq_handler (struct psp_device *psp,psp_irq_handler_t handler, +void *data); +void psp_clear_sev_irq_handler (struct psp_device *psp); + +struct psp_device *psp_get_master_device (void ); + +#endif /* __PSP_DEV_H */ drivers/crypto/ccp/sev-dev.c +103
-170@@ -21,7 +21,7 @@#include <linux/ccp.h> #include <linux/firmware.h> -#include "sp-dev.h" +#include "psp-dev.h" #include "sev-dev.h" #define DEVICE_NAME "sev"@@ -30,7 +30,6 @@static DEFINE_MUTEX (sev_cmd_mutex);static struct sev_misc_dev *misc_dev; -static struct psp_device *psp_master;static int psp_cmd_timeout =100 ;module_param (psp_cmd_timeout, int,0644 );@@ -45,68 +44,45 @@static inline bool sev_version_greater_or_equal (u8 maj,u8 min) { -if (psp_master->api_major > maj) -return true; -if (psp_master->api_major == maj && psp_master->api_minor >= min) -return true; -return false; -} - -static struct psp_device *psp_alloc_struct (struct sp_device *sp) -{ -struct device *dev = sp->dev; -struct psp_device *psp; +struct sev_device *sev = psp_master->sev_data; - psp =devm_kzalloc (dev,sizeof (*psp),GFP_KERNEL ); -if (!psp) -return NULL ; - - psp->dev = dev; - psp->sp = sp; +if (sev->api_major > maj) +return true; -snprintf (psp->name,sizeof (psp->name),"psp-%u" , sp->ord); +if (sev->api_major == maj && sev->api_minor >= min) +return true; -return psp; +return false; } -static irqreturn_t psp_irq_handler (int irq,void *data) +static void sev_irq_handler (int irq,void *data,unsigned int status) { -struct psp_device *psp = data; -unsigned int status; +struct sev_device *sev = data;int reg; -/* Read the interrupt status: */ - status =ioread32 (psp->io_regs + psp->vdata->intsts_reg); -/* Check if it is command completion: */ -if (!(status &PSP_CMD_COMPLETE )) - goto done; +if (!(status &SEV_CMD_COMPLETE )) +return ;/* Check if it is SEV command completion: */ - reg =ioread32 (psp->io_regs + psp->vdata->cmdresp_reg); + reg =ioread32 (sev->io_regs + sev->psp->vdata->cmdresp_reg);if (reg &PSP_CMDRESP_RESP ) { - psp->sev_int_rcvd =1 ; -wake_up (&psp->sev_int_queue); + sev->int_rcvd =1 ; +wake_up (&sev->int_queue); } - -done: -/* Clear the interrupt status by writing the same value we read. */ -iowrite32 (status, psp->io_regs + psp->vdata->intsts_reg); - -return IRQ_HANDLED ; } -static int sev_wait_cmd_ioc (struct psp_device *psp, +static int sev_wait_cmd_ioc (struct sev_device *sev,unsigned int *reg,unsigned int timeout) {int ret; - ret =wait_event_timeout (psp->sev_int_queue, - psp->sev_int_rcvd, timeout *HZ ); + ret =wait_event_timeout (sev->int_queue, + sev->int_rcvd, timeout *HZ );if (!ret)return -ETIMEDOUT ; - *reg =ioread32 (psp->io_regs + psp->vdata->cmdresp_reg); + *reg =ioread32 (sev->io_regs + sev->psp->vdata->cmdresp_reg);return 0 ; }@@ -150,42 +126,45 @@ static int sev_cmd_buffer_len(int cmd)static int __sev_do_cmd_locked (int cmd,void *data,int *psp_ret) {struct psp_device *psp = psp_master; +struct sev_device *sev;unsigned int phys_lsb, phys_msb;unsigned int reg, ret =0 ; -if (!psp) +if (!psp || !psp->sev_data)return -ENODEV ;if (psp_dead)return -EBUSY ; + sev = psp->sev_data; +/* Get the physical address of the command buffer */ phys_lsb = data ?lower_32_bits (__psp_pa (data)) :0 ; phys_msb = data ?upper_32_bits (__psp_pa (data)) :0 ; -dev_dbg (psp->dev,"sev command id %#x buffer 0x%08x%08x timeout %us\n" , +dev_dbg (sev->dev,"sev command id %#x buffer 0x%08x%08x timeout %us\n" , cmd, phys_msb, phys_lsb, psp_timeout);print_hex_dump_debug ("(in): " ,DUMP_PREFIX_OFFSET ,16 ,2 , data,sev_cmd_buffer_len (cmd), false); -iowrite32 (phys_lsb, psp->io_regs + psp->vdata->cmdbuff_addr_lo_reg); -iowrite32 (phys_msb, psp->io_regs + psp->vdata->cmdbuff_addr_hi_reg); +iowrite32 (phys_lsb, sev->io_regs + psp->vdata->cmdbuff_addr_lo_reg); +iowrite32 (phys_msb, sev->io_regs + psp->vdata->cmdbuff_addr_hi_reg); - psp->sev_int_rcvd =0 ; + sev->int_rcvd =0 ; reg = cmd; - reg <<=PSP_CMDRESP_CMD_SHIFT ; - reg |=PSP_CMDRESP_IOC ; -iowrite32 (reg, psp->io_regs + psp->vdata->cmdresp_reg); + reg <<=SEV_CMDRESP_CMD_SHIFT ; + reg |=SEV_CMDRESP_IOC ; +iowrite32 (reg, sev->io_regs + psp->vdata->cmdresp_reg);/* wait for command completion */ - ret =sev_wait_cmd_ioc (psp, ®, psp_timeout); + ret =sev_wait_cmd_ioc (sev, ®, psp_timeout);if (ret) {if (psp_ret) *psp_ret =0 ; -dev_err (psp->dev,"sev command %#x timed out, disabling PSP \n" , cmd); +dev_err (sev->dev,"sev command %#x timed out, disabling PSP\n" , cmd); psp_dead = true;return ret;@@ -197,7 +176,7 @@ static int __sev_do_cmd_locked(int cmd, void *data, int *psp_ret) *psp_ret = reg &PSP_CMDRESP_ERR_MASK ;if (reg &PSP_CMDRESP_ERR_MASK ) { -dev_dbg (psp->dev,"sev command %#x failed (%#010x)\n" , +dev_dbg (sev->dev,"sev command %#x failed (%#010x)\n" , cmd, reg &PSP_CMDRESP_ERR_MASK ); ret = -EIO ; }@@ -222,20 +201,23 @@ static int sev_do_cmd(int cmd, void *data, int *psp_ret)static int __sev_platform_init_locked (int *error) {struct psp_device *psp = psp_master; +struct sev_device *sev;int rc =0 ; -if (!psp) +if (!psp || !psp->sev_data)return -ENODEV ; -if (psp->sev_state ==SEV_STATE_INIT ) + sev = psp->sev_data; + +if (sev->state ==SEV_STATE_INIT )return 0 ; - rc =__sev_do_cmd_locked (SEV_CMD_INIT , &psp->init_cmd_buf, error); + rc =__sev_do_cmd_locked (SEV_CMD_INIT , &sev->init_cmd_buf, error);if (rc)return rc; - psp->sev_state =SEV_STATE_INIT ; -dev_dbg (psp->dev,"SEV firmware initialized\n" ); + sev->state =SEV_STATE_INIT ; +dev_dbg (sev->dev,"SEV firmware initialized\n" );return rc; }@@ -254,14 +236,15 @@ int sev_platform_init(int *error)static int __sev_platform_shutdown_locked (int *error) { +struct sev_device *sev = psp_master->sev_data;int ret; ret =__sev_do_cmd_locked (SEV_CMD_SHUTDOWN ,NULL , error);if (ret)return ret; - psp_master->sev_state =SEV_STATE_UNINIT ; -dev_dbg (psp_master->dev,"SEV firmware shutdown\n" ); + sev->state =SEV_STATE_UNINIT ; +dev_dbg (sev->dev,"SEV firmware shutdown\n" );return ret; }@@ -279,14 +262,15 @@ static int sev_platform_shutdown(int *error)static int sev_get_platform_state (int *state,int *error) { +struct sev_device *sev = psp_master->sev_data;int rc; rc =__sev_do_cmd_locked (SEV_CMD_PLATFORM_STATUS , - &psp_master->status_cmd_buf, error); + &sev->status_cmd_buf, error);if (rc)return rc; - *state = psp_master->status_cmd_buf.state; + *state = sev->status_cmd_buf.state;return rc; }@@ -321,7 +305,8 @@ static int sev_ioctl_do_reset(struct sev_issue_cmd *argp)static int sev_ioctl_do_platform_status (struct sev_issue_cmd *argp) { -struct sev_user_data_status *data = &psp_master->status_cmd_buf; +struct sev_device *sev = psp_master->sev_data; +struct sev_user_data_status *data = &sev->status_cmd_buf;int ret; ret =__sev_do_cmd_locked (SEV_CMD_PLATFORM_STATUS , data, &argp->error);@@ -336,9 +321,10 @@ static int sev_ioctl_do_platform_status(struct sev_issue_cmd *argp)static int sev_ioctl_do_pek_pdh_gen (int cmd,struct sev_issue_cmd *argp) { +struct sev_device *sev = psp_master->sev_data;int rc; -if (psp_master->sev_state ==SEV_STATE_UNINIT ) { +if (sev->state ==SEV_STATE_UNINIT ) { rc =__sev_platform_init_locked (&argp->error);if (rc)return rc;@@ -349,6 +335,7 @@ static int sev_ioctl_do_pek_pdh_gen(int cmd, struct sev_issue_cmd *argp)static int sev_ioctl_do_pek_csr (struct sev_issue_cmd *argp) { +struct sev_device *sev = psp_master->sev_data;struct sev_user_data_pek_csr input;struct sev_data_pek_csr *data;void *blob =NULL ;@@ -382,7 +369,7 @@ static int sev_ioctl_do_pek_csr(struct sev_issue_cmd *argp) data->len = input.length; cmd: -if (psp_master->sev_state ==SEV_STATE_UNINIT ) { +if (sev->state ==SEV_STATE_UNINIT ) { ret =__sev_platform_init_locked (&argp->error);if (ret) goto e_free_blob;@@ -425,21 +412,22 @@ void *psp_copy_user_blob(u64 __user uaddr, u32 len)static int sev_get_api_version (void ) { +struct sev_device *sev = psp_master->sev_data;struct sev_user_data_status *status;int error =0 , ret; - status = &psp_master->status_cmd_buf; + status = &sev->status_cmd_buf; ret =sev_platform_status (status, &error);if (ret) { -dev_err (psp_master->dev, +dev_err (sev->dev,"SEV: failed to get status. Error: %#x\n" , error);return 1 ; } - psp_master->api_major = status->api_major; - psp_master->api_minor = status->api_minor; - psp_master->build = status->build; - psp_master->sev_state = status->state; + sev->api_major = status->api_major; + sev->api_minor = status->api_minor; + sev->build = status->build; + sev->state = status->state;return 0 ; }@@ -535,6 +523,7 @@ static int sev_update_firmware(struct device *dev)static int sev_ioctl_do_pek_import (struct sev_issue_cmd *argp) { +struct sev_device *sev = psp_master->sev_data;struct sev_user_data_pek_cert_import input;struct sev_data_pek_cert_import *data;void *pek_blob, *oca_blob;@@ -568,7 +557,7 @@ static int sev_ioctl_do_pek_import(struct sev_issue_cmd *argp) data->oca_cert_len = input.oca_cert_len;/* If platform is not in INIT state then transition it to INIT */ -if (psp_master->sev_state !=SEV_STATE_INIT ) { +if (sev->state !=SEV_STATE_INIT ) { ret =__sev_platform_init_locked (&argp->error);if (ret) goto e_free_oca;@@ -690,6 +679,7 @@ static int sev_ioctl_do_get_id(struct sev_issue_cmd *argp)static int sev_ioctl_do_pdh_export (struct sev_issue_cmd *argp) { +struct sev_device *sev = psp_master->sev_data;struct sev_user_data_pdh_cert_export input;void *pdh_blob =NULL , *cert_blob =NULL ;struct sev_data_pdh_cert_export *data;@@ -742,7 +732,7 @@ static int sev_ioctl_do_pdh_export(struct sev_issue_cmd *argp) cmd:/* If platform is not in INIT state then transition it to INIT. */ -if (psp_master->sev_state !=SEV_STATE_INIT ) { +if (sev->state !=SEV_STATE_INIT ) { ret =__sev_platform_init_locked (&argp->error);if (ret) goto e_free_cert;@@ -788,7 +778,7 @@ static long sev_ioctl(struct file *file, unsigned int ioctl, unsigned long arg)struct sev_issue_cmd input;int ret = -EFAULT ; -if (!psp_master) +if (!psp_master || !psp_master->sev_data)return -ENODEV ;if (ioctl !=SEV_ISSUE_CMD )@@ -887,9 +877,9 @@ static void sev_exit(struct kref *ref)misc_deregister (&misc_dev->misc); } -static int sev_misc_init (struct psp_device *psp) +static int sev_misc_init (struct sev_device *sev) { -struct device *dev = psp->dev; +struct device *dev = sev->dev;int ret;/* @@ -920,115 +910,61 @@ static int sev_misc_init(struct psp_device *psp)kref_get (&misc_dev->refcount); } -init_waitqueue_head (&psp->sev_int_queue); - psp->sev_misc = misc_dev; +init_waitqueue_head (&sev->int_queue); + sev->misc = misc_dev;dev_dbg (dev,"registered SEV device\n" );return 0 ; } -static int psp_check_sev_support (struct psp_device *psp) -{ -unsigned int val =ioread32 (psp->io_regs + psp->vdata->feature_reg); - -/* -* Check for a access to the registers. If this read returns -* 0xffffffff, it's likely that the system is running a broken -* BIOS which disallows access to the device. Stop here and -* fail the PSP initialization (but not the load, as the CCP -* could get properly initialized). -*/ -if (val ==0xffffffff ) { -dev_notice (psp->dev,"psp: unable to access the device: you might be running a broken BIOS.\n" ); -return -ENODEV ; - } - -if (!(val &1 )) { -/* Device does not support the SEV feature */ -dev_dbg (psp->dev,"psp does not support SEV\n" ); -return -ENODEV ; - } - -return 0 ; -} - -int psp_dev_init (struct sp_device *sp) +int sev_dev_init (struct psp_device *psp) { -struct device *dev = sp->dev; -struct psp_device *psp; -int ret; +struct device *dev = psp->dev; +struct sev_device *sev; +int ret = -ENOMEM ; - ret = -ENOMEM ; - psp =psp_alloc_struct (sp); -if (!psp) + sev =devm_kzalloc (dev,sizeof (*sev),GFP_KERNEL ); +if (!sev) goto e_err; - sp->psp_data = psp; + psp->sev_data = sev; - psp->vdata = (struct psp_vdata *)sp->dev_vdata->psp_vdata; -if (!psp->vdata) { - ret = -ENODEV ; -dev_err (dev,"missing driver data\n" ); - goto e_err; - } + sev->dev = dev; + sev->psp = psp; - psp->io_regs = sp->io_map; + sev->io_regs = psp->io_regs; - ret =psp_check_sev_support (psp); -if (ret) - goto e_disable; +psp_set_sev_irq_handler (psp, sev_irq_handler, sev); -/* Disable and clear interrupts until ready */ -iowrite32 (0 , psp->io_regs + psp->vdata->inten_reg); -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 (ret) { -dev_err (dev,"psp: unable to allocate an IRQ\n" ); - goto e_err; - } - - ret =sev_misc_init (psp); + ret =sev_misc_init (sev);if (ret) goto e_irq; -if (sp->set_psp_master_device) - sp->set_psp_master_device (sp); - -/* Enable interrupt */ -iowrite32 (-1 , psp->io_regs + psp->vdata->inten_reg); - -dev_notice (dev,"psp enabled\n" ); +dev_notice (dev,"sev enabled\n" );return 0 ; e_irq: -sp_free_psp_irq (psp->sp, psp); +psp_clear_sev_irq_handler (psp); e_err: - sp->psp_data =NULL ; + psp->sev_data =NULL ; -dev_notice (dev,"psp initialization failed\n" ); - -return ret; - -e_disable: - sp->psp_data =NULL ; +dev_notice (dev,"sev initialization failed\n" );return ret; } -void psp_dev_destroy (struct sp_device *sp) +void sev_dev_destroy (struct psp_device *psp) { -struct psp_device *psp = sp->psp_data; +struct sev_device *sev = psp->sev_data; -if (!psp) +if (!sev)return ; -if (psp->sev_misc) +if (sev->misc)kref_put (&misc_dev->refcount, sev_exit); -sp_free_psp_irq (sp, psp); +psp_clear_sev_irq_handler (psp); } int sev_issue_cmd_external_user(struct file *filep, unsigned int cmd,@@ -1037,21 +973,18 @@ int sev_issue_cmd_external_user(struct file *filep, unsigned int cmd,if (!filep || filep->f_op != &sev_fops)return -EBADF ; -return sev_do_cmd (cmd, data, error); +return sev_do_cmd (cmd, data, error); }EXPORT_SYMBOL_GPL (sev_issue_cmd_external_user); -void psp_pci_init (void ) +void sev_pci_init (void ) { -struct sp_device *sp; +struct sev_device *sev = psp_master->sev_data;int error, rc; - sp =sp_get_psp_master_device (); -if (!sp) +if (!sev)return ; - psp_master = sp->psp_data; - psp_timeout = psp_probe_timeout;if (sev_get_api_version ())@@ -1067,13 +1000,13 @@ void psp_pci_init(void)* firmware in INIT or WORKING state. */ -if (psp_master->sev_state !=SEV_STATE_UNINIT ) { +if (sev->state !=SEV_STATE_UNINIT ) {sev_platform_shutdown (NULL ); - psp_master->sev_state =SEV_STATE_UNINIT ; + sev->state =SEV_STATE_UNINIT ; }if (sev_version_greater_or_equal (0 ,15 ) && -sev_update_firmware (psp_master->dev) ==0 ) +sev_update_firmware (sev->dev) ==0 )sev_get_api_version ();/* Initialize the platform */ @@ -1086,27 +1019,27 @@ void psp_pci_init(void)* failed and persistent state has been erased. * Retrying INIT command here should succeed. */ -dev_dbg (sp->dev,"SEV: retrying INIT command" ); +dev_dbg (sev->dev,"SEV: retrying INIT command" ); rc =sev_platform_init (&error); }if (rc) { -dev_err (sp->dev,"SEV: failed to INIT error %#x\n" , error); +dev_err (sev->dev,"SEV: failed to INIT error %#x\n" , error);return ; } -dev_info (sp->dev,"SEV API:%d.%d build:%d\n" , psp_master->api_major, - psp_master->api_minor, psp_master->build); +dev_info (sev->dev,"SEV API:%d.%d build:%d\n" , sev->api_major, + sev->api_minor, sev->build);return ; err: - psp_master =NULL ; + psp_master->sev_data =NULL ; } -void psp_pci_exit (void ) +void sev_pci_exit (void ) { -if (!psp_master) +if (!psp_master->sev_data)return ;sev_platform_shutdown (NULL );drivers/crypto/ccp/sev-dev.h +15
-21@@ -24,37 +24,25 @@#include <linux/psp-sev.h> #include <linux/miscdevice.h> -#include "sp-dev.h" - -#define PSP_CMD_COMPLETE BIT(1) - -#define PSP_CMDRESP_CMD_SHIFT 16 -#define PSP_CMDRESP_IOC BIT(0) -#define PSP_CMDRESP_RESP BIT(31) -#define PSP_CMDRESP_ERR_MASK 0xffff - -#define MAX_PSP_NAME_LEN 16 +#define SEV_CMD_COMPLETE BIT(1) +#define SEV_CMDRESP_CMD_SHIFT 16 +#define SEV_CMDRESP_IOC BIT(0)struct sev_misc_dev {struct kref refcount;struct miscdevice misc; }; -struct psp_device { -struct list_head entry; - -struct psp_vdata *vdata; -char name[MAX_PSP_NAME_LEN ]; - +struct sev_device {struct device *dev; -struct sp_device *sp; +struct psp_device *psp;void __iomem *io_regs; -int sev_state; -unsigned int sev_int_rcvd; -wait_queue_head_t sev_int_queue; -struct sev_misc_dev *sev_misc; +int state; +unsigned int int_rcvd; +wait_queue_head_t int_queue; +struct sev_misc_dev *misc;struct sev_user_data_status status_cmd_buf;struct sev_data_init init_cmd_buf;@@ -63,4 +51,10 @@ struct psp_device { u8 build; }; +int sev_dev_init (struct psp_device *psp); +void sev_dev_destroy (struct psp_device *psp); + +void sev_pci_init (void ); +void sev_pci_exit (void ); +#endif /* __SEV_DEV_H */ drivers/crypto/ccp/sp-pci.c +1
-1@@ -22,7 +22,7 @@#include <linux/ccp.h> #include "ccp-dev.h" -#include "sev-dev.h" +#include "psp-dev.h" #define MSIX_VECTORS 2
Re: [RFC PATCH v2 2/6] crypto: ccp - create a generic psp-dev file
Hi Gary,
Quoted 6 lines · Gary R Hook
Quoted 5 lines · Rijo Thomas
The PSP (Platform Security Processor) provides support for key management commands in Secure Encrypted Virtualization (SEV) mode, along with software-based Trusted Execution Environment (TEE) to enable third-party Trusted Applications.
Quoted 7 lines
Quoted 4 lines
Therefore, introduce
psp-dev.candpsp-dev.hfiles, which can invoke SEV (or TEE) initialization based on platform feature support.TEE interface support will be introduced in a later patch.
This patch does not cleanly apply to the current cryptodev-2.6 tree. Please ensure that you have pulled and rebased, built, and tested just prior to sending out your patches.
Thanks for pointing this out. I shall rebase, test and resend the patchset.
Thanks,
Rijo
Quoted 845 lines
grh
Quoted 841 lines
Cc Ard Biesheuvel <[email protected]>Cc Tom Lendacky <[email protected]>Cc Jens Wiklander <[email protected]>Co-developed-by Devaraj Rangasamy <[email protected]>Signed-off-by Devaraj Rangasamy <[email protected]>Signed-off-by Rijo Thomas <[email protected]>---
drivers/crypto/ccp/Makefile | 3 +-drivers/crypto/ccp/psp-dev.c | 194 ++++++++++++++++++++++++++++++ drivers/crypto/ccp/psp-dev.h | 52 +++++++++ drivers/crypto/ccp/sev-dev.c | 273 ++++++++++++++++--------------------------- drivers/crypto/ccp/sev-dev.h | 36 +++--- drivers/crypto/ccp/sp-pci.c | 2 +- 6 files changed, 367 insertions(+), 193 deletions(-)create mode 100644
drivers/crypto/ccp/psp-dev.c
create mode 100644drivers/crypto/ccp/psp-dev.hdrivers/crypto/ccp/Makefile +0
-0@@ -8,7 +8,8 @@ ccp-$(CONFIG_CRYPTO_DEV_SP_CCP) += ccp-dev.o \ccp-dmaengine.o ccp-$(CONFIG_CRYPTO_DEV_CCP_DEBUGFS) += ccp-debugfs.o ccp-$(CONFIG_PCI) += sp-pci.o
drivers/crypto/ccp/Makefile +2
-1-ccp-$(CONFIG_CRYPTO_DEV_SP_PSP) += sev-dev.o +ccp-$(CONFIG_CRYPTO_DEV_SP_PSP) += psp-dev.o \ + sev-dev.oobj-$(CONFIG_CRYPTO_DEV_CCP_CRYPTO) += ccp-crypto.o ccp-crypto-objs := ccp-crypto-main.o \
drivers/crypto/ccp/psp-dev.c new file +194
-0@@ -0,0 +1,194 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* +* AMD Platform Security Processor (PSP) interface +* +* Copyright (C) 2016,2019 Advanced Micro Devices, Inc. +* +* Author: Brijesh Singh <[email protected]> +*/ + +#include <linux/kernel.h> +#include <linux/irqreturn.h> + +#include "sp-dev.h" +#include "psp-dev.h" +#include "sev-dev.h" + +struct psp_device *psp_master; + +static struct psp_device *psp_alloc_struct (struct sp_device *sp) +{ + struct device *dev = sp->dev; + struct psp_device *psp; + + psp = devm_kzalloc(dev, sizeof(*psp), GFP_KERNEL); + if (!psp) + return NULL; + + psp->dev = dev; + psp->sp = sp; + + snprintf(psp->name, sizeof(psp->name), "psp-%u", sp->ord); + + return psp; +} + +static irqreturn_t psp_irq_handler (int irq,void *data) +{ + struct psp_device *psp = data; + unsigned int status; + + /* Read the interrupt status: */ + status = ioread32(psp->io_regs + psp->vdata->intsts_reg); + + /* invoke subdevice interrupt handlers */ + if (status) { + if (psp->sev_irq_handler) + psp->sev_irq_handler(irq, psp->sev_irq_data, status); + } + + /* Clear the interrupt status by writing the same value we read. */ + iowrite32(status, psp->io_regs + psp->vdata->intsts_reg); + + return IRQ_HANDLED; +} + +static int psp_check_sev_support (struct psp_device *psp) +{ + unsigned int val = ioread32(psp->io_regs + psp->vdata->feature_reg); + + /* + * Check for a access to the registers. If this read returns + * 0xffffffff, it's likely that the system is running a broken + * BIOS which disallows access to the device. Stop here and + * fail the PSP initialization (but not the load, as the CCP + * could get properly initialized). + */ + if (val == 0xffffffff) { + dev_notice(psp->dev, "psp: unable to access the device: you might be running a broken BIOS.\n"); + return -ENODEV; + } + + if (!(val & 1)) { + /* Device does not support the SEV feature */ + dev_dbg(psp->dev, "psp does not support SEV\n"); + return -ENODEV; + } + + return 0; +} + +int psp_dev_init (struct sp_device *sp) +{ + struct device *dev = sp->dev; + struct psp_device *psp; + int ret; + + ret = -ENOMEM; + psp = psp_alloc_struct(sp); + if (!psp) + goto e_err; + + sp->psp_data = psp; + + psp->vdata = (struct psp_vdata *)sp->dev_vdata->psp_vdata; + if (!psp->vdata) { + ret = -ENODEV; + dev_err(dev, "missing driver data\n"); + goto e_err; + } + + psp->io_regs = sp->io_map; + + ret = psp_check_sev_support(psp); + if (ret) + goto e_disable; + + /* Disable and clear interrupts until ready */ + iowrite32(0, psp->io_regs + psp->vdata->inten_reg); + 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 (ret) { + dev_err(dev, "psp: unable to allocate an IRQ\n"); + goto e_err; + } + + ret = sev_dev_init(psp); + if (ret) + goto e_irq; + + if (sp->set_psp_master_device) + sp->set_psp_master_device(sp); + + /* Enable interrupt */ + iowrite32(-1, psp->io_regs + psp->vdata->inten_reg); + + dev_notice(dev, "psp enabled\n"); + + return 0; + +e_irq: + sp_free_psp_irq(psp->sp, psp); +e_err: + sp->psp_data = NULL; + + dev_notice(dev, "psp initialization failed\n"); + + return ret; + +e_disable: + sp->psp_data = NULL; + + return ret; +} + +void psp_dev_destroy (struct sp_device *sp) +{ + struct psp_device *psp = sp->psp_data; + + if (!psp) + return; + + sev_dev_destroy(psp); + + sp_free_psp_irq(sp, psp); +} + +void psp_set_sev_irq_handler (struct psp_device *psp,psp_irq_handler_t handler, + void *data) +{ + psp->sev_irq_data = data; + psp->sev_irq_handler = handler; +} + +void psp_clear_sev_irq_handler (struct psp_device *psp) +{ + psp_set_sev_irq_handler(psp, NULL, NULL); +} + +struct psp_device *psp_get_master_device (void ) +{ + struct sp_device *sp = sp_get_psp_master_device(); + + return sp ? sp->psp_data : NULL; +} + +void psp_pci_init (void ) +{ + psp_master = psp_get_master_device(); + + if (!psp_master) + return; + + sev_pci_init(); +} + +void psp_pci_exit (void ) +{ + if (!psp_master) + return; + + sev_pci_exit(); +}drivers/crypto/ccp/psp-dev.h new file +52
-0@@ -0,0 +1,52 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* +* AMD Platform Security Processor (PSP) interface driver +* +* Copyright (C) 2017-2019 Advanced Micro Devices, Inc. +* +* Author: Brijesh Singh <[email protected]> +*/ + +#ifndef __PSP_DEV_H__ +#define __PSP_DEV_H__ + +#include <linux/device.h> +#include <linux/list.h> +#include <linux/bits.h> +#include <linux/interrupt.h> + +#include "sp-dev.h" + +#define PSP_CMDRESP_RESP BIT(31) +#define PSP_CMDRESP_ERR_MASK 0xffff + +#define MAX_PSP_NAME_LEN 16 + +extern struct psp_device *psp_master; + +typedef void (*psp_irq_handler_t )(int ,void *,unsigned int ); + +struct psp_device { + struct list_head entry; + + struct psp_vdata *vdata; + char name[MAX_PSP_NAME_LEN]; + + struct device *dev; + struct sp_device *sp; + + void __iomem *io_regs; + + psp_irq_handler_t sev_irq_handler; + void *sev_irq_data; + + void *sev_data; +}; + +void psp_set_sev_irq_handler (struct psp_device *psp,psp_irq_handler_t handler, + void *data); +void psp_clear_sev_irq_handler (struct psp_device *psp); + +struct psp_device *psp_get_master_device (void ); + +#endif /* __PSP_DEV_H */ drivers/crypto/ccp/sev-dev.c +0
-0@@ -21,7 +21,7 @@ #include <linux/ccp.h> #include <linux/firmware.h>-#include "
sp-dev.h"
+#include "psp-dev.h"
#include "sev-dev.h"
#define DEVICE_NAME "sev"drivers/crypto/ccp/sev-dev.c +8
-19@@ -30,7 +30,6 @@ static DEFINE_MUTEX(sev_cmd_mutex); static struct sev_misc_dev *misc_dev; -static struct psp_device *psp_master; static int psp_cmd_timeout = 100; module_param(psp_cmd_timeout, int, 0644);@@ -45,68 +44,45 @@ static inline bool sev_version_greater_or_equal(u8 maj, u8 min) { - if (psp_master->api_major > maj) - return true; - if (psp_master->api_major == maj && psp_master->api_minor >= min) - return true; - return false; -} - -static struct psp_device *psp_alloc_struct (struct sp_device *sp) -{ - struct device *dev = sp->dev; - struct psp_device *psp; + struct sev_device *sev = psp_master->sev_data; - psp = devm_kzalloc(dev, sizeof(*psp), GFP_KERNEL); - if (!psp) - return NULL; - - psp->dev = dev; - psp->sp = sp; + if (sev->api_major > maj) + return true; - snprintf(psp->name, sizeof(psp->name), "psp-%u", sp->ord); + if (sev->api_major == maj && sev->api_minor >= min) + return true; - return psp; + return false; } -static irqreturn_t psp_irq_handler(int irq, void *data) +static void sev_irq_handler(int irq, void *data, unsigned int status) { - struct psp_device *psp = data; - unsigned int status; + struct sev_device *sev = data; int reg;- /* Read the interrupt status: */
- status =ioread32(psp->io_regs + psp->vdata->intsts_reg); -
/* Check if it is command completion: */
- if (!(status &PSP_CMD_COMPLETE))
- goto done;
+ if (!(status &SEV_CMD_COMPLETE))
+ return;
/* Check if it is SEV command completion: */
- reg =ioread32(psp->io_regs + psp->vdata->cmdresp_reg); + reg =ioread32(sev->io_regs + sev->psp->vdata->cmdresp_reg); if (reg &PSP_CMDRESP_RESP) {
-psp->sev_int_rcvd= 1;
-wake_up(&psp->sev_int_queue);
+sev->int_rcvd= 1;
+wake_up(&sev->int_queue);
}drivers/crypto/ccp/sev-dev.c +0
-6- -done: - /* Clear the interrupt status by writing the same value we read. */ - iowrite32(status, psp->io_regs + psp->vdata->intsts_reg); - - return IRQ_HANDLED;}
-static int sev_wait_cmd_ioc(structpsp_device*psp, +static intsev_wait_cmd_ioc(struct sev_device *sev, unsigned int *reg, unsigned int timeout){
int ret;
- ret = wait_event_timeout(psp->sev_int_queue,
-psp->sev_int_rcvd, timeout * HZ);
+ ret = wait_event_timeout(sev->int_queue,
+sev->int_rcvd, timeout * HZ);
if (!ret)
return-ETIMEDOUT;
- *reg =ioread32(psp->io_regs + psp->vdata->cmdresp_reg); + *reg =ioread32(sev->io_regs + sev->psp->vdata->cmdresp_reg); return 0;
}drivers/crypto/ccp/sev-dev.c +29
-10@@ -150,42 +126,45 @@ static int sev_cmd_buffer_len(int cmd) static int __sev_do_cmd_locked(int cmd, void *data, int *psp_ret) { struct psp_device *psp = psp_master; + struct sev_device *sev; unsigned int phys_lsb, phys_msb; unsigned int reg, ret = 0; - if (!psp) + if (!psp || !psp->sev_data) return -ENODEV; if (psp_dead) return -EBUSY; + sev = psp->sev_data; + /* Get the physical address of the command buffer */ phys_lsb = data ? lower_32_bits(__psp_pa(data)) : 0; phys_msb = data ? upper_32_bits(__psp_pa(data)) : 0; - dev_dbg(psp->dev, "sev command id %#x buffer 0x%08x%08x timeout %us\n", + dev_dbg(sev->dev, "sev command id %#x buffer 0x%08x%08x timeout %us\n", cmd, phys_msb, phys_lsb, psp_timeout); print_hex_dump_debug("(in): ", DUMP_PREFIX_OFFSET, 16, 2, data, sev_cmd_buffer_len(cmd), false); - iowrite32(phys_lsb, psp->io_regs + psp->vdata->cmdbuff_addr_lo_reg); - iowrite32(phys_msb, psp->io_regs + psp->vdata->cmdbuff_addr_hi_reg); + iowrite32(phys_lsb, sev->io_regs + psp->vdata->cmdbuff_addr_lo_reg); + iowrite32(phys_msb, sev->io_regs + psp->vdata->cmdbuff_addr_hi_reg); - psp->sev_int_rcvd = 0; + sev->int_rcvd = 0; reg = cmd; - reg <<= PSP_CMDRESP_CMD_SHIFT; - reg |= PSP_CMDRESP_IOC; - iowrite32(reg, psp->io_regs + psp->vdata->cmdresp_reg); + reg <<= SEV_CMDRESP_CMD_SHIFT; + reg |= SEV_CMDRESP_IOC; + iowrite32(reg, sev->io_regs + psp->vdata->cmdresp_reg); /* wait for command completion */ - ret = sev_wait_cmd_ioc(psp, ®, psp_timeout); + ret = sev_wait_cmd_ioc(sev, ®, psp_timeout); if (ret) { if (psp_ret) *psp_ret = 0; - dev_err(psp->dev, "sev command %#x timed out, disabling PSP \n", cmd); + dev_err(sev->dev, "sev command %#x timed out, disabling PSP\n", cmd); psp_dead = true; return ret;@@ -197,7 +176,7 @@ static int __sev_do_cmd_locked(int cmd, void *data, int *psp_ret) *psp_ret = reg & PSP_CMDRESP_ERR_MASK; if (reg & PSP_CMDRESP_ERR_MASK) { - dev_dbg(psp->dev, "sev command %#x failed (%#010x)\n", + dev_dbg(sev->dev, "sev command %#x failed (%#010x)\n", cmd, reg & PSP_CMDRESP_ERR_MASK); ret = -EIO; }@@ -222,20 +201,23 @@ static int sev_do_cmd(int cmd, void *data, int *psp_ret) static int __sev_platform_init_locked(int *error) { struct psp_device *psp = psp_master; + struct sev_device *sev; int rc = 0; - if (!psp) + if (!psp || !psp->sev_data) return -ENODEV; - if (psp->sev_state == SEV_STATE_INIT) + sev = psp->sev_data; + + if (sev->state == SEV_STATE_INIT) return 0; - rc = __sev_do_cmd_locked(SEV_CMD_INIT, &psp->init_cmd_buf, error); + rc = __sev_do_cmd_locked(SEV_CMD_INIT, &sev->init_cmd_buf, error); if (rc) return rc; - psp->sev_state = SEV_STATE_INIT; - dev_dbg(psp->dev, "SEV firmware initialized\n"); + sev->state = SEV_STATE_INIT; + dev_dbg(sev->dev, "SEV firmware initialized\n"); return rc; }@@ -254,14 +236,15 @@ int sev_platform_init(int *error) static int __sev_platform_shutdown_locked(int *error) { + struct sev_device *sev = psp_master->sev_data; int ret; ret = __sev_do_cmd_locked(SEV_CMD_SHUTDOWN, NULL, error); if (ret) return ret; - psp_master->sev_state = SEV_STATE_UNINIT; - dev_dbg(psp_master->dev, "SEV firmware shutdown\n"); + sev->state = SEV_STATE_UNINIT; + dev_dbg(sev->dev, "SEV firmware shutdown\n"); return ret; }@@ -279,14 +262,15 @@ static int sev_platform_shutdown(int *error) static int sev_get_platform_state(int *state, int *error) { + struct sev_device *sev = psp_master->sev_data; int rc; rc = __sev_do_cmd_locked(SEV_CMD_PLATFORM_STATUS, - &psp_master->status_cmd_buf, error); + &sev->status_cmd_buf, error); if (rc) return rc; - *state = psp_master->status_cmd_buf.state; + *state = sev->status_cmd_buf.state; return rc; } @@ -321,7 +305,8 @@ static int sev_ioctl_do_reset(struct sev_issue_cmd *argp) static int sev_ioctl_do_platform_status(struct sev_issue_cmd *argp) { - struct sev_user_data_status *data = &psp_master->status_cmd_buf; + struct sev_device *sev = psp_master->sev_data; + struct sev_user_data_status *data = &sev->status_cmd_buf;int ret;
ret =__sev_do_cmd_locked(SEV_CMD_PLATFORM_STATUS, data, &argp->error);drivers/crypto/ccp/sev-dev.c +3
-0@@ -336,9 +321,10 @@ static int sev_ioctl_do_platform_status(struct sev_issue_cmd *argp) static int sev_ioctl_do_pek_pdh_gen(int cmd, struct sev_issue_cmd *argp) { + struct sev_device *sev = psp_master->sev_data; int rc; - if (psp_master->sev_state == SEV_STATE_UNINIT) { + if (sev->state == SEV_STATE_UNINIT) { rc = __sev_platform_init_locked(&argp->error); if (rc) return rc;@@ -349,6 +335,7 @@ static int sev_ioctl_do_pek_pdh_gen(int cmd, struct sev_issue_cmd *argp) static int sev_ioctl_do_pek_csr(struct sev_issue_cmd *argp) { + struct sev_device *sev = psp_master->sev_data; struct sev_user_data_pek_csr input; struct sev_data_pek_csr *data; void *blob = NULL;@@ -382,7 +369,7 @@ static int sev_ioctl_do_pek_csr(struct sev_issue_cmd *argp) data->len = input.length;cmd:
- if (psp_master->sev_state==SEV_STATE_UNINIT) { + if (sev->state==SEV_STATE_UNINIT) {
ret =__sev_platform_init_locked(&argp->error); if (ret)
gotoe_free_blob;drivers/crypto/ccp/sev-dev.c +10
-5@@ -425,21 +412,22 @@ void *psp_copy_user_blob(u64 __user uaddr, u32 len) static int sev_get_api_version(void) { + struct sev_device *sev = psp_master->sev_data; struct sev_user_data_status *status; int error = 0, ret; - status = &psp_master->status_cmd_buf; + status = &sev->status_cmd_buf; ret = sev_platform_status(status, &error); if (ret) { - dev_err(psp_master->dev, + dev_err(sev->dev, "SEV: failed to get status. Error: %#x\n", error); return 1; } - psp_master->api_major = status->api_major; - psp_master->api_minor = status->api_minor; - psp_master->build = status->build; - psp_master->sev_state = status->state; + sev->api_major = status->api_major; + sev->api_minor = status->api_minor; + sev->build = status->build; + sev->state = status->state; return 0; }@@ -535,6 +523,7 @@ static int sev_update_firmware(struct device *dev) static int sev_ioctl_do_pek_import(struct sev_issue_cmd *argp) { + struct sev_device *sev = psp_master->sev_data; struct sev_user_data_pek_cert_import input; struct sev_data_pek_cert_import *data; void *pek_blob, *oca_blob;@@ -568,7 +557,7 @@ static int sev_ioctl_do_pek_import(struct sev_issue_cmd *argp) data->oca_cert_len = input.oca_cert_len; /* If platform is not in INIT state then transition it to INIT */ - if (psp_master->sev_state != SEV_STATE_INIT) { + if (sev->state != SEV_STATE_INIT) { ret = __sev_platform_init_locked(&argp->error); if (ret) goto e_free_oca;@@ -690,6 +679,7 @@ static int sev_ioctl_do_get_id(struct sev_issue_cmd *argp) static int sev_ioctl_do_pdh_export(struct sev_issue_cmd *argp) { + struct sev_device *sev = psp_master->sev_data; struct sev_user_data_pdh_cert_export input; void *pdh_blob = NULL, *cert_blob = NULL; struct sev_data_pdh_cert_export *data;@@ -742,7 +732,7 @@ static int sev_ioctl_do_pdh_export(struct sev_issue_cmd *argp)cmd:
/* If platform is not in INIT state then transition it to INIT. */ - if (psp_master->sev_state!=SEV_STATE_INIT) {
+ if (sev->state!=SEV_STATE_INIT) {
ret =__sev_platform_init_locked(&argp->error);
if (ret)
gotoe_free_cert;drivers/crypto/ccp/sev-dev.c +16
-39@@ -788,7 +778,7 @@ static long sev_ioctl(struct file *file, unsigned int ioctl, unsigned long arg) struct sev_issue_cmd input; int ret = -EFAULT; - if (!psp_master) + if (!psp_master || !psp_master->sev_data) return -ENODEV; if (ioctl != SEV_ISSUE_CMD)@@ -887,9 +877,9 @@ static void sev_exit(struct kref *ref) misc_deregister(&misc_dev->misc); } -static int sev_misc_init(struct psp_device *psp) +static int sev_misc_init(struct sev_device *sev) { - struct device *dev = psp->dev; + struct device *dev = sev->dev; int ret; /*@@ -920,115 +910,61 @@ static int sev_misc_init(struct psp_device *psp) kref_get(&misc_dev->refcount); } - init_waitqueue_head(&psp->sev_int_queue); - psp->sev_misc = misc_dev; + init_waitqueue_head(&sev->int_queue); + sev->misc = misc_dev; dev_dbg(dev, "registered SEV device\n"); return 0; } -static int psp_check_sev_support(struct psp_device *psp) -{ - unsigned int val = ioread32(psp->io_regs + psp->vdata->feature_reg); - - /* - * Check for a access to the registers. If this read returns - * 0xffffffff, it's likely that the system is running a broken - * BIOS which disallows access to the device. Stop here and - * fail the PSP initialization (but not the load, as the CCP - * could get properly initialized). - */ - if (val == 0xffffffff) { - dev_notice(psp->dev, "psp: unable to access the device: you might be running a broken BIOS.\n"); - return -ENODEV; - } - - if (!(val & 1)) { - /* Device does not support the SEV feature */ - dev_dbg(psp->dev, "psp does not support SEV\n"); - return -ENODEV; - } - - return 0; -} - -int psp_dev_init (struct sp_device *sp) +int sev_dev_init(struct psp_device *psp) { - struct device *dev = sp->dev; - struct psp_device *psp; - int ret; + struct device *dev = psp->dev; + struct sev_device *sev; + int ret = -ENOMEM; - ret = -ENOMEM; - psp = psp_alloc_struct(sp); - if (!psp) + sev = devm_kzalloc(dev, sizeof(*sev), GFP_KERNEL); + if (!sev) goto e_err; - sp->psp_data = psp; + psp->sev_data = sev; - psp->vdata = (struct psp_vdata *)sp->dev_vdata->psp_vdata; - if (!psp->vdata) { - ret = -ENODEV; - dev_err(dev, "missing driver data\n"); - goto e_err; - } + sev->dev = dev; + sev->psp = psp; - psp->io_regs = sp->io_map; + sev->io_regs = psp->io_regs; - ret = psp_check_sev_support(psp); - if (ret) - goto e_disable; + psp_set_sev_irq_handler(psp, sev_irq_handler, sev);- /* Disable and clear interrupts until ready */ -
iowrite32(0, psp->io_regs + psp->vdata->inten_reg); -iowrite32(-1, psp->io_regs + psp->vdata->intsts_reg);drivers/crypto/ccp/sev-dev.c +1
-9- - /* Request an irq */ - 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; - } - - ret = sev_misc_init(psp); + ret = sev_misc_init(sev);if (ret)
gotoe_irq;
- if (sp->set_psp_master_device)
-sp->set_psp_master_device(sp);drivers/crypto/ccp/sev-dev.c +1
-5- - /* Enable interrupt */ - iowrite32(-1, psp->io_regs + psp->vdata->inten_reg); - - dev_notice(dev, "psp enabled\n"); + dev_notice(dev, "sev enabled\n");return 0;
e_irq:
-sp_free_psp_irq(psp->sp, psp);
+psp_clear_sev_irq_handler(psp);
e_err:
-sp->psp_data= NULL;
+psp->sev_data= NULL;
-dev_notice(dev, "psp initialization failed\n");drivers/crypto/ccp/sev-dev.c +1
-5- - return ret; - -e_disable: - sp->psp_data = NULL; + dev_notice(dev, "sev initialization failed\n");return ret;
}
-voidpsp_dev_destroy(struct sp_device *sp)
+voidsev_dev_destroy(struct psp_device *psp)
{
- structpsp_device*psp =sp->psp_data;
+ structsev_device*sev =psp->sev_data;
- if (!psp)
+ if (!sev)
return;
- if (psp->sev_misc)
+ if (sev->misc)
kref_put(&misc_dev->refcount, sev_exit);
-sp_free_psp_irq(sp, psp);
+psp_clear_sev_irq_handler(psp);
}
int sev_issue_cmd_external_user(struct file *filep, unsigned int cmd,drivers/crypto/ccp/sev-dev.c +6
-4@@ -1037,21 +973,18 @@ int sev_issue_cmd_external_user(struct file *filep, unsigned int cmd, if (!filep || filep->f_op != &sev_fops) return -EBADF; - return sev_do_cmd(cmd, data, error); + return sev_do_cmd(cmd, data, error); } EXPORT_SYMBOL_GPL(sev_issue_cmd_external_user); -void psp_pci_init(void) +void sev_pci_init(void) { - struct sp_device *sp; + struct sev_device *sev = psp_master->sev_data; int error, rc; - sp = sp_get_psp_master_device(); - if (!sp) + if (!sev) return; - psp_master = sp->psp_data; - psp_timeout = psp_probe_timeout; if (sev_get_api_version())@@ -1067,13 +1000,13 @@ void psp_pci_init(void)* firmware in INIT or WORKING state. */ - if (psp_master->sev_state != SEV_STATE_UNINIT) { + if (sev->state != SEV_STATE_UNINIT) { sev_platform_shutdown(NULL); - psp_master->sev_state = SEV_STATE_UNINIT; + sev->state = SEV_STATE_UNINIT; }if (
sev_version_greater_or_equal(0, 15)&& -sev_update_firmware(psp_master->dev)== 0) +sev_update_firmware(sev->dev)== 0)sev_get_api_version();
/* Initialize the platform */drivers/crypto/ccp/sev-dev.c +4
-3@@ -1086,27 +1019,27 @@ void psp_pci_init(void)* failed and persistent state has been erased. * Retrying INIT command here should succeed. */ - dev_dbg(sp->dev, "SEV: retrying INIT command"); + dev_dbg(sev->dev, "SEV: retrying INIT command"); rc = sev_platform_init(&error); } if (rc) { - dev_err(sp->dev, "SEV: failed to INIT error %#x\n", error); + dev_err(sev->dev, "SEV: failed to INIT error %#x\n", error); return; } - dev_info(sp->dev, "SEV API:%d.%d build:%d\n", psp_master->api_major, - psp_master->api_minor, psp_master->build); + dev_info(sev->dev, "SEV API:%d.%d build:%d\n", sev->api_major, + sev->api_minor, sev->build); return;err:
-psp_master= NULL;
+psp_master->sev_data= NULL;
}
-voidpsp_pci_exit(void)
+voidsev_pci_exit(void)
{
- if (!psp_master)
+ if (!psp_master->sev_data)
return;
sev_platform_shutdown(NULL);drivers/crypto/ccp/sev-dev.h +0
-0@@ -24,37 +24,25 @@ #include <linux/psp-sev.h> #include <linux/miscdevice.h>-#include "
sp-dev.h"drivers/crypto/ccp/sev-dev.h +3
-9- -#define PSP_CMD_COMPLETE BIT(1) - -#define PSP_CMDRESP_CMD_SHIFT 16 -#define PSP_CMDRESP_IOC BIT(0) -#define PSP_CMDRESP_RESP BIT(31) -#define PSP_CMDRESP_ERR_MASK 0xffff - -#define MAX_PSP_NAME_LEN 16 +#define SEV_CMD_COMPLETE BIT(1) +#define SEV_CMDRESP_CMD_SHIFT 16 +#define SEV_CMDRESP_IOC BIT(0)struct
sev_misc_dev{
struct kref refcount;
struct miscdevice misc;
};
-structpsp_device{
- structlist_headentry;drivers/crypto/ccp/sev-dev.h +1
-4- - struct psp_vdata *vdata; - char name[MAX_PSP_NAME_LEN]; - +struct sev_device {struct device *dev;
- structsp_device*sp;
+ structpsp_device*psp;
void__iomem*io_regs;
- intsev_state;
- unsigned intsev_int_rcvd;
-wait_queue_head_tsev_int_queue;
- structsev_misc_dev*sev_misc;
+ int state;
+ unsigned intint_rcvd;
+wait_queue_head_tint_queue;
+ structsev_misc_dev*misc;
structsev_user_data_statusstatus_cmd_buf;
structsev_data_initinit_cmd_buf;
@@ -63,4 +51,10 @@ structpsp_device{
u8 build;
};
+intsev_dev_init(struct psp_device *psp);drivers/crypto/ccp/sev-dev.h +5
-0+void sev_dev_destroy (struct psp_device *psp); + +void sev_pci_init (void ); +void sev_pci_exit (void ); +#endif /*
__SEV_DEV_H*/drivers/crypto/ccp/sp-pci.c +1
-1@@ -22,7 +22,7 @@ #include <linux/ccp.h> #include "ccp-dev.h" -#include "sev-dev.h" +#include "psp-dev.h" #define MSIX_VECTORS 2
RFC PATCH v2 3/6 crypto: ccp - move SEV vdata to a dedicated data structure
In reply to Rijo ThomasPSP can support both SEV and TEE interface. Therefore, move SEV specific registers to a dedicated data structure. TEE interface specific registers will be added in a later patch.
--- drivers/crypto/ccp/sev-dev.c | 17 ++++++++++++----- drivers/crypto/ccp/sev-dev.h | 2 ++ drivers/crypto/ccp/sp-dev.h | 6 +++++- drivers/crypto/ccp/sp-pci.c | 16 ++++++++++++---- 4 files changed, 31 insertions(+), 10 deletions(-)
drivers/crypto/ccp/sev-dev.c +12 -5
@@ -65,7 +65,7 @@ static void sev_irq_handler(int irq, void *data, unsigned int status)return ;/* Check if it is SEV command completion: */ - reg =ioread32 (sev->io_regs + sev->psp->vdata->cmdresp_reg); + reg =ioread32 (sev->io_regs + sev->vdata->cmdresp_reg);if (reg &PSP_CMDRESP_RESP ) { sev->int_rcvd =1 ;wake_up (&sev->int_queue);
@@ -82,7 +82,7 @@ static int sev_wait_cmd_ioc(struct sev_device *sev,if (!ret)return -ETIMEDOUT ; - *reg =ioread32 (sev->io_regs + sev->psp->vdata->cmdresp_reg); + *reg =ioread32 (sev->io_regs + sev->vdata->cmdresp_reg);return 0 ; }
@@ -148,15 +148,15 @@ static int __sev_do_cmd_locked(int cmd, void *data, int *psp_ret)print_hex_dump_debug ("(in): " ,DUMP_PREFIX_OFFSET ,16 ,2 , data,sev_cmd_buffer_len (cmd), false); -iowrite32 (phys_lsb, sev->io_regs + psp->vdata->cmdbuff_addr_lo_reg); -iowrite32 (phys_msb, sev->io_regs + psp->vdata->cmdbuff_addr_hi_reg); +iowrite32 (phys_lsb, sev->io_regs + sev->vdata->cmdbuff_addr_lo_reg); +iowrite32 (phys_msb, sev->io_regs + sev->vdata->cmdbuff_addr_hi_reg); sev->int_rcvd =0 ; reg = cmd; reg <<=SEV_CMDRESP_CMD_SHIFT ; reg |=SEV_CMDRESP_IOC ; -iowrite32 (reg, sev->io_regs + psp->vdata->cmdresp_reg); +iowrite32 (reg, sev->io_regs + sev->vdata->cmdresp_reg);/* wait for command completion */ ret =sev_wait_cmd_ioc (sev, ®, psp_timeout);
@@ -934,6 +934,13 @@ int sev_dev_init(struct psp_device *psp) sev->io_regs = psp->io_regs; + sev->vdata = (struct sev_vdata *)psp->vdata->sev; +if (!sev->vdata) { + ret = -ENODEV ; +dev_err (dev,"sev: missing driver data\n" ); + goto e_err; + } +psp_set_sev_irq_handler (psp, sev_irq_handler, sev); ret =sev_misc_init (sev);
drivers/crypto/ccp/sev-dev.h +2 -0
@@ -39,6 +39,8 @@ struct sev_device {void __iomem *io_regs; +struct sev_vdata *vdata; +int state;unsigned int int_rcvd;wait_queue_head_t int_queue;
drivers/crypto/ccp/sp-dev.h +5 -1
@@ -39,10 +39,14 @@ struct ccp_vdata {const unsigned int rsamax; }; -struct psp_vdata { +struct sev_vdata {const unsigned int cmdresp_reg;const unsigned int cmdbuff_addr_lo_reg;const unsigned int cmdbuff_addr_hi_reg; +}; + +struct psp_vdata { +const struct sev_vdata *sev;const unsigned int feature_reg;const unsigned int inten_reg;const unsigned int intsts_reg;
drivers/crypto/ccp/sp-pci.c +12 -4
@@ -262,19 +262,27 @@ static int sp_pci_resume(struct pci_dev *pdev)#endif #ifdef CONFIG_CRYPTO_DEV_SP_PSP -static const struct psp_vdata pspv1 = { +static const struct sev_vdata sevv1 = { .cmdresp_reg =0x10580 , .cmdbuff_addr_lo_reg =0x105e0 , .cmdbuff_addr_hi_reg =0x105e4 , +}; + +static const struct sev_vdata sevv2 = { + .cmdresp_reg =0x10980 , + .cmdbuff_addr_lo_reg =0x109e0 , + .cmdbuff_addr_hi_reg =0x109e4 , +}; + +static const struct psp_vdata pspv1 = { + .sev = &sevv1, .feature_reg =0x105fc , .inten_reg =0x10610 , .intsts_reg =0x10614 , };static const struct psp_vdata pspv2 = { - .cmdresp_reg =0x10980 , - .cmdbuff_addr_lo_reg =0x109e0 , - .cmdbuff_addr_hi_reg =0x109e4 , + .sev = &sevv2, .feature_reg =0x109fc , .inten_reg =0x10690 , .intsts_reg = 0x10694,
Signature · 1 line
1.9.1
RFC PATCH v2 4/6 crypto: ccp - check whether PSP supports SEV or TEE before initialization
In reply to Rijo ThomasRead PSP feature register to check for TEE (Trusted Execution Environment) support.
If neither SEV nor TEE is supported by PSP, then skip PSP initialization.
--- drivers/crypto/ccp/psp-dev.c | 46 +++++++++++++++++++++++++++++++++++++++----- 1 file changed, 41 insertions(+), 5 deletions(-)
drivers/crypto/ccp/psp-dev.c +41 -5
@@ -53,7 +53,7 @@ static irqreturn_t psp_irq_handler(int irq, void *data)return IRQ_HANDLED ; } -static int psp_check_sev_support (struct psp_device *psp) +static unsigned int psp_get_capability (struct psp_device *psp) {unsigned int val =ioread32 (psp->io_regs + psp->vdata->feature_reg);
@@ -66,11 +66,17 @@ static int psp_check_sev_support(struct psp_device *psp)*/ if (val ==0xffffffff ) {dev_notice (psp->dev,"psp: unable to access the device: you might be running a broken BIOS.\n" ); -return -ENODEV ; +return 0 ; } -if (!(val &1 )) { -/* Device does not support the SEV feature */ +return val; +} + +static int psp_check_sev_support (struct psp_device *psp, +unsigned int capability) +{ +/* Check if device supports SEV feature */ +if (!(capability &1 )) {dev_dbg (psp->dev,"psp does not support SEV\n" );return -ENODEV ; }
@@ -78,10 +84,36 @@ static int psp_check_sev_support(struct psp_device *psp)return 0 ; } +static int psp_check_tee_support (struct psp_device *psp, +unsigned int capability) +{ +/* Check if device supports TEE feature */ +if (!(capability &2 )) { +dev_dbg (psp->dev,"psp does not support TEE\n" ); +return -ENODEV ; + } + +return 0 ; +} + +static int psp_check_support (struct psp_device *psp, +unsigned int capability) +{ +int sev_support =psp_check_sev_support (psp, capability); +int tee_support =psp_check_tee_support (psp, capability); + +/* Return error if device neither supports SEV nor TEE */ +if (sev_support && tee_support) +return -ENODEV ; + +return 0 ; +} +int psp_dev_init (struct sp_device *sp) {struct device *dev = sp->dev;struct psp_device *psp; +unsigned int capability;int ret; ret = -ENOMEM ;
@@ -100,7 +132,11 @@ int psp_dev_init(struct sp_device *sp) psp->io_regs = sp->io_map; - ret =psp_check_sev_support (psp); + capability =psp_get_capability (psp); +if (!capability) + goto e_disable; + + ret =psp_check_support (psp, capability);if (ret) goto e_disable;
Signature · 1 line
1.9.1
RFC PATCH v2 5/6 crypto: ccp - add TEE support for Raven Ridge
In reply to Rijo ThomasAdds a PCI device entry for Raven Ridge. Raven Ridge is an APU with a dedicated AMD Secure Processor having Trusted Execution Environment (TEE) support. The TEE provides a secure environment for running Trusted Applications (TAs) which implement security-sensitive parts of a feature.
This patch configures AMD Secure Processor's TEE interface by initializing a ring buffer (shared memory between Rich OS and Trusted OS) which can hold multiple command buffer entries. The TEE interface is facilitated by a set of CPU to PSP mailbox registers.
The next patch will address how commands are submitted to the ring buffer.
--- drivers/crypto/ccp/Makefile | 3 +- drivers/crypto/ccp/psp-dev.c | 39 ++++++- drivers/crypto/ccp/psp-dev.h | 8 ++ drivers/crypto/ccp/sp-dev.h | 11 +- drivers/crypto/ccp/sp-pci.c | 27 ++++- drivers/crypto/ccp/tee-dev.c | 238 +++++++++++++++++++++++++++++++++++++++++++ drivers/crypto/ccp/tee-dev.h | 109 ++++++++++++++++++++ 7 files changed, 431 insertions(+), 4 deletions(-) create mode 100644 drivers/crypto/ccp/tee-dev.c create mode 100644 drivers/crypto/ccp/tee-dev.h
drivers/crypto/ccp/Makefile +2 -1
@@ -9,7 +9,8 @@ ccp-$(CONFIG_CRYPTO_DEV_SP_CCP) += ccp-dev.o \ ccp-$(CONFIG_CRYPTO_DEV_CCP_DEBUGFS) += ccp-debugfs.o ccp-$(CONFIG_PCI) += sp-pci.o ccp-$(CONFIG_CRYPTO_DEV_SP_PSP) += psp-dev.o \ - sev-dev.o + sev-dev.o \ + tee-dev.o obj-$(CONFIG_CRYPTO_DEV_CCP_CRYPTO) += ccp-crypto.o ccp-crypto-objs := ccp-crypto-main.o \
drivers/crypto/ccp/psp-dev.c +38 -1
@@ -13,6 +13,7 @@#include "sp-dev.h" #include "psp-dev.h" #include "sev-dev.h" +#include "tee-dev.h" struct psp_device *psp_master;
@@ -45,6 +46,9 @@ static irqreturn_t psp_irq_handler(int irq, void *data)if (status) {if (psp->sev_irq_handler) psp->sev_irq_handler (irq, psp->sev_irq_data, status); + +if (psp->tee_irq_handler) + psp->tee_irq_handler (irq, psp->tee_irq_data, status); }/* Clear the interrupt status by writing the same value we read. */
@@ -109,6 +113,25 @@ static int psp_check_support(struct psp_device *psp,return 0 ; } +static int psp_init (struct psp_device *psp,unsigned int capability) +{ +int ret; + +if (!psp_check_sev_support (psp, capability)) { + ret =sev_dev_init (psp); +if (ret) +return ret; + } + +if (!psp_check_tee_support (psp, capability)) { + ret =tee_dev_init (psp); +if (ret) +return ret; + } + +return 0 ; +} +int psp_dev_init (struct sp_device *sp) {struct device *dev = sp->dev;
@@ -151,7 +174,7 @@ int psp_dev_init(struct sp_device *sp) goto e_err; } - ret =sev_dev_init (psp); + ret =psp_init (psp, capability);if (ret) goto e_irq;
@@ -189,6 +212,8 @@ void psp_dev_destroy(struct sp_device *sp)sev_dev_destroy (psp); +tee_dev_destroy (psp); +sp_free_psp_irq (sp, psp); }
@@ -204,6 +229,18 @@ void psp_clear_sev_irq_handler(struct psp_device *psp)psp_set_sev_irq_handler (psp,NULL ,NULL ); } +void psp_set_tee_irq_handler (struct psp_device *psp,psp_irq_handler_t handler, +void *data) +{ + psp->tee_irq_data = data; + psp->tee_irq_handler = handler; +} + +void psp_clear_tee_irq_handler (struct psp_device *psp) +{ +psp_set_tee_irq_handler (psp,NULL ,NULL ); +} +struct psp_device *psp_get_master_device (void ) {struct sp_device *sp =sp_get_psp_master_device ();
drivers/crypto/ccp/psp-dev.h +8 -0
@@ -40,13 +40,21 @@ struct psp_device {psp_irq_handler_t sev_irq_handler;void *sev_irq_data; +psp_irq_handler_t tee_irq_handler; +void *tee_irq_data; +void *sev_data; + void *tee_data; };void psp_set_sev_irq_handler (struct psp_device *psp,psp_irq_handler_t handler,void *data);void psp_clear_sev_irq_handler (struct psp_device *psp); +void psp_set_tee_irq_handler (struct psp_device *psp,psp_irq_handler_t handler, +void *data); +void psp_clear_tee_irq_handler (struct psp_device *psp); +struct psp_device *psp_get_master_device (void );#endif /* __PSP_DEV_H */
drivers/crypto/ccp/sp-dev.h +10 -1
@@ -2,7 +2,7 @@/* * AMD Secure Processor driver * -* Copyright (C) 2017-2018 Advanced Micro Devices, Inc. +* Copyright (C) 2017-2019 Advanced Micro Devices, Inc. * * Author: Tom Lendacky <[email protected]> * Author: Gary R Hook <[email protected]>
@@ -45,8 +45,17 @@ struct sev_vdata {const unsigned int cmdbuff_addr_hi_reg; }; +struct tee_vdata { +const unsigned int cmdresp_reg; +const unsigned int cmdbuff_addr_lo_reg; +const unsigned int cmdbuff_addr_hi_reg; +const unsigned int ring_wptr_reg; +const unsigned int ring_rptr_reg; +}; +struct psp_vdata {const struct sev_vdata *sev; +const struct tee_vdata *tee;const unsigned int feature_reg;const unsigned int inten_reg;const unsigned int intsts_reg;
drivers/crypto/ccp/sp-pci.c +26 -1
@@ -2,7 +2,7 @@/* * AMD Secure Processor device driver * -* Copyright (C) 2013,2018 Advanced Micro Devices, Inc. +* Copyright (C) 2013,2019 Advanced Micro Devices, Inc. * * Author: Tom Lendacky <[email protected]> * Author: Gary R Hook <[email protected]>
@@ -274,6 +274,14 @@ static int sp_pci_resume(struct pci_dev *pdev) .cmdbuff_addr_hi_reg = 0x109e4, }; +static const struct tee_vdata teev1 = { + .cmdresp_reg =0x10544 , + .cmdbuff_addr_lo_reg =0x10548 , + .cmdbuff_addr_hi_reg =0x1054c , + .ring_wptr_reg =0x10550 , + .ring_rptr_reg =0x10554 , +}; +static const struct psp_vdata pspv1 = { .sev = &sevv1, .feature_reg =0x105fc ,
@@ -287,6 +295,13 @@ static int sp_pci_resume(struct pci_dev *pdev) .inten_reg = 0x10690, .intsts_reg = 0x10694, }; + +static const struct psp_vdata pspv3 = { + .tee = &teev1, + .feature_reg =0x109fc , + .inten_reg =0x10690 , + .intsts_reg =0x10694 , +};#endif static const struct sp_dev_vdata dev_vdata[] = {
@@ -320,12 +335,22 @@ static int sp_pci_resume(struct pci_dev *pdev) .psp_vdata = &pspv2,#endif }, + {/* 4 */ + .bar = 2, +#ifdef CONFIG_CRYPTO_DEV_SP_CCP + .ccp_vdata = &ccpv5a, +#endif +#ifdef CONFIG_CRYPTO_DEV_SP_PSP + .psp_vdata = &pspv3, +#endif + }, };static const struct pci_device_id sp_pci_table[] = { {PCI_VDEVICE (AMD ,0x1537 ), (kernel_ulong_t)&dev_vdata[0 ] }, {PCI_VDEVICE (AMD ,0x1456 ), (kernel_ulong_t)&dev_vdata[1 ] }, {PCI_VDEVICE (AMD ,0x1468 ), (kernel_ulong_t)&dev_vdata[2 ] }, {PCI_VDEVICE (AMD ,0x1486 ), (kernel_ulong_t)&dev_vdata[3 ] }, + {PCI_VDEVICE (AMD ,0x15DF ), (kernel_ulong_t)&dev_vdata[4 ] },/* Last entry must be zero */ {0 , } };
drivers/crypto/ccp/tee-dev.c new file +238 -0
238 lines not on this page · raw message
drivers/crypto/ccp/tee-dev.h new file +109 -0
109 lines not on this page · raw message
Signature · 1 line
1.9.1
RFC PATCH v2 6/6 crypto: ccp - provide in-kernel API to submit TEE commands
In reply to Rijo ThomasExtend the functionality of AMD Secure Processor (SP) driver by providing an in-kernel API to submit commands to TEE ring buffer for processing by Trusted OS running on AMD Secure Processor.
Following TEE commands are supported by Trusted OS:
* TEE_CMD_ID_LOAD_TA : Load Trusted Application (TA) binary into TEE environment
* TEE_CMD_ID_UNLOAD_TA : Unload TA binary from TEE environment
* TEE_CMD_ID_OPEN_SESSION : Open session with loaded TA
* TEE_CMD_ID_CLOSE_SESSION : Close session with loaded TA
* TEE_CMD_ID_INVOKE_CMD : Invoke a command with loaded TA
* TEE_CMD_ID_MAP_SHARED_MEM : Map shared memory
* TEE_CMD_ID_UNMAP_SHARED_MEM : Unmap shared memory
Linux AMD-TEE driver will use this API to submit command buffers for processing in Trusted Execution Environment. The AMD-TEE driver shall be introduced in a separate patch.
--- drivers/crypto/ccp/tee-dev.c | 126 +++++++++++++++++++++++++++++++++++++++++++ drivers/crypto/ccp/tee-dev.h | 1 + include/linux/psp-tee.h | 73 +++++++++++++++++++++++++ 3 files changed, 200 insertions(+) create mode 100644 include/linux/psp-tee.h
drivers/crypto/ccp/tee-dev.c +126 -0
@@ -14,6 +14,7 @@#include <linux/slab.h> #include <linux/gfp.h> #include <linux/psp-sev.h> +#include <linux/psp-tee.h> #include "psp-dev.h" #include "tee-dev.h"
@@ -38,6 +39,7 @@ static int tee_alloc_ring(struct psp_tee_device *tee, int ring_size) rb_mgr->ring_start = start_addr; rb_mgr->ring_size = ring_size; rb_mgr->ring_pa =__psp_pa (start_addr); +mutex_init (&rb_mgr->mutex);return 0 ; }
@@ -55,6 +57,7 @@ static void tee_free_ring(struct psp_tee_device *tee) rb_mgr->ring_start =NULL ; rb_mgr->ring_size =0 ; rb_mgr->ring_pa =0 ; +mutex_destroy (&rb_mgr->mutex); } static int tee_wait_cmd_poll(struct psp_tee_device *tee, unsigned int timeout,
@@ -236,3 +239,126 @@ void tee_dev_destroy(struct psp_device *psp)tee_destroy_ring (tee); } + +static int tee_submit_cmd (struct psp_tee_device *tee,enum tee_cmd_id cmd_id, +void *buf,size_t len,struct tee_ring_cmd **resp) +{ +struct tee_ring_cmd *cmd; +u32 rptr, wptr; +int nloop =1000 , ret =0 ; + + *resp =NULL ; + +mutex_lock (&tee->rb_mgr.mutex); + + wptr = tee->rb_mgr.wptr; + +/* Check if ring buffer is full */ +do { + rptr =ioread32 (tee->io_regs + tee->vdata->ring_rptr_reg); + +if (!(wptr +sizeof (struct tee_ring_cmd ) == rptr)) +break ; + +dev_info (tee->dev,"tee: ring buffer full. rptr = %u wptr = %u\n" , + rptr, wptr); + +/* Wait if ring buffer is full */ +mutex_unlock (&tee->rb_mgr.mutex); +schedule_timeout_interruptible (msecs_to_jiffies (10 )); +mutex_lock (&tee->rb_mgr.mutex); + + }while (--nloop); + +if (!nloop && (wptr +sizeof (struct tee_ring_cmd ) == rptr)) { +dev_err (tee->dev,"tee: ring buffer full. rptr = %u wptr = %u\n" , + rptr, wptr); + ret = -EBUSY ; + goto unlock; + } + +/* Pointer to empty data entry in ring buffer */ + cmd = (struct tee_ring_cmd *)(tee->rb_mgr.ring_start + wptr); + +/* Write command data into ring buffer */ + cmd->cmd_id = cmd_id; + cmd->cmd_state =TEE_CMD_STATE_INIT ; +memset (&cmd->buf[0 ],0 ,sizeof (cmd->buf)); +memcpy (&cmd->buf[0 ], buf, len); + +/* Update local copy of write pointer */ + tee->rb_mgr.wptr +=sizeof (struct tee_ring_cmd ); +if (tee->rb_mgr.wptr >= tee->rb_mgr.ring_size) + tee->rb_mgr.wptr =0 ; + +/* Trigger interrupt to Trusted OS */ +iowrite32 (tee->rb_mgr.wptr, tee->io_regs + tee->vdata->ring_wptr_reg); + +/* The response is provided by Trusted OS in same +* location as submitted data entry within ring buffer. +*/ + *resp = cmd; + +unlock: +mutex_unlock (&tee->rb_mgr.mutex); + +return ret; +} + +static int tee_wait_cmd_completion (struct psp_tee_device *tee, +struct tee_ring_cmd *resp, +unsigned int timeout) +{ +/* ~5ms sleep per loop => nloop = timeout * 200 */ +int nloop = timeout *200 ; + +while (--nloop) { +if (resp->cmd_state ==TEE_CMD_STATE_COMPLETED ) +return 0 ; + +usleep_range (5000 ,5100 ); + } + +dev_err (tee->dev,"tee: command 0x%x timed out, disabling PSP\n" , + resp->cmd_id); + + psp_dead = true; + +return -ETIMEDOUT ; +} + +int psp_tee_process_cmd (enum tee_cmd_id cmd_id,void *buf,size_t len, +u32 *status) +{ +struct psp_device *psp =psp_get_master_device (); +struct psp_tee_device *tee; +struct tee_ring_cmd *resp; +int ret; + +if (!buf || !status || !len || len >sizeof (resp->buf)) +return -EINVAL ; + + *status =0 ; + +if (!psp || !psp->tee_data) +return -ENODEV ; + +if (psp_dead) +return -EBUSY ; + + tee = psp->tee_data; + + ret =tee_submit_cmd (tee, cmd_id, buf, len, &resp); +if (ret) +return ret; + + ret =tee_wait_cmd_completion (tee, resp,TEE_DEFAULT_TIMEOUT ); +if (ret) +return ret; + +memcpy (buf, &resp->buf[0 ], len); + *status = resp->status; + +return 0 ; +} +EXPORT_SYMBOL (psp_tee_process_cmd);
drivers/crypto/ccp/tee-dev.h +1 -0
@@ -54,6 +54,7 @@ struct tee_init_ring_cmd {* @wptr: index to the last written entry in ring buffer */ struct ring_buf_manager { +struct mutex mutex;/* synchronizes access to ring buffer */ void *ring_start;u32 ring_size;phys_addr_t ring_pa;
include/linux/psp-tee.h new file +73 -0
73 lines not on this page · raw message
Signature · 1 line
1.9.1