aboutsummaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
authorJohn Levon <john.levon@nutanix.com>2021-01-05 15:18:42 +0000
committerGitHub <noreply@github.com>2021-01-05 15:18:42 +0000
commit70524c550322948765415d9b0eb29ac766e32e79 (patch)
tree02ad60182191238de12f7df4121f137018a29840 /test
parent1fa90d5abecd896362e551b2bd2ec987d8f60a6b (diff)
downloadlibvfio-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.c75
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),