diff options
-rw-r--r-- | include/pci_caps/px.h | 20 | ||||
-rw-r--r-- | lib/pci_caps.c | 32 | ||||
-rw-r--r-- | test/py/libvfio_user.py | 3 | ||||
-rw-r--r-- | test/py/test_pci_caps.py | 27 |
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: # |