Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
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);

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
12 changes: 12 additions & 0 deletions samples/lspci.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,15 @@

#include "libvfio-user.h"

static int
lspci_reset_cb(vfu_ctx_t *vfu_ctx, vfu_reset_type_t type)
{
(void)vfu_ctx;
(void)type;

return 0;
}

int main(void)
{
int i, j;
Expand All @@ -61,6 +70,9 @@ int main(void)
if (vfu_ctx == NULL) {
err(EXIT_FAILURE, "failed to create libvfio-user context");
}
if (vfu_setup_device_reset_cb(vfu_ctx, lspci_reset_cb) < 0) {
err(EXIT_FAILURE, "vfu_setup_device_reset_cb() failed");
}
if (vfu_pci_init(vfu_ctx, VFU_PCI_TYPE_EXPRESS,
PCI_HEADER_TYPE_NORMAL, 0) < 0) {
err(EXIT_FAILURE, "vfu_pci_init() failed");
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
Loading