qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v1 QEMU CXL modifications for openspdm 0/1] Testing PCIe DOE in QEMU CXL/PCIe Device using openspdm
@ 2021-06-26  0:02 Chris Browy
  2021-06-26  0:05 ` [PATCH v1 QEMU CXL modifications for openspdm 1/1] pcie/spdm: PCIe CMA implementation Chris Browy
  2021-06-29 12:25 ` [PATCH v1 QEMU CXL modifications for openspdm 0/1] Testing PCIe DOE in QEMU CXL/PCIe Device using openspdm Jonathan Cameron
  0 siblings, 2 replies; 3+ messages in thread
From: Chris Browy @ 2021-06-26  0:02 UTC (permalink / raw)
  To: mst
  Cc: ben.widawsky, david, qemu-devel, vishal.l.verma, jgroves,
	Chris Browy, armbru, linux-cxl, f4bug, hchkuo, tyshao,
	jonathan.cameron, imammedo, dan.j.williams, ira.weiny

This patch series provides an implementation of the the Data Object Exchange
(DOE) for Component Measurement and Authentication (CMA) of the Security
Protocol and Data Model (SPDM). 

This patch is based on 
[1] [PATCH v1 openspdm on QEMU CXL/PCIe Device 0/2] Testing PCIe DOE in QEMU CXL/PCIe Device using openspdm
https://lore.kernel.org/qemu-devel/1624665280-3595-1-git-send-email-cbrowy@avery-design.com/T/#u
[2] QEMU DOE: [PATCH v6 cxl2.0-v6-doe 0/6] QEMU PCIe DOE for PCIe 4.0/5.0 and CXL 2.0
https://lore.kernel.org/qemu-devel/1623329999-15662-1-git-send-email-cbrowy@avery-design.com/

Openspdm is an emulator composed of an SPDM requester and an SPDM responder.
The default SpdmEmu usage have the requester and responder communicate with
each other via a TCP socket. 

However to test PCIe DOE support in QEMU PCIe/CXL device directly, the openspdm
requester is modified to use pwrite/pread for MMIO access to the
QEMU CXL Device DOE capability (hw/mem/cxl_type3.c).  The openspdm
requester is run as user application targeting the CXL Device.

Follow the readme.md under [1] to build this enhanced version of openspdm.

The QEMU CXL device is extended usig the "-spdm=<bool>" option to turn on/off
the DOE/CMA capability. Once the option is turned on (-spdm=true) the CXL
device can communicate with Openspdm's responder to get the data object of
SPDM/secured SPDM.  QEMU and SPDM responder communicate over client-server
method.

Build the QEMU with patch series applied to [2].

Now run the system as follows:

1. Start Responder process:
    ./openspdm/Build/RELEASE_GCC/X64/SpdmResponderEmu --trans PCI_DOE

2. Start QEMU process:
    qemu-system-x86_64 \
    -nic user,hostfwd=tcp::2222-:22 \
	-machine type=pc-q35-4.0 \
	-smp 8,sockets=2,cores=2,threads=2 \
	-m 4G \
	-boot order=d \
	-k 'en-us' \
	-vga virtio \
	-drive file=<path to qcow>,format=qcow2 \
	-drive if=pflash,format=raw,readonly=on,file=<path to OVMF_CODE.fd> \
	-drive if=pflash,format=raw,file=<path to OVMF_VARS.fd> \
	-object memory-backend-file,id=cxl-mem2,share=on,mem-path=/tmp/cxl-mem2,size=1K \
	-object memory-backend-file,id=cxl-mem1,share=on,mem-path=/tmp/cxl-mem,size=512M \
	-device pxb-cxl,id=cxl.0,bus=pcie.0,bus_nr=52,uid=0,len-window-base=1,window-base[0]=0x4c0000000,memdev[0]=cxl-mem1 \
	-device cxl-rp,id=rp0,bus=cxl.0,addr=0.0,chassis=0,slot=0 \
	-device cxl-type3,bus=rp0,memdev=cxl-mem1,id=cxl-pmem0,size=256M,lsa=cxl-mem2,spdm=true

3. Next copy the openspdm build into QEMU qcow

    scp -rP2222 openspdm qemu@localhost:.

