Skip to content

Commit 2a6170d

Browse files
committed
crypto: ccp: Add Platform Security Processor (PSP) device support
The Platform Security Processor (PSP) is part of the AMD Secure Processor (AMD-SP) functionality. The PSP is a dedicated processor that 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. Note that the key management functionality provided by the SEV firmware can be used outside of the kvm-amd driver hence it doesn't need to depend on CONFIG_KVM_AMD. Cc: Paolo Bonzini <[email protected]> Cc: "Radim Krčmář" <[email protected]> Cc: Borislav Petkov <[email protected]> Cc: Herbert Xu <[email protected]> Cc: Gary Hook <[email protected]> Cc: Tom Lendacky <[email protected]> Cc: [email protected] Cc: [email protected] Cc: [email protected] Improvements-by: Borislav Petkov <[email protected]> Signed-off-by: Brijesh Singh <[email protected]> Reviewed-by: Borislav Petkov <[email protected]>
1 parent 592d5e7 commit 2a6170d

File tree

7 files changed

+277
-1
lines changed

7 files changed

+277
-1
lines changed

drivers/crypto/ccp/Kconfig

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,3 +33,14 @@ config CRYPTO_DEV_CCP_CRYPTO
3333
Support for using the cryptographic API with the AMD Cryptographic
3434
Coprocessor. This module supports offload of SHA and AES algorithms.
3535
If you choose 'M' here, this module will be called ccp_crypto.
36+
37+
config CRYPTO_DEV_SP_PSP
38+
bool "Platform Security Processor (PSP) device"
39+
default y
40+
depends on CRYPTO_DEV_CCP_DD && X86_64
41+
help
42+
Provide support for the AMD Platform Security Processor (PSP).
43+
The PSP is a dedicated processor that provides support for key
44+
management commands in Secure Encrypted Virtualization (SEV) mode,
45+
along with software-based Trusted Execution Environment (TEE) to
46+
enable third-party trusted applications.

drivers/crypto/ccp/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ ccp-$(CONFIG_CRYPTO_DEV_SP_CCP) += ccp-dev.o \
88
ccp-dmaengine.o \
99
ccp-debugfs.o
1010
ccp-$(CONFIG_PCI) += sp-pci.o
11+
ccp-$(CONFIG_CRYPTO_DEV_SP_PSP) += psp-dev.o
1112

1213
obj-$(CONFIG_CRYPTO_DEV_CCP_CRYPTO) += ccp-crypto.o
1314
ccp-crypto-objs := ccp-crypto-main.o \

