diff options
author | John Levon <john.levon@nutanix.com> | 2021-01-05 15:18:42 +0000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-01-05 15:18:42 +0000 |
commit | 70524c550322948765415d9b0eb29ac766e32e79 (patch) | |
tree | 02ad60182191238de12f7df4121f137018a29840 /test | |
parent | 1fa90d5abecd896362e551b2bd2ec987d8f60a6b (diff) | |
download | libvfio-user-70524c550322948765415d9b0eb29ac766e32e79.zip libvfio-user-70524c550322948765415d9b0eb29ac766e32e79.tar.gz libvfio-user-70524c550322948765415d9b0eb29ac766e32e79.tar.bz2 |
re-work capability-locating API (#199)
Explicitly mimic the Linux kernel API: the searching functions return an offset
into configuration space. Just like a driver, libvfio-user devices can then
look into config space via vfu_pci_get_config_space() to read the capability as
needed. In general, the driver itself will know exactly what the size and shape
of the capability is, so this seems like a low-friction, and familiar to driver
writers, API.
Signed-off-by: John Levon <john.levon@nutanix.com>
Reviewed-by: Thanos Makatos <thanos.makatos@nutanix.com>
Diffstat (limited to 'test')
-rw-r--r-- | test/unit-tests.c | 75 |
1 files changed, 59 insertions, 16 deletions
diff --git a/test/unit-tests.c b/test/unit-tests.c index a304e02..6fb89a4 100644 --- a/test/unit-tests.c +++ b/test/unit-tests.c @@ -534,7 +534,12 @@ static void test_pci_caps(void **state __attribute__((unused))) { vfu_pci_config_space_t config_space; - vfu_ctx_t vfu_ctx = { .pci.config_space = &config_space }; + vfu_reg_info_t reg_info[VFU_PCI_DEV_NUM_REGIONS] = { + [VFU_PCI_DEV_CFG_REGION_IDX] = { .size = PCI_CFG_SPACE_SIZE }, + }; + vfu_ctx_t vfu_ctx = { .pci.config_space = &config_space, + .reg_info = reg_info, + }; vfu_cap_t pm = {.pm = {.hdr.id = PCI_CAP_ID_PM, .pmcs.raw = 0xabcd }}; vfu_cap_t *vsc[2] = { alloca(sizeof(struct vsc) + 5), @@ -544,6 +549,7 @@ test_pci_caps(void **state __attribute__((unused))) struct caps *caps; int err; struct pmcap pmcap = { .pmcs.raw = 0xef01 }; + size_t offset; off_t off; vsc[0]->vsc.hdr.id = PCI_CAP_ID_VNDR; @@ -558,24 +564,61 @@ test_pci_caps(void **state __attribute__((unused))) assert_non_null(caps); /* check that capability list is placed correctly */ - assert_int_equal(PCI_CAP_ID_PM, - config_space.raw[PCI_STD_HEADER_SIZEOF + PCI_CAP_LIST_ID]); + + offset = vfu_pci_find_capability(&vfu_ctx, false, PCI_CAP_ID_PM); + assert_int_equal(PCI_STD_HEADER_SIZEOF, offset); + assert_int_equal(PCI_CAP_ID_PM, config_space.raw[offset]); assert_int_equal(PCI_STD_HEADER_SIZEOF + PCI_PM_SIZEOF, - config_space.raw[PCI_STD_HEADER_SIZEOF + PCI_CAP_LIST_NEXT]); - assert_int_equal(PCI_CAP_ID_VNDR, - config_space.raw[PCI_STD_HEADER_SIZEOF + PCI_PM_SIZEOF + PCI_CAP_LIST_ID]); + config_space.raw[offset + PCI_CAP_LIST_NEXT]); + + offset = vfu_pci_find_next_capability(&vfu_ctx, false, offset, + PCI_CAP_ID_PM); + assert_int_equal(0, offset); + + offset = vfu_pci_find_capability(&vfu_ctx, false, PCI_CAP_ID_VNDR); + assert_int_equal(PCI_STD_HEADER_SIZEOF + PCI_PM_SIZEOF, offset); + assert_int_equal(PCI_CAP_ID_VNDR, config_space.raw[offset]); + + offset = vfu_pci_find_next_capability(&vfu_ctx, false, offset, + PCI_CAP_ID_PM); + assert_int_equal(0, offset); + + offset = vfu_pci_find_next_capability(&vfu_ctx, false, 0, PCI_CAP_ID_VNDR); + assert_int_equal(PCI_STD_HEADER_SIZEOF + PCI_PM_SIZEOF, offset); + assert_int_equal(PCI_CAP_ID_VNDR, config_space.raw[offset]); assert_int_equal(PCI_STD_HEADER_SIZEOF + PCI_PM_SIZEOF + vsc[0]->vsc.size, - config_space.raw[PCI_STD_HEADER_SIZEOF + PCI_PM_SIZEOF + PCI_CAP_LIST_NEXT]); - assert_int_equal(8, - config_space.raw[PCI_STD_HEADER_SIZEOF + PCI_PM_SIZEOF + PCI_CAP_LIST_NEXT + 1]); - assert_int_equal(PCI_CAP_ID_VNDR, - config_space.raw[PCI_STD_HEADER_SIZEOF + PCI_PM_SIZEOF + vsc[0]->vsc.size]); - assert_int_equal(0, - config_space.raw[PCI_STD_HEADER_SIZEOF + PCI_PM_SIZEOF + vsc[0]->vsc.size + PCI_CAP_LIST_NEXT]); - assert_int_equal(vsc[1]->vsc.size, - config_space.raw[PCI_STD_HEADER_SIZEOF + PCI_PM_SIZEOF + vsc[0]->vsc.size + PCI_CAP_LIST_NEXT + 1]); + config_space.raw[offset + PCI_CAP_LIST_NEXT]); + + offset = vfu_pci_find_next_capability(&vfu_ctx, false, offset, + PCI_CAP_ID_VNDR); + assert_int_equal(PCI_STD_HEADER_SIZEOF + PCI_PM_SIZEOF + vsc[0]->vsc.size, + offset); + assert_int_equal(PCI_CAP_ID_VNDR, config_space.raw[offset]); + assert_int_equal(0, config_space.raw[offset + PCI_CAP_LIST_NEXT]); + + offset = vfu_pci_find_next_capability(&vfu_ctx, false, offset, + PCI_CAP_ID_VNDR); + assert_int_equal(0, offset); + + /* check for invalid offsets */ + offset = vfu_pci_find_next_capability(&vfu_ctx, false, 8192, PCI_CAP_ID_PM); + assert_int_equal(0, offset); + assert_int_equal(EINVAL, errno); + offset = vfu_pci_find_next_capability(&vfu_ctx, false, 256, PCI_CAP_ID_PM); + assert_int_equal(0, offset); + assert_int_equal(EINVAL, errno); + offset = vfu_pci_find_next_capability(&vfu_ctx, false, 255, PCI_CAP_ID_PM); + assert_int_equal(0, offset); + assert_int_equal(EINVAL, errno); + + offset = vfu_pci_find_next_capability(&vfu_ctx, false, + PCI_STD_HEADER_SIZEOF + + PCI_PM_SIZEOF + 1, + PCI_CAP_ID_VNDR); + assert_int_equal(0, offset); + assert_int_equal(ENOENT, errno); - /* check writing PMCS */ + /* check writing PMCS */ assert_int_equal(0, cap_maybe_access(&vfu_ctx, caps, (char*)&pmcap.pmcs, sizeof(struct pmcs), |