|
@@ -203,6 +203,7 @@
|
|
#include "sysemu/hostmem.h"
|
|
#include "sysemu/hostmem.h"
|
|
#include "hw/pci/msix.h"
|
|
#include "hw/pci/msix.h"
|
|
#include "hw/pci/pcie_sriov.h"
|
|
#include "hw/pci/pcie_sriov.h"
|
|
|
|
+#include "sysemu/spdm-socket.h"
|
|
#include "migration/vmstate.h"
|
|
#include "migration/vmstate.h"
|
|
|
|
|
|
#include "nvme.h"
|
|
#include "nvme.h"
|
|
@@ -8113,6 +8114,27 @@ static int nvme_add_pm_capability(PCIDevice *pci_dev, uint8_t offset)
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+static bool pcie_doe_spdm_rsp(DOECap *doe_cap)
|
|
|
|
+{
|
|
|
|
+ void *req = pcie_doe_get_write_mbox_ptr(doe_cap);
|
|
|
|
+ uint32_t req_len = pcie_doe_get_obj_len(req) * 4;
|
|
|
|
+ void *rsp = doe_cap->read_mbox;
|
|
|
|
+ uint32_t rsp_len = SPDM_SOCKET_MAX_MESSAGE_BUFFER_SIZE;
|
|
|
|
+
|
|
|
|
+ uint32_t recvd = spdm_socket_rsp(doe_cap->spdm_socket,
|
|
|
|
+ SPDM_SOCKET_TRANSPORT_TYPE_PCI_DOE,
|
|
|
|
+ req, req_len, rsp, rsp_len);
|
|
|
|
+ doe_cap->read_mbox_len += DIV_ROUND_UP(recvd, 4);
|
|
|
|
+
|
|
|
|
+ return recvd != 0;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static DOEProtocol doe_spdm_prot[] = {
|
|
|
|
+ { PCI_VENDOR_ID_PCI_SIG, PCI_SIG_DOE_CMA, pcie_doe_spdm_rsp },
|
|
|
|
+ { PCI_VENDOR_ID_PCI_SIG, PCI_SIG_DOE_SECURED_CMA, pcie_doe_spdm_rsp },
|
|
|
|
+ { }
|
|
|
|
+};
|
|
|
|
+
|
|
static bool nvme_init_pci(NvmeCtrl *n, PCIDevice *pci_dev, Error **errp)
|
|
static bool nvme_init_pci(NvmeCtrl *n, PCIDevice *pci_dev, Error **errp)
|
|
{
|
|
{
|
|
ERRP_GUARD();
|
|
ERRP_GUARD();
|
|
@@ -8200,6 +8222,25 @@ static bool nvme_init_pci(NvmeCtrl *n, PCIDevice *pci_dev, Error **errp)
|
|
|
|
|
|
nvme_update_msixcap_ts(pci_dev, n->conf_msix_qsize);
|
|
nvme_update_msixcap_ts(pci_dev, n->conf_msix_qsize);
|
|
|
|
|
|
|
|
+ pcie_cap_deverr_init(pci_dev);
|
|
|
|
+
|
|
|
|
+ /* DOE Initialisation */
|
|
|
|
+ if (pci_dev->spdm_port) {
|
|
|
|
+ uint16_t doe_offset = n->params.sriov_max_vfs ?
|
|
|
|
+ PCI_CONFIG_SPACE_SIZE + PCI_ARI_SIZEOF
|
|
|
|
+ : PCI_CONFIG_SPACE_SIZE;
|
|
|
|
+
|
|
|
|
+ pcie_doe_init(pci_dev, &pci_dev->doe_spdm, doe_offset,
|
|
|
|
+ doe_spdm_prot, true, 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;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
if (n->params.cmb_size_mb) {
|
|
if (n->params.cmb_size_mb) {
|
|
nvme_init_cmb(n, pci_dev);
|
|
nvme_init_cmb(n, pci_dev);
|
|
}
|
|
}
|
|
@@ -8446,6 +8487,11 @@ static void nvme_exit(PCIDevice *pci_dev)
|
|
g_free(n->cmb.buf);
|
|
g_free(n->cmb.buf);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ if (pci_dev->doe_spdm.spdm_socket > 0) {
|
|
|
|
+ spdm_socket_close(pci_dev->doe_spdm.spdm_socket,
|
|
|
|
+ SPDM_SOCKET_TRANSPORT_TYPE_PCI_DOE);
|
|
|
|
+ }
|
|
|
|
+
|
|
if (n->pmr.dev) {
|
|
if (n->pmr.dev) {
|
|
host_memory_backend_set_mapped(n->pmr.dev, false);
|
|
host_memory_backend_set_mapped(n->pmr.dev, false);
|
|
}
|
|
}
|
|
@@ -8491,6 +8537,7 @@ static Property nvme_props[] = {
|
|
DEFINE_PROP_BOOL("msix-exclusive-bar", NvmeCtrl, params.msix_exclusive_bar,
|
|
DEFINE_PROP_BOOL("msix-exclusive-bar", NvmeCtrl, params.msix_exclusive_bar,
|
|
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_END_OF_LIST(),
|
|
DEFINE_PROP_END_OF_LIST(),
|
|
};
|
|
};
|
|
|
|
|
|
@@ -8562,11 +8609,25 @@ 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)) {
|
|
|
|
+ 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);
|
|
pcie_cap_flr_write_config(dev, address, val, len);
|
|
pcie_cap_flr_write_config(dev, address, val, len);
|
|
nvme_sriov_post_write_config(dev, old_num_vfs);
|
|
nvme_sriov_post_write_config(dev, old_num_vfs);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+static uint32_t nvme_pci_read_config(PCIDevice *dev, uint32_t address, int len)
|
|
|
|
+{
|
|
|
|
+ uint32_t val;
|
|
|
|
+ if (dev->spdm_port && pcie_find_capability(dev, PCI_EXT_CAP_ID_DOE)) {
|
|
|
|
+ if (pcie_doe_read_config(&dev->doe_spdm, address, len, &val)) {
|
|
|
|
+ return val;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ return pci_default_read_config(dev, address, len);
|
|
|
|
+}
|
|
|
|
+
|
|
static const VMStateDescription nvme_vmstate = {
|
|
static const VMStateDescription nvme_vmstate = {
|
|
.name = "nvme",
|
|
.name = "nvme",
|
|
.unmigratable = 1,
|
|
.unmigratable = 1,
|
|
@@ -8579,6 +8640,7 @@ static void nvme_class_init(ObjectClass *oc, void *data)
|
|
|
|
|
|
pc->realize = nvme_realize;
|
|
pc->realize = nvme_realize;
|
|
pc->config_write = nvme_pci_write_config;
|
|
pc->config_write = nvme_pci_write_config;
|
|
|
|
+ pc->config_read = nvme_pci_read_config;
|
|
pc->exit = nvme_exit;
|
|
pc->exit = nvme_exit;
|
|
pc->class_id = PCI_CLASS_STORAGE_EXPRESS;
|
|
pc->class_id = PCI_CLASS_STORAGE_EXPRESS;
|
|
pc->revision = 2;
|
|
pc->revision = 2;
|