Skip to content
Merged
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
4 changes: 4 additions & 0 deletions include/libvfio-user.h
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,10 @@ vfu_create_ctx(vfu_trans_t trans, const char *path,
* mandatory to be called before vfu_attach_ctx().
* @vfu_ctx: the libvfio-user context
*
* Devices advertising PCIe Function Level Reset capability must
* register a reset callback via vfu_setup_device_reset_cb()
* before realization, otherwise realization fails with EINVAL.
*
* @returns: 0 on success, -1 on error. Sets errno.
*/
int
Expand Down
11 changes: 11 additions & 0 deletions lib/libvfio-user.c
Original file line number Diff line number Diff line change
Expand Up @@ -1798,7 +1798,18 @@ vfu_realize_ctx(vfu_ctx_t *vfu_ctx)
if (vfu_ctx->pci.nr_caps != 0) {
vfu_ctx->pci.config_space->hdr.sts.cl = 0x1;
}
if (vfu_ctx->pci_cap_exp_off >= 0) {
struct pxcap *px;

px = (struct pxcap *)pci_config_space_ptr(vfu_ctx,
vfu_ctx->pci_cap_exp_off);

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.

identation


if (px->pxdcap.flrc && vfu_ctx->reset == NULL) {
vfu_log(vfu_ctx, LOG_ERR,
"FLR capability requires a reset callback");
return ERROR_INT(EINVAL);
}
}
vfu_ctx->realized = true;

return 0;
Expand Down
23 changes: 23 additions & 0 deletions test/py/test_pci_caps.py
Original file line number Diff line number Diff line change
Expand Up @@ -342,6 +342,29 @@ def test_pci_cap_write_px(mock_quiesce, mock_reset):
expect=errno.EINVAL)


@patch('libvfio_user.quiesce_cb')
def test_pci_cap_write_px_no_reset_cb(mock_quiesce):
"""
FLR must fail if no reset callback exists.
"""

global ctx

# recreate context without reset callback
vfu_destroy_ctx(ctx)

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

vfu_setup_device_quiesce_cb(ctx)

setup_pci_dev(realize=False)
setup_flrc(ctx)
ret = vfu_realize_ctx(ctx)
assert ret == -1
assert c.get_errno() == errno.EINVAL


def test_pci_cap_write_msi():
setup_pci_dev(realize=True)
client = connect_client(ctx)
Expand Down