Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 39 additions & 2 deletions lib/pci.c
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,44 @@ handle_erom_write(vfu_ctx_t *ctx, vfu_pci_config_space_t *pci,
return 0;
}

static int
handle_status_write(vfu_ctx_t *ctx UNUSED,
vfu_pci_config_space_t *pci,
const char *buf)
{
vfu_pci_hdr_sts_t w;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit, rename to device_status or something more descriptive?


assert(pci != NULL);
assert(buf != NULL);

w.raw = *(uint16_t *)buf;

if (w.dpd) {
pci->hdr.sts.dpd = 0;
}

if (w.sta) {
pci->hdr.sts.sta = 0;
}

if (w.rta) {
pci->hdr.sts.rta = 0;
}

if (w.rma) {
pci->hdr.sts.rma = 0;
}

if (w.sse) {
pci->hdr.sts.sse = 0;
}

if (w.dpe) {
pci->hdr.sts.dpe = 0;
}

return 0;
}
static int
pci_hdr_write(vfu_ctx_t *vfu_ctx, const char *buf, loff_t offset)
{
Expand All @@ -267,8 +305,7 @@ pci_hdr_write(vfu_ctx_t *vfu_ctx, const char *buf, loff_t offset)
ret = handle_command_write(vfu_ctx, cfg_space, buf);
break;
case PCI_STATUS:
/* FIXME ignoring write completely is wrong as some bits are RW1C */
vfu_log(vfu_ctx, LOG_INFO, "write to status ignored");
ret = handle_status_write(vfu_ctx, cfg_space, buf);
break;
/*
* According to the PCI spec, writing to read-only registers must be
Expand Down
1 change: 1 addition & 0 deletions test/py/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ python_tests = [
'test_sgl_read_write.py',
'test_vfu_create_ctx.py',
'test_vfu_realize_ctx.py',
'test_pci_status.py',
]

if get_option('shadow-ioeventfd')
Expand Down
112 changes: 112 additions & 0 deletions test/py/test_pci_status.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
#
# Copyright (c) 2026 Nutanix Inc.
Comment thread
zp78256pxd-ux marked this conversation as resolved.
Outdated
#

from libvfio_user import *
import struct

ctx = None

PCI_STATUS = 0x06
Comment thread
zp78256pxd-ux marked this conversation as resolved.
Outdated
PCI_STATUS_CAP_LIST = 0x0010
PCI_STATUS_DETECTED_PARITY = 0x8000


def setup_function(function):
global ctx

ctx = vfu_create_ctx(flags=LIBVFIO_USER_FLAG_ATTACH_NB)
assert ctx is not None

ret = vfu_setup_device_reset_cb(ctx)
assert ret == 0

vfu_setup_device_quiesce_cb(ctx)


def teardown_function(function):
vfu_destroy_ctx(ctx)


def read_status(sock):
payload = read_region(
ctx,
sock,
VFU_PCI_DEV_CFG_REGION_IDX,
offset=PCI_STATUS,
count=2
)

return struct.unpack("<H", payload)[0]


def test_pci_status_rw1c():
Comment thread
zp78256pxd-ux marked this conversation as resolved.

ret = vfu_pci_init(ctx, pci_type=VFU_PCI_TYPE_CONVENTIONAL)
assert ret == 0

ret = vfu_setup_region(
ctx,
index=VFU_PCI_DEV_CFG_REGION_IDX,
size=PCI_CFG_SPACE_SIZE,
flags=VFU_REGION_FLAG_RW
)
assert ret == 0

ret = vfu_realize_ctx(ctx)
assert ret == 0

client = connect_client(ctx)

initial = (
PCI_STATUS_DETECTED_PARITY |
PCI_STATUS_CAP_LIST
)

write_pci_cfg_space(
ctx,
struct.pack("<H", initial),
2,
PCI_STATUS
)

assert read_status(client.sock) == initial

write_region(
ctx,
client.sock,
VFU_PCI_DEV_CFG_REGION_IDX,
offset=PCI_STATUS,
count=2,
data=struct.pack(
"<H",
PCI_STATUS_DETECTED_PARITY
)
)

assert read_status(client.sock) == PCI_STATUS_CAP_LIST

write_pci_cfg_space(
ctx,
struct.pack(
"<H",
PCI_STATUS_DETECTED_PARITY
),
2,
PCI_STATUS
)

write_region(
ctx,
client.sock,
VFU_PCI_DEV_CFG_REGION_IDX,
offset=PCI_STATUS,
count=2,
data=struct.pack("<H", 0)
)

assert (
read_status(client.sock)
==
PCI_STATUS_DETECTED_PARITY
)
Loading