mirror of
https://github.com/xemu-project/xemu.git
synced 2026-07-11 01:24:41 +02:00
hw/nvme: connect SPDM over NVMe Security Send/Recv
This patch extends the existing support we have for NVMe with only DoE to also add support to SPDM over the NVMe Security Send/Recv commands. With the new definition of the `spdm-trans` argument, users can specify `spdm_trans=nvme` or `spdm_trans=doe`. This allows us to select the SPDM transport respectively. SPDM over the NVMe Security Send/Recv commands are defined in the DMTF DSP0286. Signed-off-by: Wilfred Mallawa <wilfred.mallawa@wdc.com> Reviewed-by: Jonathan Cameron <jonathan.cameron@huawei.com> Reviewed-by: Klaus Jensen <k.jensen@samsung.com> Reviewed-by: Alistair Francis <alistair.francis@wdc.com> [k.jensen: fix declaration in case statement; fix quotes in docs] Signed-off-by: Klaus Jensen <k.jensen@samsung.com>
This commit is contained in:
committed by
Klaus Jensen
parent
3d8412c2fb
commit
7f2eeccb4b
+8
-2
@@ -98,7 +98,7 @@ Then you can add this to your QEMU command line:
|
|||||||
.. code-block:: shell
|
.. code-block:: shell
|
||||||
|
|
||||||
-drive file=blknvme,if=none,id=mynvme,format=raw \
|
-drive file=blknvme,if=none,id=mynvme,format=raw \
|
||||||
-device nvme,drive=mynvme,serial=deadbeef,spdm_port=2323
|
-device nvme,drive=mynvme,serial=deadbeef,spdm_port=2323,spdm_trans=doe
|
||||||
|
|
||||||
At which point QEMU will try to connect to the SPDM server.
|
At which point QEMU will try to connect to the SPDM server.
|
||||||
|
|
||||||
@@ -113,7 +113,13 @@ of the default. So the entire QEMU command might look like this
|
|||||||
-append "root=/dev/vda console=ttyS0" \
|
-append "root=/dev/vda console=ttyS0" \
|
||||||
-net none -nographic \
|
-net none -nographic \
|
||||||
-drive file=blknvme,if=none,id=mynvme,format=raw \
|
-drive file=blknvme,if=none,id=mynvme,format=raw \
|
||||||
-device nvme,drive=mynvme,serial=deadbeef,spdm_port=2323
|
-device nvme,drive=mynvme,serial=deadbeef,spdm_port=2323,spdm_trans=doe
|
||||||
|
|
||||||
|
The ``spdm_trans`` argument defines the underlying transport type that is
|
||||||
|
emulated by QEMU. For an PCIe NVMe controller, both "doe" and "nvme" are
|
||||||
|
supported. Where, "doe" does SPDM transport over the PCIe extended capability
|
||||||
|
Data Object Exchange (DOE), and "nvme" uses the NVMe Admin Security
|
||||||
|
Send/Receive commands to implement the SPDM transport.
|
||||||
|
|
||||||
.. _DMTF:
|
.. _DMTF:
|
||||||
https://www.dmtf.org/standards/SPDM
|
https://www.dmtf.org/standards/SPDM
|
||||||
|
|||||||
+36
-11
@@ -8943,19 +8943,33 @@ static bool nvme_init_pci(NvmeCtrl *n, PCIDevice *pci_dev, Error **errp)
|
|||||||
|
|
||||||
pcie_cap_deverr_init(pci_dev);
|
pcie_cap_deverr_init(pci_dev);
|
||||||
|
|
||||||
/* DOE Initialisation */
|
/* SPDM Initialisation */
|
||||||
if (pci_dev->spdm_port) {
|
if (pci_dev->spdm_port) {
|
||||||
uint16_t doe_offset = n->params.sriov_max_vfs ?
|
uint16_t doe_offset = PCI_CONFIG_SPACE_SIZE;
|
||||||
PCI_CONFIG_SPACE_SIZE + PCI_ARI_SIZEOF
|
|
||||||
: PCI_CONFIG_SPACE_SIZE;
|
|
||||||
|
|
||||||
pcie_doe_init(pci_dev, &pci_dev->doe_spdm, doe_offset,
|
switch (pci_dev->spdm_trans) {
|
||||||
doe_spdm_prot, true, 0);
|
case SPDM_SOCKET_TRANSPORT_TYPE_PCI_DOE:
|
||||||
|
if (n->params.sriov_max_vfs) {
|
||||||
|
doe_offset += PCI_ARI_SIZEOF;
|
||||||
|
}
|
||||||
|
|
||||||
pci_dev->doe_spdm.spdm_socket = spdm_socket_connect(pci_dev->spdm_port,
|
pcie_doe_init(pci_dev, &pci_dev->doe_spdm, doe_offset,
|
||||||
errp);
|
doe_spdm_prot, true, 0);
|
||||||
|
|
||||||
if (pci_dev->doe_spdm.spdm_socket < 0) {
|
pci_dev->doe_spdm.spdm_socket =
|
||||||
|
spdm_socket_connect(pci_dev->spdm_port, errp);
|
||||||
|
|
||||||
|
if (pci_dev->doe_spdm.spdm_socket < 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SPDM_SOCKET_TRANSPORT_TYPE_NVME:
|
||||||
|
n->spdm_socket = spdm_socket_connect(pci_dev->spdm_port, errp);
|
||||||
|
if (n->spdm_socket < 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -9246,9 +9260,14 @@ static void nvme_exit(PCIDevice *pci_dev)
|
|||||||
g_free(n->cmb.buf);
|
g_free(n->cmb.buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Only one of the `spdm_socket`s below should have been setup */
|
||||||
|
assert(!(pci_dev->doe_spdm.spdm_socket > 0 && n->spdm_socket >= 0));
|
||||||
if (pci_dev->doe_spdm.spdm_socket > 0) {
|
if (pci_dev->doe_spdm.spdm_socket > 0) {
|
||||||
spdm_socket_close(pci_dev->doe_spdm.spdm_socket,
|
spdm_socket_close(pci_dev->doe_spdm.spdm_socket,
|
||||||
SPDM_SOCKET_TRANSPORT_TYPE_PCI_DOE);
|
SPDM_SOCKET_TRANSPORT_TYPE_PCI_DOE);
|
||||||
|
} else if (n->spdm_socket >= 0) {
|
||||||
|
spdm_socket_close(pci_dev->doe_spdm.spdm_socket,
|
||||||
|
SPDM_SOCKET_TRANSPORT_TYPE_NVME);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (n->pmr.dev) {
|
if (n->pmr.dev) {
|
||||||
@@ -9303,6 +9322,8 @@ static const Property nvme_props[] = {
|
|||||||
false),
|
false),
|
||||||
DEFINE_PROP_UINT16("mqes", NvmeCtrl, params.mqes, 0x7ff),
|
DEFINE_PROP_UINT16("mqes", NvmeCtrl, params.mqes, 0x7ff),
|
||||||
DEFINE_PROP_UINT16("spdm_port", PCIDevice, spdm_port, 0),
|
DEFINE_PROP_UINT16("spdm_port", PCIDevice, spdm_port, 0),
|
||||||
|
DEFINE_PROP_SPDM_TRANS("spdm_trans", PCIDevice, spdm_trans,
|
||||||
|
SPDM_SOCKET_TRANSPORT_TYPE_PCI_DOE),
|
||||||
DEFINE_PROP_BOOL("ctratt.mem", NvmeCtrl, params.ctratt.mem, false),
|
DEFINE_PROP_BOOL("ctratt.mem", NvmeCtrl, params.ctratt.mem, false),
|
||||||
DEFINE_PROP_BOOL("atomic.dn", NvmeCtrl, params.atomic_dn, 0),
|
DEFINE_PROP_BOOL("atomic.dn", NvmeCtrl, params.atomic_dn, 0),
|
||||||
DEFINE_PROP_UINT16("atomic.awun", NvmeCtrl, params.atomic_awun, 0),
|
DEFINE_PROP_UINT16("atomic.awun", NvmeCtrl, params.atomic_awun, 0),
|
||||||
@@ -9378,7 +9399,9 @@ static void nvme_pci_write_config(PCIDevice *dev, uint32_t address,
|
|||||||
{
|
{
|
||||||
uint16_t old_num_vfs = pcie_sriov_num_vfs(dev);
|
uint16_t old_num_vfs = pcie_sriov_num_vfs(dev);
|
||||||
|
|
||||||
if (pcie_find_capability(dev, PCI_EXT_CAP_ID_DOE)) {
|
/* DOE is only initialised if SPDM over DOE is used */
|
||||||
|
if (pcie_find_capability(dev, PCI_EXT_CAP_ID_DOE) &&
|
||||||
|
dev->spdm_trans == SPDM_SOCKET_TRANSPORT_TYPE_PCI_DOE) {
|
||||||
pcie_doe_write_config(&dev->doe_spdm, address, val, len);
|
pcie_doe_write_config(&dev->doe_spdm, address, val, len);
|
||||||
}
|
}
|
||||||
pci_default_write_config(dev, address, val, len);
|
pci_default_write_config(dev, address, val, len);
|
||||||
@@ -9389,7 +9412,9 @@ static void nvme_pci_write_config(PCIDevice *dev, uint32_t address,
|
|||||||
static uint32_t nvme_pci_read_config(PCIDevice *dev, uint32_t address, int len)
|
static uint32_t nvme_pci_read_config(PCIDevice *dev, uint32_t address, int len)
|
||||||
{
|
{
|
||||||
uint32_t val;
|
uint32_t val;
|
||||||
if (dev->spdm_port && pcie_find_capability(dev, PCI_EXT_CAP_ID_DOE)) {
|
|
||||||
|
if (dev->spdm_port && pcie_find_capability(dev, PCI_EXT_CAP_ID_DOE) &&
|
||||||
|
(dev->spdm_trans == SPDM_SOCKET_TRANSPORT_TYPE_PCI_DOE)) {
|
||||||
if (pcie_doe_read_config(&dev->doe_spdm, address, len, &val)) {
|
if (pcie_doe_read_config(&dev->doe_spdm, address, len, &val)) {
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
#include "hw/pci/pci.h"
|
#include "hw/pci/pci.h"
|
||||||
#include "hw/pci/pcie.h"
|
#include "hw/pci/pcie.h"
|
||||||
#include "hw/pci/pcie_doe.h"
|
#include "hw/pci/pcie_doe.h"
|
||||||
|
#include "system/spdm-socket.h"
|
||||||
|
|
||||||
#define TYPE_PCI_DEVICE "pci-device"
|
#define TYPE_PCI_DEVICE "pci-device"
|
||||||
typedef struct PCIDeviceClass PCIDeviceClass;
|
typedef struct PCIDeviceClass PCIDeviceClass;
|
||||||
@@ -166,6 +167,7 @@ struct PCIDevice {
|
|||||||
|
|
||||||
/* SPDM */
|
/* SPDM */
|
||||||
uint16_t spdm_port;
|
uint16_t spdm_port;
|
||||||
|
SpdmTransportType spdm_trans;
|
||||||
|
|
||||||
/* DOE */
|
/* DOE */
|
||||||
DOECap doe_spdm;
|
DOECap doe_spdm;
|
||||||
|
|||||||
Reference in New Issue
Block a user