crypto/ccp: Implement SEV-TIO PCIe IDE (phase1)

Implement the SEV-TIO (Trusted I/O) firmware interface for PCIe TDISP
(Trust Domain In-Socket Protocol). This enables secure communication
between trusted domains and PCIe devices through the PSP (Platform
Security Processor).

The implementation includes:
- Device Security Manager (DSM) operations for establishing secure links
- SPDM (Security Protocol and Data Model) over DOE (Data Object Exchange)
- IDE (Integrity Data Encryption) stream management for secure PCIe

This module bridges the SEV firmware stack with the generic PCIe TSM
framework.

This is phase1 as described in Documentation/driver-api/pci/tsm.rst.

On AMD SEV, the AMD PSP firmware acts as TSM (manages the security/trust).
The CCP driver provides the interface to it and registers in the TSM
subsystem.

Detect the PSP support (reported via FEATURE_INFO + SNP_PLATFORM_STATUS)
and enable SEV-TIO in the SNP_INIT_EX call if the hardware supports TIO.

Implement SEV TIO PSP command wrappers in sev-dev-tio.c and store
the data in the SEV-TIO-specific structs.

Implement TSM hooks and IDE setup in sev-dev-tsm.c.

Signed-off-by: Alexey Kardashevskiy <aik@amd.com>
Link: https://patch.msgid.link/692f506bb80c9_261c11004@dwillia2-mobl4.notmuch
Acked-by: Tom Lendacky <thomas.lendacky@amd.com>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
This commit is contained in:
Alexey Kardashevskiy
2025-12-02 12:50:33 -08:00
committed by Dan Williams
parent eeb934137d
commit 4be423572d
8 changed files with 1469 additions and 3 deletions
+1
View File
@@ -39,6 +39,7 @@ config CRYPTO_DEV_SP_PSP
bool "Platform Security Processor (PSP) device"
default y
depends on CRYPTO_DEV_CCP_DD && X86_64 && AMD_IOMMU
select PCI_TSM
help
Provide support for the AMD Platform Security Processor (PSP).
The PSP is a dedicated processor that provides support for key
+4
View File
@@ -16,6 +16,10 @@ ccp-$(CONFIG_CRYPTO_DEV_SP_PSP) += psp-dev.o \
hsti.o \
sfs.o
ifeq ($(CONFIG_PCI_TSM),y)
ccp-$(CONFIG_CRYPTO_DEV_SP_PSP) += sev-dev-tsm.o sev-dev-tio.o
endif
obj-$(CONFIG_CRYPTO_DEV_CCP_CRYPTO) += ccp-crypto.o
ccp-crypto-objs := ccp-crypto-main.o \
ccp-crypto-aes.o \
File diff suppressed because it is too large Load Diff
+123
View File
@@ -0,0 +1,123 @@
/* SPDX-License-Identifier: GPL-2.0-only */
#ifndef __PSP_SEV_TIO_H__
#define __PSP_SEV_TIO_H__
#include <linux/pci-tsm.h>
#include <linux/pci-ide.h>
#include <linux/tsm.h>
#include <uapi/linux/psp-sev.h>
struct sla_addr_t {
union {
u64 sla;
struct {
u64 page_type :1,
page_size :1,
reserved1 :10,
pfn :40,
reserved2 :12;
};
};
} __packed;
#define SEV_TIO_MAX_COMMAND_LENGTH 128
/* SPDM control structure for DOE */
struct tsm_spdm {
unsigned long req_len;
void *req;
unsigned long rsp_len;
void *rsp;
};
/* Describes TIO device */
struct tsm_dsm_tio {
u8 cert_slot;
struct sla_addr_t dev_ctx;
struct sla_addr_t req;
struct sla_addr_t resp;
struct sla_addr_t scratch;
struct sla_addr_t output;
size_t output_len;
size_t scratch_len;
struct tsm_spdm spdm;
struct sla_buffer_hdr *reqbuf; /* vmap'ed @req for DOE */
struct sla_buffer_hdr *respbuf; /* vmap'ed @resp for DOE */
int cmd;
int psp_ret;
u8 cmd_data[SEV_TIO_MAX_COMMAND_LENGTH];
void *data_pg; /* Data page for DEV_STATUS/TDI_STATUS/TDI_INFO/ASID_FENCE */
#define TIO_IDE_MAX_TC 8
struct pci_ide *ide[TIO_IDE_MAX_TC];
};
/* Describes TSM structure for PF0 pointed by pci_dev->tsm */
struct tio_dsm {
struct pci_tsm_pf0 tsm;
struct tsm_dsm_tio data;
struct sev_device *sev;
};
/* Data object IDs */
#define SPDM_DOBJ_ID_NONE 0
#define SPDM_DOBJ_ID_REQ 1
#define SPDM_DOBJ_ID_RESP 2
struct spdm_dobj_hdr {
u32 id; /* Data object type identifier */
u32 length; /* Length of the data object, INCLUDING THIS HEADER */
struct { /* Version of the data object structure */
u8 minor;
u8 major;
} version;
} __packed;
/**
* struct sev_tio_status - TIO_STATUS command's info_paddr buffer
*
* @length: Length of this structure in bytes
* @tio_en: Indicates that SNP_INIT_EX initialized the RMP for SEV-TIO
* @tio_init_done: Indicates TIO_INIT has been invoked
* @spdm_req_size_min: Minimum SPDM request buffer size in bytes
* @spdm_req_size_max: Maximum SPDM request buffer size in bytes
* @spdm_scratch_size_min: Minimum SPDM scratch buffer size in bytes
* @spdm_scratch_size_max: Maximum SPDM scratch buffer size in bytes
* @spdm_out_size_min: Minimum SPDM output buffer size in bytes
* @spdm_out_size_max: Maximum for the SPDM output buffer size in bytes
* @spdm_rsp_size_min: Minimum SPDM response buffer size in bytes
* @spdm_rsp_size_max: Maximum SPDM response buffer size in bytes
* @devctx_size: Size of a device context buffer in bytes
* @tdictx_size: Size of a TDI context buffer in bytes
* @tio_crypto_alg: TIO crypto algorithms supported
*/
struct sev_tio_status {
u32 length;
u32 tio_en :1,
tio_init_done :1,
reserved :30;
u32 spdm_req_size_min;
u32 spdm_req_size_max;
u32 spdm_scratch_size_min;
u32 spdm_scratch_size_max;
u32 spdm_out_size_min;
u32 spdm_out_size_max;
u32 spdm_rsp_size_min;
u32 spdm_rsp_size_max;
u32 devctx_size;
u32 tdictx_size;
u32 tio_crypto_alg;
u8 reserved2[12];
} __packed;
int sev_tio_init_locked(void *tio_status_page);
int sev_tio_continue(struct tsm_dsm_tio *dev_data);
int sev_tio_dev_create(struct tsm_dsm_tio *dev_data, u16 device_id, u16 root_port_id,
u8 segment_id);
int sev_tio_dev_connect(struct tsm_dsm_tio *dev_data, u8 tc_mask, u8 ids[8], u8 cert_slot);
int sev_tio_dev_disconnect(struct tsm_dsm_tio *dev_data, bool force);
int sev_tio_dev_reclaim(struct tsm_dsm_tio *dev_data);
#endif /* __PSP_SEV_TIO_H__ */
+405
View File
@@ -0,0 +1,405 @@
// SPDX-License-Identifier: GPL-2.0-only
// Interface to CCP/SEV-TIO for generic PCIe TDISP module
#include <linux/pci.h>
#include <linux/device.h>
#include <linux/tsm.h>
#include <linux/iommu.h>
#include <linux/pci-doe.h>
#include <linux/bitfield.h>
#include <linux/module.h>
#include <asm/sev-common.h>
#include <asm/sev.h>
#include "psp-dev.h"
#include "sev-dev.h"
#include "sev-dev-tio.h"
MODULE_IMPORT_NS("PCI_IDE");
#define TIO_DEFAULT_NR_IDE_STREAMS 1
static uint nr_ide_streams = TIO_DEFAULT_NR_IDE_STREAMS;
module_param_named(ide_nr, nr_ide_streams, uint, 0644);
MODULE_PARM_DESC(ide_nr, "Set the maximum number of IDE streams per PHB");
#define dev_to_sp(dev) ((struct sp_device *)dev_get_drvdata(dev))
#define dev_to_psp(dev) ((struct psp_device *)(dev_to_sp(dev)->psp_data))
#define dev_to_sev(dev) ((struct sev_device *)(dev_to_psp(dev)->sev_data))
#define tsm_dev_to_sev(tsmdev) dev_to_sev((tsmdev)->dev.parent)
#define pdev_to_tio_dsm(pdev) (container_of((pdev)->tsm, struct tio_dsm, tsm.base_tsm))
static int sev_tio_spdm_cmd(struct tio_dsm *dsm, int ret)
{
struct tsm_dsm_tio *dev_data = &dsm->data;
struct tsm_spdm *spdm = &dev_data->spdm;
/* Check the main command handler response before entering the loop */
if (ret == 0 && dev_data->psp_ret != SEV_RET_SUCCESS)
return -EINVAL;
if (ret <= 0)
return ret;
/* ret > 0 means "SPDM requested" */
while (ret == PCI_DOE_FEATURE_CMA || ret == PCI_DOE_FEATURE_SSESSION) {
ret = pci_doe(dsm->tsm.doe_mb, PCI_VENDOR_ID_PCI_SIG, ret,
spdm->req, spdm->req_len, spdm->rsp, spdm->rsp_len);
if (ret < 0)
break;
WARN_ON_ONCE(ret == 0); /* The response should never be empty */
spdm->rsp_len = ret;
ret = sev_tio_continue(dev_data);
}
return ret;
}
static int stream_enable(struct pci_ide *ide)
{
struct pci_dev *rp = pcie_find_root_port(ide->pdev);
int ret;
ret = pci_ide_stream_enable(rp, ide);
if (ret)
return ret;
ret = pci_ide_stream_enable(ide->pdev, ide);
if (ret)
pci_ide_stream_disable(rp, ide);
return ret;
}
static int streams_enable(struct pci_ide **ide)
{
int ret = 0;
for (int i = 0; i < TIO_IDE_MAX_TC; ++i) {
if (ide[i]) {
ret = stream_enable(ide[i]);
if (ret)
break;
}
}
return ret;
}
static void stream_disable(struct pci_ide *ide)
{
pci_ide_stream_disable(ide->pdev, ide);
pci_ide_stream_disable(pcie_find_root_port(ide->pdev), ide);
}
static void streams_disable(struct pci_ide **ide)
{
for (int i = 0; i < TIO_IDE_MAX_TC; ++i)
if (ide[i])
stream_disable(ide[i]);
}
static void stream_setup(struct pci_ide *ide)
{
struct pci_dev *rp = pcie_find_root_port(ide->pdev);
ide->partner[PCI_IDE_EP].rid_start = 0;
ide->partner[PCI_IDE_EP].rid_end = 0xffff;
ide->partner[PCI_IDE_RP].rid_start = 0;
ide->partner[PCI_IDE_RP].rid_end = 0xffff;
ide->pdev->ide_cfg = 0;
ide->pdev->ide_tee_limit = 1;
rp->ide_cfg = 1;
rp->ide_tee_limit = 0;
pci_warn(ide->pdev, "Forcing CFG/TEE for %s", pci_name(rp));
pci_ide_stream_setup(ide->pdev, ide);
pci_ide_stream_setup(rp, ide);
}
static u8 streams_setup(struct pci_ide **ide, u8 *ids)
{
bool def = false;
u8 tc_mask = 0;
int i;
for (i = 0; i < TIO_IDE_MAX_TC; ++i) {
if (!ide[i]) {
ids[i] = 0xFF;
continue;
}
tc_mask |= BIT(i);
ids[i] = ide[i]->stream_id;
if (!def) {
struct pci_ide_partner *settings;
settings = pci_ide_to_settings(ide[i]->pdev, ide[i]);
settings->default_stream = 1;
def = true;
}
stream_setup(ide[i]);
}
return tc_mask;
}
static int streams_register(struct pci_ide **ide)
{
int ret = 0, i;
for (i = 0; i < TIO_IDE_MAX_TC; ++i) {
if (ide[i]) {
ret = pci_ide_stream_register(ide[i]);
if (ret)
break;
}
}
return ret;
}
static void streams_unregister(struct pci_ide **ide)
{
for (int i = 0; i < TIO_IDE_MAX_TC; ++i)
if (ide[i])
pci_ide_stream_unregister(ide[i]);
}
static void stream_teardown(struct pci_ide *ide)
{
pci_ide_stream_teardown(ide->pdev, ide);
pci_ide_stream_teardown(pcie_find_root_port(ide->pdev), ide);
}
static void streams_teardown(struct pci_ide **ide)
{
for (int i = 0; i < TIO_IDE_MAX_TC; ++i) {
if (ide[i]) {
stream_teardown(ide[i]);
pci_ide_stream_free(ide[i]);
ide[i] = NULL;
}
}
}
static int stream_alloc(struct pci_dev *pdev, struct pci_ide **ide,
unsigned int tc)
{
struct pci_dev *rp = pcie_find_root_port(pdev);
struct pci_ide *ide1;
if (ide[tc]) {
pci_err(pdev, "Stream for class=%d already registered", tc);
return -EBUSY;
}
/* FIXME: find a better way */
if (nr_ide_streams != TIO_DEFAULT_NR_IDE_STREAMS)
pci_notice(pdev, "Enable non-default %d streams", nr_ide_streams);
pci_ide_set_nr_streams(to_pci_host_bridge(rp->bus->bridge), nr_ide_streams);
ide1 = pci_ide_stream_alloc(pdev);
if (!ide1)
return -EFAULT;
/* Blindly assign streamid=0 to TC=0, and so on */
ide1->stream_id = tc;
ide[tc] = ide1;
return 0;
}
static struct pci_tsm *tio_pf0_probe(struct pci_dev *pdev, struct sev_device *sev)
{
struct tio_dsm *dsm __free(kfree) = kzalloc(sizeof(*dsm), GFP_KERNEL);
int rc;
if (!dsm)
return NULL;
rc = pci_tsm_pf0_constructor(pdev, &dsm->tsm, sev->tsmdev);
if (rc)
return NULL;
pci_dbg(pdev, "TSM enabled\n");
dsm->sev = sev;
return &no_free_ptr(dsm)->tsm.base_tsm;
}
static struct pci_tsm *dsm_probe(struct tsm_dev *tsmdev, struct pci_dev *pdev)
{
struct sev_device *sev = tsm_dev_to_sev(tsmdev);
if (is_pci_tsm_pf0(pdev))
return tio_pf0_probe(pdev, sev);
return 0;
}
static void dsm_remove(struct pci_tsm *tsm)
{
struct pci_dev *pdev = tsm->pdev;
pci_dbg(pdev, "TSM disabled\n");
if (is_pci_tsm_pf0(pdev)) {
struct tio_dsm *dsm = container_of(tsm, struct tio_dsm, tsm.base_tsm);
pci_tsm_pf0_destructor(&dsm->tsm);
kfree(dsm);
}
}
static int dsm_create(struct tio_dsm *dsm)
{
struct pci_dev *pdev = dsm->tsm.base_tsm.pdev;
u8 segment_id = pdev->bus ? pci_domain_nr(pdev->bus) : 0;
struct pci_dev *rootport = pcie_find_root_port(pdev);
u16 device_id = pci_dev_id(pdev);
u16 root_port_id;
u32 lnkcap = 0;
if (pci_read_config_dword(rootport, pci_pcie_cap(rootport) + PCI_EXP_LNKCAP,
&lnkcap))
return -ENODEV;
root_port_id = FIELD_GET(PCI_EXP_LNKCAP_PN, lnkcap);
return sev_tio_dev_create(&dsm->data, device_id, root_port_id, segment_id);
}
static int dsm_connect(struct pci_dev *pdev)
{
struct tio_dsm *dsm = pdev_to_tio_dsm(pdev);
struct tsm_dsm_tio *dev_data = &dsm->data;
u8 ids[TIO_IDE_MAX_TC];
u8 tc_mask;
int ret;
if (pci_find_doe_mailbox(pdev, PCI_VENDOR_ID_PCI_SIG,
PCI_DOE_FEATURE_SSESSION) != dsm->tsm.doe_mb) {
pci_err(pdev, "CMA DOE MB must support SSESSION\n");
return -EFAULT;
}
ret = stream_alloc(pdev, dev_data->ide, 0);
if (ret)
return ret;
ret = dsm_create(dsm);
if (ret)
goto ide_free_exit;
tc_mask = streams_setup(dev_data->ide, ids);
ret = sev_tio_dev_connect(dev_data, tc_mask, ids, dev_data->cert_slot);
ret = sev_tio_spdm_cmd(dsm, ret);
if (ret)
goto free_exit;
streams_enable(dev_data->ide);
ret = streams_register(dev_data->ide);
if (ret)
goto free_exit;
return 0;
free_exit:
sev_tio_dev_reclaim(dev_data);
streams_disable(dev_data->ide);
ide_free_exit:
streams_teardown(dev_data->ide);
return ret;
}
static void dsm_disconnect(struct pci_dev *pdev)
{
bool force = SYSTEM_HALT <= system_state && system_state <= SYSTEM_RESTART;
struct tio_dsm *dsm = pdev_to_tio_dsm(pdev);
struct tsm_dsm_tio *dev_data = &dsm->data;
int ret;
ret = sev_tio_dev_disconnect(dev_data, force);
ret = sev_tio_spdm_cmd(dsm, ret);
if (ret && !force) {
ret = sev_tio_dev_disconnect(dev_data, true);
sev_tio_spdm_cmd(dsm, ret);
}
sev_tio_dev_reclaim(dev_data);
streams_disable(dev_data->ide);
streams_unregister(dev_data->ide);
streams_teardown(dev_data->ide);
}
static struct pci_tsm_ops sev_tsm_ops = {
.probe = dsm_probe,
.remove = dsm_remove,
.connect = dsm_connect,
.disconnect = dsm_disconnect,
};
void sev_tsm_init_locked(struct sev_device *sev, void *tio_status_page)
{
struct sev_tio_status *t = kzalloc(sizeof(*t), GFP_KERNEL);
struct tsm_dev *tsmdev;
int ret;
WARN_ON(sev->tio_status);
if (!t)
return;
ret = sev_tio_init_locked(tio_status_page);
if (ret) {
pr_warn("SEV-TIO STATUS failed with %d\n", ret);
goto error_exit;
}
tsmdev = tsm_register(sev->dev, &sev_tsm_ops);
if (IS_ERR(tsmdev))
goto error_exit;
memcpy(t, tio_status_page, sizeof(*t));
pr_notice("SEV-TIO status: EN=%d INIT_DONE=%d rq=%d..%d rs=%d..%d "
"scr=%d..%d out=%d..%d dev=%d tdi=%d algos=%x\n",
t->tio_en, t->tio_init_done,
t->spdm_req_size_min, t->spdm_req_size_max,
t->spdm_rsp_size_min, t->spdm_rsp_size_max,
t->spdm_scratch_size_min, t->spdm_scratch_size_max,
t->spdm_out_size_min, t->spdm_out_size_max,
t->devctx_size, t->tdictx_size,
t->tio_crypto_alg);
sev->tsmdev = tsmdev;
sev->tio_status = t;
return;
error_exit:
kfree(t);
pr_err("Failed to enable SEV-TIO: ret=%d en=%d initdone=%d SEV=%d\n",
ret, t->tio_en, t->tio_init_done, boot_cpu_has(X86_FEATURE_SEV));
}
void sev_tsm_uninit(struct sev_device *sev)
{
if (sev->tsmdev)
tsm_unregister(sev->tsmdev);
sev->tsmdev = NULL;
}
+53 -2
View File
@@ -75,6 +75,14 @@ static bool psp_init_on_probe = true;
module_param(psp_init_on_probe, bool, 0444);
MODULE_PARM_DESC(psp_init_on_probe, " if true, the PSP will be initialized on module init. Else the PSP will be initialized on the first command requiring it");
#if IS_ENABLED(CONFIG_PCI_TSM)
static bool sev_tio_enabled = true;
module_param_named(tio, sev_tio_enabled, bool, 0444);
MODULE_PARM_DESC(tio, "Enables TIO in SNP_INIT_EX");
#else
static const bool sev_tio_enabled = false;
#endif
MODULE_FIRMWARE("amd/amd_sev_fam17h_model0xh.sbin"); /* 1st gen EPYC */
MODULE_FIRMWARE("amd/amd_sev_fam17h_model3xh.sbin"); /* 2nd gen EPYC */
MODULE_FIRMWARE("amd/amd_sev_fam19h_model0xh.sbin"); /* 3rd gen EPYC */
@@ -251,7 +259,7 @@ static int sev_cmd_buffer_len(int cmd)
case SEV_CMD_SNP_COMMIT: return sizeof(struct sev_data_snp_commit);
case SEV_CMD_SNP_FEATURE_INFO: return sizeof(struct sev_data_snp_feature_info);
case SEV_CMD_SNP_VLEK_LOAD: return sizeof(struct sev_user_data_snp_vlek_load);
default: return 0;
default: return sev_tio_cmd_buffer_len(cmd);
}
return 0;
@@ -1394,6 +1402,8 @@ static int __sev_snp_init_locked(int *error, unsigned int max_snp_asid)
*
*/
if (sev_version_greater_or_equal(SNP_MIN_API_MAJOR, 52)) {
bool tio_supp = !!(sev->snp_feat_info_0.ebx & SNP_SEV_TIO_SUPPORTED);
/*
* Firmware checks that the pages containing the ranges enumerated
* in the RANGES structure are either in the default page state or in the
@@ -1434,6 +1444,17 @@ static int __sev_snp_init_locked(int *error, unsigned int max_snp_asid)
data.init_rmp = 1;
data.list_paddr_en = 1;
data.list_paddr = __psp_pa(snp_range_list);
data.tio_en = tio_supp && sev_tio_enabled && amd_iommu_sev_tio_supported();
/*
* When psp_init_on_probe is disabled, the userspace calling
* SEV ioctl can inadvertently shut down SNP and SEV-TIO causing
* unexpected state loss.
*/
if (data.tio_en && !psp_init_on_probe)
dev_warn(sev->dev, "SEV-TIO as incompatible with psp_init_on_probe=0\n");
cmd = SEV_CMD_SNP_INIT_EX;
} else {
cmd = SEV_CMD_SNP_INIT;
@@ -1471,7 +1492,8 @@ static int __sev_snp_init_locked(int *error, unsigned int max_snp_asid)
snp_hv_fixed_pages_state_update(sev, HV_FIXED);
sev->snp_initialized = true;
dev_dbg(sev->dev, "SEV-SNP firmware initialized\n");
dev_dbg(sev->dev, "SEV-SNP firmware initialized, SEV-TIO is %s\n",
data.tio_en ? "enabled" : "disabled");
dev_info(sev->dev, "SEV-SNP API:%d.%d build:%d\n", sev->api_major,
sev->api_minor, sev->build);
@@ -1479,6 +1501,23 @@ static int __sev_snp_init_locked(int *error, unsigned int max_snp_asid)
atomic_notifier_chain_register(&panic_notifier_list,
&snp_panic_notifier);
if (data.tio_en) {
/*
* This executes with the sev_cmd_mutex held so down the stack
* snp_reclaim_pages(locked=false) might be needed (which is extremely
* unlikely) but will cause a deadlock.
* Instead of exporting __snp_alloc_firmware_pages(), allocate a page
* for this one call here.
*/
void *tio_status = page_address(__snp_alloc_firmware_pages(
GFP_KERNEL_ACCOUNT | __GFP_ZERO, 0, true));
if (tio_status) {
sev_tsm_init_locked(sev, tio_status);
__snp_free_firmware_pages(virt_to_page(tio_status), 0, true);
}
}
sev_es_tmr_size = SNP_TMR_SIZE;
return 0;
@@ -2758,8 +2797,20 @@ static void __sev_firmware_shutdown(struct sev_device *sev, bool panic)
static void sev_firmware_shutdown(struct sev_device *sev)
{
/*
* Calling without sev_cmd_mutex held as TSM will likely try disconnecting
* IDE and this ends up calling sev_do_cmd() which locks sev_cmd_mutex.
*/
if (sev->tio_status)
sev_tsm_uninit(sev);
mutex_lock(&sev_cmd_mutex);
__sev_firmware_shutdown(sev, false);
kfree(sev->tio_status);
sev->tio_status = NULL;
mutex_unlock(&sev_cmd_mutex);
}
+9
View File
@@ -34,6 +34,8 @@ struct sev_misc_dev {
struct miscdevice misc;
};
struct sev_tio_status;
struct sev_device {
struct device *dev;
struct psp_device *psp;
@@ -61,6 +63,9 @@ struct sev_device {
struct sev_user_data_snp_status snp_plat_status;
struct snp_feature_info snp_feat_info_0;
struct tsm_dev *tsmdev;
struct sev_tio_status *tio_status;
};
int sev_dev_init(struct psp_device *psp);
@@ -74,4 +79,8 @@ void sev_pci_exit(void);
struct page *snp_alloc_hv_fixed_pages(unsigned int num_2mb_pages);
void snp_free_hv_fixed_pages(struct page *page);
void sev_tsm_init_locked(struct sev_device *sev, void *tio_status_page);
void sev_tsm_uninit(struct sev_device *sev);
int sev_tio_cmd_buffer_len(int cmd);
#endif /* __SEV_DEV_H */
+10 -1
View File
@@ -109,6 +109,13 @@ enum sev_cmd {
SEV_CMD_SNP_VLEK_LOAD = 0x0CD,
SEV_CMD_SNP_FEATURE_INFO = 0x0CE,
/* SEV-TIO commands */
SEV_CMD_TIO_STATUS = 0x0D0,
SEV_CMD_TIO_INIT = 0x0D1,
SEV_CMD_TIO_DEV_CREATE = 0x0D2,
SEV_CMD_TIO_DEV_RECLAIM = 0x0D3,
SEV_CMD_TIO_DEV_CONNECT = 0x0D4,
SEV_CMD_TIO_DEV_DISCONNECT = 0x0D5,
SEV_CMD_MAX,
};
@@ -750,7 +757,8 @@ struct sev_data_snp_init_ex {
u32 list_paddr_en:1;
u32 rapl_dis:1;
u32 ciphertext_hiding_en:1;
u32 rsvd:28;
u32 tio_en:1;
u32 rsvd:27;
u32 rsvd1;
u64 list_paddr;
u16 max_snp_asid;
@@ -850,6 +858,7 @@ struct snp_feature_info {
} __packed;
#define SNP_CIPHER_TEXT_HIDING_SUPPORTED BIT(3)
#define SNP_SEV_TIO_SUPPORTED BIT(1) /* EBX */
#ifdef CONFIG_CRYPTO_DEV_SP_PSP