4. Next ssh to QEMU emulator and execute the requester user application

    sudo ./openspdm/Build/RELEASE_GCC/X64/SpdmRequesterEmu --trans PCI_DOE -s 35:00.0

hchkuo (1):
  pcie/spdm: PCIe CMA implementation

 hw/mem/cxl_type3.c              |  31 +++-
 hw/pci/Kconfig                  |   4 +
 hw/pci/SpdmEmuCommand.c         | 319 ++++++++++++++++++++++++++++++++++++++++
 hw/pci/meson.build              |   1 +
 include/hw/cxl/cxl_device.h     |   2 +
 include/hw/pci/SpdmEmuCommand.h |  21 +++
 include/hw/pci/pcie_doe.h       |   2 +
 7 files changed, 377 insertions(+), 3 deletions(-)
 create mode 100644 hw/pci/SpdmEmuCommand.c
 create mode 100644 include/hw/pci/SpdmEmuCommand.h

-- 
1.8.3.1



^ permalink raw reply	[flat|nested] 3+ messages in thread

* [PATCH v1 QEMU CXL modifications for openspdm 1/1] pcie/spdm: PCIe CMA implementation
  2021-06-26  0:02 [PATCH v1 QEMU CXL modifications for openspdm 0/1] Testing PCIe DOE in QEMU CXL/PCIe Device using openspdm Chris Browy
@ 2021-06-26  0:05 ` Chris Browy
  2021-06-29 12:25 ` [PATCH v1 QEMU CXL modifications for openspdm 0/1] Testing PCIe DOE in QEMU CXL/PCIe Device using openspdm Jonathan Cameron
  1 sibling, 0 replies; 3+ messages in thread
From: Chris Browy @ 2021-06-26  0:05 UTC (permalink / raw)
  To: mst
  Cc: ben.widawsky, david, qemu-devel, vishal.l.verma, jgroves,
	Chris Browy, armbru, linux-cxl, f4bug, hchkuo, tyshao,
	jonathan.cameron, imammedo, dan.j.williams, ira.weiny

From: hchkuo <hchkuo@avery-design.com.tw>

The Data Object Exchange implementation of Component Measurement
and Authentication (CMA). This patch is basically based on Openspdm:
https://github.com/jyao1/openspdm.git.

Openspdm is an emulator composed of an SPDM requester and an SPDM
responder. The requester and responder communicate with each other via
a TCP socket. The Openspdm requester is merged to this patch as a DOE
capability in hw/mem/cxl_type3.c. The "-spdm=<bool>" is provided to turn
on/off the CMA capability. Once the option is turned on (-spdm=true) the 
CXL device can communicate with Openspdm's responder to get the data 
object of SPDM/secured SPDM.

Signed-off-by: hchkuo <hchkuo@avery-design.com.tw>
Signed-off-by: Chris Browy <cbrowy@avery-design.com>
---
 hw/mem/cxl_type3.c              |  31 +++-
 hw/pci/Kconfig                  |   4 +
 hw/pci/SpdmEmuCommand.c         | 319 ++++++++++++++++++++++++++++++++++++++++
 hw/pci/meson.build              |   1 +
 include/hw/cxl/cxl_device.h     |   2 +
 include/hw/pci/SpdmEmuCommand.h |  21 +++
 include/hw/pci/pcie_doe.h       |   2 +
 7 files changed, 377 insertions(+), 3 deletions(-)
 create mode 100644 hw/pci/SpdmEmuCommand.c
 create mode 100644 include/hw/pci/SpdmEmuCommand.h

diff --git a/hw/mem/cxl_type3.c b/hw/mem/cxl_type3.c
index 4b4097f..da38f3f 100644
--- a/hw/mem/cxl_type3.c
+++ b/hw/mem/cxl_type3.c
@@ -16,6 +16,8 @@
 #include "hw/pci/msi.h"
 #include "hw/pci/msix.h"
 
+#include "hw/pci/SpdmEmuCommand.h"
+
 #define DWORD_BYTE 4
 
 /* This function will be used when cdat file is not specified */
