aboutsummaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
authorThanos Makatos <thanos.makatos@nutanix.com>2022-02-04 13:51:59 +0000
committerGitHub <noreply@github.com>2022-02-04 13:51:59 +0000
commit2d1d87016133b6c2f38e4f6a5fca6be5b820653c (patch)
treef316e6a045a8c08d9d5ab31f29e96b7034d73ea7 /test
parent314ed91fd991756bef2c87ecdf7feff4016c1d40 (diff)
downloadlibvfio-user-2d1d87016133b6c2f38e4f6a5fca6be5b820653c.zip
libvfio-user-2d1d87016133b6c2f38e4f6a5fca6be5b820653c.tar.gz
libvfio-user-2d1d87016133b6c2f38e4f6a5fca6be5b820653c.tar.bz2
ignore writes to RO MSI-X registers (#642)
Signed-off-by: Thanos Makatos <thanos.makatos@nutanix.com> Reviewed-by: John Levon <john.levon@nutanix.com>
Diffstat (limited to 'test')
-rw-r--r--test/py/libvfio_user.py9
-rw-r--r--test/py/test_pci_caps.py67
2 files changed, 74 insertions, 2 deletions
diff --git a/test/py/libvfio_user.py b/test/py/libvfio_user.py
index 4b4a96a..6d71efd 100644
--- a/test/py/libvfio_user.py
+++ b/test/py/libvfio_user.py
@@ -63,6 +63,7 @@ PCI_CAP_LIST_NEXT = 1
PCI_CAP_ID_PM = 0x1
PCI_CAP_ID_VNDR = 0x9
+PCI_CAP_ID_MSIX = 0x11
PCI_CAP_ID_EXP = 0x10
PCI_EXP_DEVCTL2 = 40
@@ -75,6 +76,14 @@ PCI_EXT_CAP_DSN_SIZEOF = 12
PCI_EXT_CAP_VNDR_HDR_SIZEOF = 8
+# MSI-X registers
+PCI_MSIX_FLAGS = 2 # Message Control
+PCI_MSIX_TABLE = 4 # Table offset
+PCI_MSIX_FLAGS_MASKALL = 0x4000 # Mask all vectors for this function
+PCI_MSIX_FLAGS_ENABLE = 0x8000 # MSI-X enable
+PCI_CAP_MSIX_SIZEOF = 12 # size of MSIX registers
+
+
# from linux/vfio.h
VFIO_DEVICE_FLAGS_RESET = (1 << 0)
diff --git a/test/py/test_pci_caps.py b/test/py/test_pci_caps.py
index effd6d3..b83c06c 100644
--- a/test/py/test_pci_caps.py
+++ b/test/py/test_pci_caps.py
@@ -349,9 +349,72 @@ def test_pci_cap_write_px(mock_quiesce, mock_reset):
expect=errno.EINVAL)
+def to_bytes_le(n, length=1):
+ return n.to_bytes(length, 'little')
+
+
def test_pci_cap_write_msix():
- # FIXME
- pass
+ setup_pci_dev(realize=True)
+ sock = connect_client(ctx)
+
+ flags = PCI_MSIX_FLAGS_MASKALL | PCI_MSIX_FLAGS_ENABLE
+ pos = vfu_pci_add_capability(ctx, pos=0, flags=0,
+ data=struct.pack("ccHII",
+ to_byte(PCI_CAP_ID_MSIX),
+ b'\0', 0, 0, 0))
+ assert pos == cap_offsets[0]
+
+ offset = vfu_pci_find_capability(ctx, False, PCI_CAP_ID_MSIX)
+
+ # write exactly to Message Control: mask all vectors and enable MSI-X
+ data = b'\xff\xff'
+ write_region(ctx, sock, VFU_PCI_DEV_CFG_REGION_IDX,
+ offset=offset + PCI_MSIX_FLAGS,
+ count=len(data), data=data)
+ data = b'\xff\xff' + to_bytes_le(flags, 2)
+ payload = read_region(ctx, sock, VFU_PCI_DEV_CFG_REGION_IDX, offset=offset,
+ count=len(data))
+ expected = to_bytes_le(PCI_CAP_ID_MSIX) + b'\x00' + \
+ to_bytes_le(PCI_MSIX_FLAGS_MASKALL | PCI_MSIX_FLAGS_ENABLE, 2)
+ assert expected == payload
+
+ # reset
+ data = b'\x00\x00'
+ write_region(ctx, sock, VFU_PCI_DEV_CFG_REGION_IDX,
+ offset=offset + PCI_MSIX_FLAGS,
+ count=len(data), data=data)
+ expected = to_bytes_le(PCI_CAP_ID_MSIX) + b'\x00\x00'
+ payload = read_region(ctx, sock, VFU_PCI_DEV_CFG_REGION_IDX, offset=offset,
+ count=len(expected))
+ assert expected == payload
+
+ # write 2 bytes to Message Control + 1: mask all vectors and enable MSI-X
+ # This looks bizarre, but some versions of QEMU do this.
+ data = to_bytes_le(flags >> 8) + b'\xff'
+ write_region(ctx, sock, VFU_PCI_DEV_CFG_REGION_IDX,
+ offset=offset + PCI_MSIX_FLAGS + 1,
+ count=len(data), data=data)
+ # read back entire MSI-X
+ expected = to_bytes_le(PCI_CAP_ID_MSIX) + b'\x00' + \
+ to_bytes_le(flags, 2) + b'\x00\x00\x00\x00' + b'\x00\x00\x00\x00'
+ payload = read_region(ctx, sock, VFU_PCI_DEV_CFG_REGION_IDX, offset=offset,
+ count=PCI_CAP_MSIX_SIZEOF)
+ assert expected == payload
+
+ # reset with MSI-X enabled
+ data = to_bytes_le(PCI_MSIX_FLAGS_ENABLE, 2)
+ write_region(ctx, sock, VFU_PCI_DEV_CFG_REGION_IDX,
+ offset=offset + PCI_MSIX_FLAGS,
+ count=len(data), data=data)
+
+ # write 1 byte past Message Control, MSI-X should still be enabled
+ data = b'\x00'
+ write_region(ctx, sock, VFU_PCI_DEV_CFG_REGION_IDX,
+ offset=offset + PCI_MSIX_TABLE,
+ count=len(data), data=data)
+ payload = read_region(ctx, sock, VFU_PCI_DEV_CFG_REGION_IDX,
+ offset=offset + PCI_MSIX_FLAGS, count=2)
+ assert payload == to_bytes_le(PCI_MSIX_FLAGS_ENABLE, 2)
def test_pci_cap_write_pxdc2():