drivers/crypto/ccp/psp-dev.c

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
/*
2+
* AMD Platform Security Processor (PSP) interface
3+
*
4+
* Copyright (C) 2016-2017 Advanced Micro Devices, Inc.
5+
*
6+
* Author: Brijesh Singh <[email protected]>
7+
*
8+
* This program is free software; you can redistribute it and/or modify
9+
* it under the terms of the GNU General Public License version 2 as
10+
* published by the Free Software Foundation.
11+
*/
12+
13+
#include <linux/module.h>
14+
#include <linux/kernel.h>
15+
#include <linux/kthread.h>
16+
#include <linux/sched.h>
17+
#include <linux/interrupt.h>
18+
#include <linux/spinlock.h>
19+
#include <linux/spinlock_types.h>
20+
#include <linux/types.h>
21+
#include <linux/mutex.h>
22+
#include <linux/delay.h>
23+
#include <linux/hw_random.h>
24+
#include <linux/ccp.h>
25+
26+
#include "sp-dev.h"
27+
#include "psp-dev.h"
28+
29+
static struct psp_device *psp_alloc_struct(struct sp_device *sp)
30+
{
31+
struct device *dev = sp->dev;
32+
struct psp_device *psp;
33+
34+
psp = devm_kzalloc(dev, sizeof(*psp), GFP_KERNEL);
35+
if (!psp)
36+
return NULL;
37+
38+
psp->dev = dev;
39+
psp->sp = sp;
40+
41+
snprintf(psp->name, sizeof(psp->name), "psp-%u", sp->ord);
42+
43+
return psp;
44+
}
45+
46+
static irqreturn_t psp_irq_handler(int irq, void *data)
47+
{
48+
return IRQ_HANDLED;
49+
}
50+
51+
int psp_dev_init(struct sp_device *sp)
52+
{
53+
struct device *dev = sp->dev;
54+
struct psp_device *psp;
55+
int ret;
56+
57+
ret = -ENOMEM;
58+
psp = psp_alloc_struct(sp);
59+
if (!psp)
60+
goto e_err;
61+
62+
sp->psp_data = psp;
63+
64+
psp->vdata = (struct psp_vdata *)sp->dev_vdata->psp_vdata;
65+
if (!psp->vdata) {
66+
ret = -ENODEV;
67+
dev_err(dev, "missing driver data\n");
68+
goto e_err;
69+
}
70+
71+
psp->io_regs = sp->io_map + psp->vdata->offset;
72+
73+
/* Disable and clear interrupts until ready */
74+
iowrite32(0, psp->io_regs + PSP_P2CMSG_INTEN);
75+
iowrite32(-1, psp->io_regs + PSP_P2CMSG_INTSTS);
76+
77+
/* Request an irq */
78+
ret = sp_request_psp_irq(psp->sp, psp_irq_handler, psp->name, psp);
79+
if (ret) {
80+
dev_err(dev, "psp: unable to allocate an IRQ\n");
81+
goto e_err;
82+
}
83+
84+
if (sp->set_psp_master_device)
85+
sp->set_psp_master_device(sp);
86+
87+
/* Enable interrupt */
88+
iowrite32(-1, psp->io_regs + PSP_P2CMSG_INTEN);
89+
90+
return 0;
91+
92+
e_err:
93+
sp->psp_data = NULL;
94+
95+
dev_notice(dev, "psp initialization failed\n");
96+
97+
return ret;
98+
}
99+
100+
void psp_dev_destroy(struct sp_device *sp)
101+
{
102+
struct psp_device *psp = sp->psp_data;
103+
104+
sp_free_psp_irq(sp, psp);
105+
}

drivers/crypto/ccp/psp-dev.h

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
/*
2+
* AMD Platform Security Processor (PSP) interface driver
3+
*
4+
* Copyright (C) 2017 Advanced Micro Devices, Inc.
5+
*
6+
* Author: Brijesh Singh <[email protected]>
7+
*
8+
* This program is free software; you can redistribute it and/or modify
9+
* it under the terms of the GNU General Public License version 2 as
10+
* published by the Free Software Foundation.
11+
*/
12+
13+
#ifndef __PSP_DEV_H__
14+
#define __PSP_DEV_H__
15+
16+
#include <linux/device.h>
17+
#include <linux/pci.h>
18+
#include <linux/spinlock.h>
19+
#include <linux/mutex.h>
20+
#include <linux/list.h>
21+
#include <linux/wait.h>
22+
#include <linux/dmapool.h>
23+
#include <linux/hw_random.h>
24+
#include <linux/bitops.h>
25+
#include <linux/interrupt.h>
26+
#include <linux/irqreturn.h>
27+
#include <linux/dmaengine.h>
28+
29+
#include "sp-dev.h"
30+
31+
#define PSP_P2CMSG_INTEN 0x0110
32+
#define PSP_P2CMSG_INTSTS 0x0114
33+
34+
#define PSP_C2PMSG_ATTR_0 0x0118
35+
#define PSP_C2PMSG_ATTR_1 0x011c
36+
#define PSP_C2PMSG_ATTR_2 0x0120
37+
#define PSP_C2PMSG_ATTR_3 0x0124
38+
#define PSP_P2CMSG_ATTR_0 0x0128
39+
40+
#define PSP_CMDRESP_CMD_SHIFT 16
41+
#define PSP_CMDRESP_IOC BIT(0)
42+
#define PSP_CMDRESP_RESP BIT(31)
43+
#define PSP_CMDRESP_ERR_MASK 0xffff
44+
45+
#define MAX_PSP_NAME_LEN 16
46+
47+
struct psp_device {
48+
struct list_head entry;
49+
50+
struct psp_vdata *vdata;
51+
char name[MAX_PSP_NAME_LEN];
52+
53+
struct device *dev;
54+
struct sp_device *sp;
55+
56+
void __iomem *io_regs;
57+
};
58+
59+
#endif /* __PSP_DEV_H */

