aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/pci_caps/px.h20
-rw-r--r--lib/pci_caps.c32
-rw-r--r--test/py/libvfio_user.py3
-rw-r--r--test/py/test_pci_caps.py27
4 files changed, 78 insertions, 4 deletions
diff --git a/include/pci_caps/px.h b/include/pci_caps/px.h
index 86cd1b3..e2eb36c 100644
--- a/include/pci_caps/px.h
+++ b/include/pci_caps/px.h
@@ -157,10 +157,22 @@ struct pxdcap2 {
} __attribute__((packed));
_Static_assert(sizeof(struct pxdcap2) == 0x4, "bad PXDCAP2 size");
-struct pxdc2 {
- uint16_t stuff:16;
+union pxdc2 {
+ uint16_t raw;
+ struct {
+ uint32_t comp_timeout:4;
+ uint32_t comp_timout_dis:1;
+ uint32_t ari:1;
+ uint32_t atomic_req:1;
+ uint32_t atomic_egress_block:1;
+ uint32_t ido_req_en:1;
+ uint32_t ido_cmp_en:1;
+ uint32_t ltr_en:1;
+ uint32_t obff_en:2;
+ uint32_t end_end_tlp_prefix_block:1;
+ } __attribute__((packed));
} __attribute__((packed));
-_Static_assert(sizeof(struct pxdc2) == 0x2, "bad PXDC2 size");
+_Static_assert(sizeof(union pxdc2) == 0x2, "bad PXDC2 size");
struct pxds2 {
uint16_t stuff:16;
@@ -245,7 +257,7 @@ struct pxcap {
/* Device Capabilities 2 */
struct pxdcap2 pxdcap2;
/* Device Control 2 */
- struct pxdc2 pxdc2;
+ union pxdc2 pxdc2;
/* Device Status 2 */
struct pxds2 pxds2;
/* Link Capabilities 2 */
diff --git a/lib/pci_caps.c b/lib/pci_caps.c
index f6a3abc..d7d312f 100644
--- a/lib/pci_caps.c
+++ b/lib/pci_caps.c
@@ -293,12 +293,44 @@ handle_px_pxdc_write(vfu_ctx_t *vfu_ctx, struct pxcap *px,
}
static int
+handle_px_pxdc2_write(vfu_ctx_t *vfu_ctx, struct pxcap *px,
+ const union pxdc2 *const p)
+{
+ assert(px != NULL);
+ assert(p != NULL);
+
+ if (p->raw != px->pxdc2.raw) {
+ vfu_log(vfu_ctx, LOG_DEBUG, "Device Control 2 set to %#x", p->raw);
+ }
+ px->pxdc2 = *p;
+ return 0;
+}
+
+static int
+handle_px_pxlc2_write(vfu_ctx_t *vfu_ctx, struct pxcap *px,
+ const struct pxlc2 *const p)
+{
+ assert(px != NULL);
+ assert(p != NULL);
+
+ if (p->stuff != px->pxlc2.stuff) {
+ vfu_log(vfu_ctx, LOG_DEBUG, "Link Control 2 set to %#x", p->stuff);
+ }
+ px->pxlc2 = *p;
+ return 0;
+}
+
+static int
handle_px_write_2_bytes(vfu_ctx_t *vfu_ctx, struct pxcap *px, char *buf,
loff_t off)
{
switch (off) {
case offsetof(struct pxcap, pxdc):
return handle_px_pxdc_write(vfu_ctx, px, (union pxdc *)buf);
+ case offsetof(struct pxcap, pxdc2):
+ return handle_px_pxdc2_write(vfu_ctx, px, (union pxdc2 *)buf);
+ case offsetof(struct pxcap, pxlc2):
+ return handle_px_pxlc2_write(vfu_ctx, px, (struct pxlc2 *)buf);
}
return ERROR_INT(EINVAL);
}
diff --git a/test/py/libvfio_user.py b/test/py/libvfio_user.py
index f0fc568..70986fa 100644
--- a/test/py/libvfio_user.py
+++ b/test/py/libvfio_user.py
@@ -61,6 +61,9 @@ PCI_CAP_ID_PM = 0x1
PCI_CAP_ID_VNDR = 0x9
PCI_CAP_ID_EXP = 0x10
+PCI_EXP_DEVCTL2 = 40
+PCI_EXP_LNKCTL2 = 48
+
PCI_EXT_CAP_ID_DSN = 0x03
PCI_EXT_CAP_ID_VNDR = 0x0b
diff --git a/test/py/test_pci_caps.py b/test/py/test_pci_caps.py
index be1914d..5af54e3 100644
--- a/test/py/test_pci_caps.py
+++ b/test/py/test_pci_caps.py
@@ -326,5 +326,32 @@ def test_pci_cap_write_msix():
# FIXME
pass
+
+def test_pci_cap_write_pxdc2():
+ sock = connect_client(ctx)
+ offset = vfu_pci_find_capability(ctx, False, PCI_CAP_ID_EXP) + PCI_EXP_DEVCTL2
+ data = b'\xde\xad'
+ write_region(ctx, sock, VFU_PCI_DEV_CFG_REGION_IDX, offset=offset,
+ count=len(data), data=data)
+ payload = read_region(ctx, sock, VFU_PCI_DEV_CFG_REGION_IDX, offset=offset,
+ count=len(data))
+ assert payload == data
+ disconnect_client(ctx, sock)
+
+
+def test_pci_cap_write_pxlc2():
+ sock = connect_client(ctx)
+ offset = vfu_pci_find_capability(ctx, False, PCI_CAP_ID_EXP) + PCI_EXP_LNKCTL2
+ data = b'\xbe\xef'
+ write_region(ctx, sock, VFU_PCI_DEV_CFG_REGION_IDX, offset=offset,
+ count=len(data), data=data)
+ payload = read_region(ctx, sock, VFU_PCI_DEV_CFG_REGION_IDX, offset=offset,
+ count=len(data))
+ assert payload == data
+ disconnect_client(ctx, sock)
+
+
def test_pci_cap_cleanup():
vfu_destroy_ctx(ctx)
+
+# ex: set tabstop=4 shiftwidth=4 softtabstop=4 expandtab: #