@@ -266,6 +268,9 @@ static uint32_t ct3d_config_read(PCIDevice *pci_dev, uint32_t addr, int size)
 
     if (pcie_doe_read_config(&ct3d->doe_comp, addr, size, &val)) {
         return val;
+    } else if (ct3d->use_spdm &&
+               pcie_doe_read_config(&ct3d->doe_spdm, addr, size, &val)) {
+        return val;
     } else if (pcie_doe_read_config(&ct3d->doe_cdat, addr, size, &val)) {
         return val;
     }
@@ -278,6 +283,9 @@ static void ct3d_config_write(PCIDevice *pci_dev, uint32_t addr, uint32_t val,
 {
     CXLType3Dev *ct3d = CT3(pci_dev);
 
+    if (ct3d->use_spdm) {
+        pcie_doe_write_config(&ct3d->doe_spdm, addr, val, size);
+    }
     pcie_doe_write_config(&ct3d->doe_comp, addr, val, size);
     pcie_doe_write_config(&ct3d->doe_cdat, addr, val, size);
     pci_default_write_config(pci_dev, addr, val, size);
@@ -472,6 +480,12 @@ static MemoryRegion *cxl_md_get_memory_region(MemoryDeviceState *md,
     return ct3d->cxl_dstate.pmem;
 }
 
+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 DOEProtocol doe_comp_prot[] = {
     {CXL_VENDOR_ID, CXL_DOE_COMPLIANCE, cxl_doe_compliance_rsp},
     {},
@@ -489,7 +503,7 @@ static void ct3_realize(PCIDevice *pci_dev, Error **errp)
     ComponentRegisters *regs = &cxl_cstate->crb;
     MemoryRegion *mr = &regs->component_registers;
     uint8_t *pci_conf = pci_dev->config;
-    unsigned short msix_num = 2;
+    unsigned short msix_num = 3;
     int i;
 
     if (!ct3d->cxl_dstate.pmem) {
@@ -528,13 +542,22 @@ static void ct3_realize(PCIDevice *pci_dev, Error **errp)
     }
 
     /* DOE Initailization */
-    pcie_doe_init(pci_dev, &ct3d->doe_comp, 0x160, doe_comp_prot, true, 0);
-    pcie_doe_init(pci_dev, &ct3d->doe_cdat, 0x190, doe_cdat_prot, true, 1);
+    if (ct3d->use_spdm) {
+        spdm_sock_init(errp);
+        pcie_doe_init(pci_dev, &ct3d->doe_spdm, 0x160, doe_spdm_prot, true, 2);
+    }
+    pcie_doe_init(pci_dev, &ct3d->doe_comp, 0x190, doe_comp_prot, true, 1);
+    pcie_doe_init(pci_dev, &ct3d->doe_cdat, 0x1b0, doe_cdat_prot, true, 0);
 
     cxl_cstate->cdat.build_cdat_table = build_default_cdat_table;
     cxl_doe_cdat_init(cxl_cstate, errp);
 }
 
+static void ct3_exit(PCIDevice *pci_dev)
+{
+    spdm_sock_fini();
+}
+
 static uint64_t cxl_md_get_addr(const MemoryDeviceState *md)
 {
     CXLType3Dev *ct3d = CT3(md);
@@ -570,6 +593,7 @@ static Property ct3_props[] = {
     DEFINE_PROP_LINK("lsa", CXLType3Dev, lsa, TYPE_MEMORY_BACKEND,
                      HostMemoryBackend *),
     DEFINE_PROP_STRING("cdat", CXLType3Dev, cxl_cstate.cdat.filename),
+    DEFINE_PROP_BOOL("spdm", CXLType3Dev, use_spdm, false),
     DEFINE_PROP_END_OF_LIST(),
 };
 
@@ -658,6 +682,7 @@ static void ct3_class_init(ObjectClass *oc, void *data)
     CXLType3Class *cvc = CXL_TYPE3_DEV_CLASS(oc);
 
     pc->realize = ct3_realize;
+    pc->exit = ct3_exit;
     pc->class_id = PCI_CLASS_STORAGE_EXPRESS;
     pc->vendor_id = PCI_VENDOR_ID_INTEL;
     pc->device_id = 0xd93; /* LVF for now */
diff --git a/hw/pci/Kconfig b/hw/pci/Kconfig
index 77f8b00..181495e 100644
--- a/hw/pci/Kconfig
+++ b/hw/pci/Kconfig
@@ -13,3 +13,7 @@ config MSI_NONBROKEN
     # or support it and have a good implementation. See commit
     # 47d2b0f33c664533b8dbd5cb17faa8e6a01afe1f.
     bool
+
+config PCIE_SPDM
+    bool
+    default y
diff --git a/hw/pci/SpdmEmuCommand.c b/hw/pci/SpdmEmuCommand.c
new file mode 100644
index 0000000..b1944fa
--- /dev/null
+++ b/hw/pci/SpdmEmuCommand.c
@@ -0,0 +1,319 @@
+/**
+@file
+UEFI OS based application.
+
+Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "hw/pci/SpdmEmuCommand.h"
+#include "qapi/error.h"
+#include <sys/socket.h>
+#include <arpa/inet.h>
+
+#define DWORD_BYTE 4
+
+struct in_addr mIpAddress = {0x0100007F};
+int ClientSocket;
+uint32_t mUseTransportLayer = SOCKET_TRANSPORT_TYPE_PCI_DOE;
+
+/**
+  This function dump raw data.
+
+  @param  Data  raw data
+  @param  Size  raw data size
+**/
+static void DumpData(uint8_t *Data, uint64_t Size)
+{
+    uint64_t Index;
+
+    for (Index = 0; Index < Size; Index++) {
+        if (Index != 0) {
+            printf (" ");
+        }
+        printf ("%02x", Data[Index]);
+    }
+    printf("\n");
+}
+
+/**
+  Read number of bytes data in blocking mode.
+
+  If there is no enough data in socket, this function will wait.
+  This function will return if enough data is read, or socket error.
+**/
+static bool ReadBytes(int Socket, uint8_t *Buffer, uint32_t NumberOfBytes)
+{
+    int Result;
+    uint32_t NumberReceived;
+
+    NumberReceived = 0;
+    while (NumberReceived < NumberOfBytes) {
+        Result = recv(Socket, (char *)(Buffer + NumberReceived),
+                      NumberOfBytes - NumberReceived, 0);
+        if (Result == -1) {
+            printf("Receive error - 0x%x\n", errno);
+            return false;
+        }
+        if (Result == 0) {
+            return false;
+        }
+        NumberReceived += Result;
+    }
+    return true;
+}
+
+static bool ReadData32(int Socket, uint32_t *Data)
+{
+    bool Result;
+
+    Result = ReadBytes(Socket, (uint8_t *)Data, sizeof(uint32_t));
+    if (!Result) {
+        return Result;
+    }
+    *Data = ntohl(*Data);
+    return true;
+}
+
+/**
+  Read multiple bytes in blocking mode.
+
+  The length is presented as first 4 bytes in big endian.
+  The data follows the length.
+
+  If there is no enough data in socket, this function will wait.
+  This function will return if enough data is read, or socket error.
+**/
+static bool ReadMultipleBytes(int Socket, uint8_t *Buffer,
+                              uint32_t *BytesReceived, uint32_t MaxBufferLength)
+{
+    uint32_t Length;
+    bool Result;
+
+    Result = ReadData32(Socket, &Length);
+    if (!Result) {
+        return Result;
+    }
+    printf("Platform Port Receive Size: ");
+    Length = ntohl(Length);
+    DumpData((uint8_t *)&Length, sizeof(uint32_t));
+    Length = ntohl(Length);
+
+    *BytesReceived = Length;
+    if (*BytesReceived > MaxBufferLength) {
+        printf("Buffer too small (0x%x). Expected - 0x%x\n",
+               MaxBufferLength, *BytesReceived);
+        return false;
+    }
+    if (Length == 0) {
+        return true;
+    }
+    Result = ReadBytes (Socket, Buffer, Length);
+    if (!Result) {
+        return Result;
+    }
+    printf("Platform Port Receive Buffer:\n    ");
+    DumpData(Buffer, Length);
+    return true;
+}
+
+static bool ReceivePlatformData(int Socket, uint32_t *Command,
+                                uint8_t *ReceiveBuffer,
+                                uint32_t *BytesToReceive)
+{
+    bool Result;
+    uint32_t Response;
+    uint32_t TransportType;
+    uint32_t BytesReceived;
+
+    Result = ReadData32(Socket, &Response);
+    if (!Result) {
+        return Result;
+    }
+    *Command = Response;
+    printf("Platform Port Receive Command: ");
+    Response = ntohl(Response);
+    DumpData((uint8_t *)&Response, sizeof(uint32_t));
+
+    Result = ReadData32(Socket, &TransportType);
+    if (!Result) {
+        return Result;
+    }
+    printf("Platform Port Receive TransportType: ");
+    TransportType = ntohl(TransportType);
+    DumpData((uint8_t *)&TransportType, sizeof(uint32_t));
+    TransportType = ntohl(TransportType);
+    if (TransportType != mUseTransportLayer) {
+        printf("TransportType mismatch\n");
+        return false;
+    }
+
+    BytesReceived = 0;
+    Result = ReadMultipleBytes(Socket, ReceiveBuffer, &BytesReceived,
+                               (uint32_t)*BytesToReceive);
+    if (!Result) {
+        return Result;
+    }
+    *BytesToReceive = BytesReceived;
+
+    return Result;
+}
+
+/**
+  Write number of bytes data in blocking mode.
+
+  This function will return if data is written, or socket error.
+**/
+static bool WriteBytes(int Socket, uint8_t *Buffer, uint32_t NumberOfBytes)
+{
+    int Result;
+    uint32_t NumberSent;
+
+    NumberSent = 0;
+    while (NumberSent < NumberOfBytes) {
+        Result = send(Socket, (char *)(Buffer + NumberSent),
+                      NumberOfBytes - NumberSent, 0);
+        if (Result == -1) {
+            printf ("Send error - 0x%x\n", errno);
+            return false;
+        }
+        NumberSent += Result;
+    }
+    return true;
+}
+
+static bool WriteData32(int Socket, uint32_t Data)
+{
+    Data = htonl(Data);
+    return WriteBytes(Socket, (uint8_t *)&Data, sizeof(uint32_t));
+}
+
+/**
+  Write multiple bytes.
+
+  The length is presented as first 4 bytes in big endian.
+  The data follows the length.
+**/
+static bool WriteMultipleBytes(int Socket, uint8_t *Buffer,
+                               uint32_t BytesToSend)
+{
+    bool Result;
+
+    Result = WriteData32 (Socket, BytesToSend);
+    if (!Result) {
+        return Result;
+    }
+    printf("Platform Port Transmit Size: ");
+    BytesToSend = htonl(BytesToSend);
+    DumpData((uint8_t *)&BytesToSend, sizeof(uint32_t));
+    BytesToSend = htonl(BytesToSend);
+
+    Result = WriteBytes(Socket, Buffer, BytesToSend);
+    if (!Result) {
+        return Result;
+    }
+    printf("Platform Port Transmit Buffer:\n    ");
+    DumpData(Buffer, BytesToSend);
+
+    return true;
+}
+
+static bool SendPlatformData(int Socket, uint32_t Command, uint8_t *SendBuffer,
+                             uint32_t BytesToSend)
+{
+    bool Result;
+    uint32_t Request;
+    uint32_t TransportType;
+
+    Request = Command;
+    Result = WriteData32(Socket, Request);
+    if (!Result) {
+        return Result;
+    }
+    printf ("Platform Port Transmit Command: ");
+    Request = htonl(Request);
+    DumpData((uint8_t *)&Request, sizeof(uint32_t));
+
+    Result = WriteData32(Socket, mUseTransportLayer);
+    if (!Result) {
+        return Result;
+    }
+    printf("Platform Port Transmit TransportType: ");
+    TransportType = ntohl(mUseTransportLayer);
+    DumpData((uint8_t *)&TransportType, sizeof(uint32_t));
+
+    Result = WriteMultipleBytes(Socket, SendBuffer, BytesToSend);
+    if (!Result) {
+        return Result;
+    }
+
+    return true;
+}
+
+void spdm_sock_init(Error **errp)
+{
+    int result;
+    struct sockaddr_in ServerAddr;
+    uint16_t Port = 2323;
+
+    ClientSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+    if (ClientSocket == INVALID_SOCKET) {
+        error_setg(errp, "Openspdm: %s\n", strerror(errno));
+        return;
+    }
+
+    ServerAddr.sin_family = AF_INET;
+    memcpy(&ServerAddr.sin_addr.s_addr, &mIpAddress, sizeof(struct in_addr));
+    ServerAddr.sin_port = htons(Port);
+    memset(ServerAddr.sin_zero, 0, sizeof(ServerAddr.sin_zero));
+
+    result = connect(ClientSocket, (struct sockaddr *)&ServerAddr,
+                     sizeof(ServerAddr));
+    if (result == SOCKET_ERROR) {
+        error_setg(errp, "Openspdm: %s\n", strerror(errno));
+        closesocket(ClientSocket);
+        return;
+    }
+    printf("Openspdm: Connect success!\n");
+}
+
+bool pcie_doe_spdm_rsp(DOECap *doe_cap)
+{
+    void *req = pcie_doe_get_write_mbox_ptr(doe_cap);
+    uint32_t len = pcie_doe_get_obj_len(req);
+    uint32_t rsp_len = MAX_SPDM_MESSAGE_BUFFER_SIZE, Command;
+    bool result;
+
+    result = SendPlatformData(ClientSocket, SOCKET_SPDM_COMMAND_NORMAL,
+                              req, len * DWORD_BYTE);
+    if (!result) {
+        printf("SendPlatformData error\n");
+        return result;
+    }
+
+    result = ReceivePlatformData(ClientSocket, &Command,
+                                 (uint8_t *)doe_cap->read_mbox, &rsp_len);
+    if (!result) {
+        printf("ReceivePlatformData error\n");
+        return result;
+    }
+
+    assert(Command != 0);
+    doe_cap->read_mbox_len += DIV_ROUND_UP(rsp_len, DWORD_BYTE);
+
+    return true;
+}
+
+void spdm_sock_fini(void)
+{
+    bool result;
+
+    result = SendPlatformData(ClientSocket, SOCKET_SPDM_COMMAND_SHUTDOWN,
+                              NULL, 0);
+    if (!result) {
+        printf("SendPlatformData error\n");
+        return;
+    }
+    printf("Openspdm: Shutdown!\n");
+}
diff --git a/hw/pci/meson.build b/hw/pci/meson.build
index 115e502..e3be112 100644
--- a/hw/pci/meson.build
+++ b/hw/pci/meson.build
@@ -13,6 +13,7 @@ pci_ss.add(files(
 # CONFIG_PCI_EXPRESS=n.
 pci_ss.add(files('pcie.c', 'pcie_aer.c'))
 pci_ss.add(files('pcie_doe.c'))
+pci_ss.add(when: 'CONFIG_PCIE_SPDM', if_true: files('SpdmEmuCommand.c'))
 softmmu_ss.add(when: 'CONFIG_PCI_EXPRESS', if_true: files('pcie_port.c', 'pcie_host.c'))
 softmmu_ss.add_all(when: 'CONFIG_PCI', if_true: pci_ss)
 
diff --git a/include/hw/cxl/cxl_device.h b/include/hw/cxl/cxl_device.h
index de006ff..a112620 100644
--- a/include/hw/cxl/cxl_device.h
+++ b/include/hw/cxl/cxl_device.h
@@ -240,6 +240,8 @@ typedef struct cxl_type3_dev {
     /* DOE */
     DOECap doe_comp;
     DOECap doe_cdat;
+    bool use_spdm;
+    DOECap doe_spdm;
 } CXLType3Dev;
 
 #ifndef TYPE_CXL_TYPE3_DEV
diff --git a/include/hw/pci/SpdmEmuCommand.h b/include/hw/pci/SpdmEmuCommand.h
new file mode 100644
index 0000000..39e7e9a
--- /dev/null
+++ b/include/hw/pci/SpdmEmuCommand.h
@@ -0,0 +1,21 @@
+#include "qemu/osdep.h"
+#include "hw/pci/pcie_doe.h"
+
+#define SOCKET_TRANSPORT_TYPE_MCTP     0x01
+#define SOCKET_TRANSPORT_TYPE_PCI_DOE  0x02
+
+#define SOCKET_SPDM_COMMAND_NORMAL                0x0001
+#define SOCKET_SPDM_COMMAND_OOB_ENCAP_KEY_UPDATE  0x8001
+#define SOCKET_SPDM_COMMAND_CONTINUE              0xFFFD
+#define SOCKET_SPDM_COMMAND_SHUTDOWN              0xFFFE
+#define SOCKET_SPDM_COMMAND_UNKOWN                0xFFFF
+#define SOCKET_SPDM_COMMAND_TEST                  0xDEAD
+
+#define INVALID_SOCKET (-1)
+#define SOCKET_ERROR (-1)
+
+#define MAX_SPDM_MESSAGE_BUFFER_SIZE      0x1200
+
+void spdm_sock_init(Error **errp);
+bool pcie_doe_spdm_rsp(DOECap *doe_cap);
+void spdm_sock_fini(void);
diff --git a/include/hw/pci/pcie_doe.h b/include/hw/pci/pcie_doe.h
index e551f49..af4be56 100644
--- a/include/hw/pci/pcie_doe.h
+++ b/include/hw/pci/pcie_doe.h
@@ -47,6 +47,8 @@ REG32(PCI_DOE_CAP_STATUS, 0)
 
 /* PCI-SIG defined Data Object Types - Table 7-x2 */
 #define PCI_SIG_DOE_DISCOVERY       0x00
+#define PCI_SIG_DOE_CMA             0x01
+#define PCI_SIG_DOE_SECURED_CMA     0x02
 
 #define PCI_DOE_DW_SIZE_MAX         (1 << 18)
 #define PCI_DOE_PROTOCOL_NUM_MAX    256
-- 
1.8.3.1



^ permalink raw reply related	[flat|nested] 3+ messages in thread

* Re: [PATCH v1 QEMU CXL modifications for openspdm 0/1] Testing PCIe DOE in QEMU CXL/PCIe Device using openspdm
  2021-06-26  0:02 [PATCH v1 QEMU CXL modifications for openspdm 0/1] Testing PCIe DOE in QEMU CXL/PCIe Device using openspdm Chris Browy
  2021-06-26  0:05 ` [PATCH v1 QEMU CXL modifications for openspdm 1/1] pcie/spdm: PCIe CMA implementation Chris Browy
@ 2021-06-29 12:25 ` Jonathan Cameron
  1 sibling, 0 replies; 3+ messages in thread
From: Jonathan Cameron @ 2021-06-29 12:25 UTC (permalink / raw)
  To: Chris Browy
  Cc: ben.widawsky, jgroves, david, qemu-devel, vishal.l.verma, mst,
	armbru, linux-cxl, f4bug, hchkuo, tyshao, imammedo,
	dan.j.williams, ira.weiny

On Fri, 25 Jun 2021 20:02:03 -0400
Chris Browy <cbrowy@avery-design.com> wrote:

> This patch series provides an implementation of the the Data Object Exchange
> (DOE) for Component Measurement and Authentication (CMA) of the Security
> Protocol and Data Model (SPDM). 
> 
> This patch is based on 
> [1] [PATCH v1 openspdm on QEMU CXL/PCIe Device 0/2] Testing PCIe DOE in QEMU CXL/PCIe Device using openspdm
> https://lore.kernel.org/qemu-devel/1624665280-3595-1-git-send-email-cbrowy@avery-design.com/T/#u
> [2] QEMU DOE: [PATCH v6 cxl2.0-v6-doe 0/6] QEMU PCIe DOE for PCIe 4.0/5.0 and CXL 2.0
> https://lore.kernel.org/qemu-devel/1623329999-15662-1-git-send-email-cbrowy@avery-design.com/
> 
> Openspdm is an emulator composed of an SPDM requester and an SPDM responder.
> The default SpdmEmu usage have the requester and responder communicate with
> each other via a TCP socket. 
> 
> However to test PCIe DOE support in QEMU PCIe/CXL device directly, the openspdm
> requester is modified to use pwrite/pread for MMIO access to the
> QEMU CXL Device DOE capability (hw/mem/cxl_type3.c).  The openspdm
> requester is run as user application targeting the CXL Device.
> 
> Follow the readme.md under [1] to build this enhanced version of openspdm.
> 
> The QEMU CXL device is extended usig the "-spdm=<bool>" option to turn on/off
> the DOE/CMA capability. Once the option is turned on (-spdm=true) the CXL
> device can communicate with Openspdm's responder to get the data object of
> SPDM/secured SPDM.  QEMU and SPDM responder communicate over client-server
> method.

Hi Chris / Hchkuo

Thanks. I've gotten it up on running on my normal ARM64 emulated
on x86 platform. Very useful indeed!

Next step for me is to get a kernel implementation up and running.
I have the basic version negotiation etc running already, but the
cert handling will take a little longer I think.

For QEMU I'm thinking that it will be 'interesting' to upstream emulation
based on the current strategy of opening a socket to the openspdm test
app.  Definitely works for now though and lets us get on with the
OS side of things :)  If nothing else the spdm build approach of
having to checkout other libraries inside the spdm tree and it linking
statically against them (I think) is not exactly standard practice for
userspace software.

One note below.

Jonathan

> 
> Build the QEMU with patch series applied to [2].
> 
> Now run the system as follows:
> 
> 1. Start Responder process:
>     ./openspdm/Build/RELEASE_GCC/X64/SpdmResponderEmu --trans PCI_DOE

If I run it like this, it fails to find the certs.
cd openspdm/Build/RELEASE_GCC/X64/
./SpdmResponderEmu --trans PCI_DOE
finds them all.  Same is need inside QEMU 'guest'.

> 
> 2. Start QEMU process:
>     qemu-system-x86_64 \
>     -nic user,hostfwd=tcp::2222-:22 \
> 	-machine type=pc-q35-4.0 \
> 	-smp 8,sockets=2,cores=2,threads=2 \
> 	-m 4G \
> 	-boot order=d \
> 	-k 'en-us' \
> 	-vga virtio \
> 	-drive file=<path to qcow>,format=qcow2 \
> 	-drive if=pflash,format=raw,readonly=on,file=<path to OVMF_CODE.fd> \
> 	-drive if=pflash,format=raw,file=<path to OVMF_VARS.fd> \
> 	-object memory-backend-file,id=cxl-mem2,share=on,mem-path=/tmp/cxl-mem2,size=1K \
> 	-object memory-backend-file,id=cxl-mem1,share=on,mem-path=/tmp/cxl-mem,size=512M \
> 	-device pxb-cxl,id=cxl.0,bus=pcie.0,bus_nr=52,uid=0,len-window-base=1,window-base[0]=0x4c0000000,memdev[0]=cxl-mem1 \
> 	-device cxl-rp,id=rp0,bus=cxl.0,addr=0.0,chassis=0,slot=0 \
> 	-device cxl-type3,bus=rp0,memdev=cxl-mem1,id=cxl-pmem0,size=256M,lsa=cxl-mem2,spdm=true
> 
> 3. Next copy the openspdm build into QEMU qcow
> 
>     scp -rP2222 openspdm qemu@localhost:.
> 
> 4. Next ssh to QEMU emulator and execute the requester user application
> 
>     sudo ./openspdm/Build/RELEASE_GCC/X64/SpdmRequesterEmu --trans PCI_DOE -s 35:00.0
> 
> hchkuo (1):
>   pcie/spdm: PCIe CMA implementation
> 
>  hw/mem/cxl_type3.c              |  31 +++-
>  hw/pci/Kconfig                  |   4 +
>  hw/pci/SpdmEmuCommand.c         | 319 ++++++++++++++++++++++++++++++++++++++++
>  hw/pci/meson.build              |   1 +
>  include/hw/cxl/cxl_device.h     |   2 +
>  include/hw/pci/SpdmEmuCommand.h |  21 +++
>  include/hw/pci/pcie_doe.h       |   2 +
>  7 files changed, 377 insertions(+), 3 deletions(-)
>  create mode 100644 hw/pci/SpdmEmuCommand.c
>  create mode 100644 include/hw/pci/SpdmEmuCommand.h
> 



^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2021-06-29 12:27 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-06-26  0:02 [PATCH v1 QEMU CXL modifications for openspdm 0/1] Testing PCIe DOE in QEMU CXL/PCIe Device using openspdm Chris Browy
2021-06-26  0:05 ` [PATCH v1 QEMU CXL modifications for openspdm 1/1] pcie/spdm: PCIe CMA implementation Chris Browy
2021-06-29 12:25 ` [PATCH v1 QEMU CXL modifications for openspdm 0/1] Testing PCIe DOE in QEMU CXL/PCIe Device using openspdm Jonathan Cameron

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).