drivers/crypto/ccp/sp-dev.c

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,8 @@ int sp_init(struct sp_device *sp)
198198
if (sp->dev_vdata->ccp_vdata)
199199
ccp_dev_init(sp);
200200

201+
if (sp->dev_vdata->psp_vdata)
202+
psp_dev_init(sp);
201203
return 0;
202204
}
203205

@@ -206,6 +208,9 @@ void sp_destroy(struct sp_device *sp)
206208
if (sp->dev_vdata->ccp_vdata)
207209
ccp_dev_destroy(sp);
208210

211+
if (sp->dev_vdata->psp_vdata)
212+
psp_dev_destroy(sp);
213+
209214
sp_del_device(sp);
210215
}
211216

@@ -237,6 +242,27 @@ int sp_resume(struct sp_device *sp)
237242
}
238243
#endif
239244

245+
struct sp_device *sp_get_psp_master_device(void)
246+
{
247+
struct sp_device *i, *ret = NULL;
248+
unsigned long flags;
249+
250+
write_lock_irqsave(&sp_unit_lock, flags);
251+
if (list_empty(&sp_units))
252+
goto unlock;
253+
254+
list_for_each_entry(i, &sp_units, entry) {
255+
if (i->psp_data)
256+
break;
257+
}
258+
259+
if (i->get_psp_master_device)
260+
ret = i->get_psp_master_device();
261+
unlock:
262+
write_unlock_irqrestore(&sp_unit_lock, flags);
263+
return ret;
264+
}
265+
240266
static int __init sp_mod_init(void)
241267
{
242268
#ifdef CONFIG_X86

drivers/crypto/ccp/sp-dev.h

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,12 +42,17 @@ struct ccp_vdata {
4242
const unsigned int offset;
4343
const unsigned int rsamax;
4444
};
45+
46+
struct psp_vdata {
47+
const unsigned int offset;
48+
};
49+
4550
/* Structure to hold SP device data */
4651
struct sp_dev_vdata {
4752
const unsigned int bar;
4853

4954
const struct ccp_vdata *ccp_vdata;
50-
void *psp_vdata;
55+
const struct psp_vdata *psp_vdata;
5156
};
5257

5358
struct sp_device {
@@ -68,6 +73,10 @@ struct sp_device {
6873
/* DMA caching attribute support */
6974
unsigned int axcache;
7075

76+
/* get and set master device */
77+
struct sp_device*(*get_psp_master_device)(void);
78+
void (*set_psp_master_device)(struct sp_device *);
79+
7180
bool irq_registered;
7281
bool use_tasklet;
7382

@@ -103,6 +112,7 @@ void sp_free_ccp_irq(struct sp_device *sp, void *data);
103112
int sp_request_psp_irq(struct sp_device *sp, irq_handler_t handler,
104113
const char *name, void *data);
105114
void sp_free_psp_irq(struct sp_device *sp, void *data);
115+
struct sp_device *sp_get_psp_master_device(void);
106116

107117
#ifdef CONFIG_CRYPTO_DEV_SP_CCP
108118

@@ -130,4 +140,16 @@ static inline int ccp_dev_resume(struct sp_device *sp)
130140
}
131141
#endif /* CONFIG_CRYPTO_DEV_SP_CCP */
132142

143+
#ifdef CONFIG_CRYPTO_DEV_SP_PSP
144+
145+
int psp_dev_init(struct sp_device *sp);
146+
void psp_dev_destroy(struct sp_device *sp);
147+
148+
#else /* !CONFIG_CRYPTO_DEV_SP_PSP */
149+
150+
static inline int psp_dev_init(struct sp_device *sp) { return 0; }
151+
static inline void psp_dev_destroy(struct sp_device *sp) { }
152+
153+
#endif /* CONFIG_CRYPTO_DEV_SP_PSP */
154+
133155
#endif

drivers/crypto/ccp/sp-pci.c

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,15 @@
2525
#include <linux/ccp.h>
2626

2727
#include "ccp-dev.h"
28+
#include "psp-dev.h"
2829

2930
#define MSIX_VECTORS 2
3031

3132
struct sp_pci {
3233
int msix_count;
3334
struct msix_entry msix_entry[MSIX_VECTORS];
3435
};
36+
static struct sp_device *sp_dev_master;
3537

3638
static int sp_get_msix_irqs(struct sp_device *sp)
3739
{
@@ -108,6 +110,45 @@ static void sp_free_irqs(struct sp_device *sp)
108110
sp->psp_irq = 0;
109111
}
110112

113+
static bool sp_pci_is_master(struct sp_device *sp)
114+
{
115+
struct device *dev_cur, *dev_new;
116+
struct pci_dev *pdev_cur, *pdev_new;
117+
118+
dev_new = sp->dev;
119+
dev_cur = sp_dev_master->dev;
120+
121+
pdev_new = to_pci_dev(dev_new);
122+
pdev_cur = to_pci_dev(dev_cur);
123+
124+
if (pdev_new->bus->number < pdev_cur->bus->number)
125+
return true;
126+
127+
if (PCI_SLOT(pdev_new->devfn) < PCI_SLOT(pdev_cur->devfn))
128+
return true;
129+
130+
if (PCI_FUNC(pdev_new->devfn) < PCI_FUNC(pdev_cur->devfn))
131+
return true;
132+
133+
return false;
134+
}
135+
136+
static void psp_set_master(struct sp_device *sp)
137+
{
138+
if (!sp_dev_master) {
139+
sp_dev_master = sp;
140+
return;
141+
}
142+
143+
if (sp_pci_is_master(sp))
144+
sp_dev_master = sp;
145+
}
146+
147+
static struct sp_device *psp_get_master(void)
148+
{
149+
return sp_dev_master;
150+
}
151+
111152
static int sp_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
112153
{
113154
struct sp_device *sp;
@@ -166,6 +207,8 @@ static int sp_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
166207
goto e_err;
167208

168209
pci_set_master(pdev);
210+
sp->set_psp_master_device = psp_set_master;
211+
sp->get_psp_master_device = psp_get_master;
169212

170213
ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(48));
171214
if (ret) {
@@ -225,6 +268,12 @@ static int sp_pci_resume(struct pci_dev *pdev)
225268
}
226269
#endif
227270

271+
#ifdef CONFIG_CRYPTO_DEV_SP_PSP
272+
static const struct psp_vdata psp_entry = {
273+
.offset = 0x10500,
274+
};
275+
#endif
276+
228277
static const struct sp_dev_vdata dev_vdata[] = {
229278
{
230279
.bar = 2,
@@ -236,6 +285,9 @@ static const struct sp_dev_vdata dev_vdata[] = {
236285
.bar = 2,
237286
#ifdef CONFIG_CRYPTO_DEV_SP_CCP
238287
.ccp_vdata = &ccpv5a,
288+
#endif
289+
#ifdef CONFIG_CRYPTO_DEV_SP_PSP
290+
.psp_vdata = &psp_entry
239291
#endif
240292
},
241293
{

0 commit comments

Comments
 (0)