test/pci: add ut for pci hooks
Add a test with a hooked PCI device that redirects all PCI config reads and writes to a local buffer. Change-Id: I86fb847a50a3d33ab20dcb1a8158a76e68843f6e Signed-off-by: Darek Stojaczyk <dariusz.stojaczyk@intel.com> Reviewed-on: https://review.gerrithub.io/435803 Tested-by: SPDK CI Jenkins <sys_sgci@intel.com> Chandler-Test-Pool: SPDK Automated Test System <sys_sgsw@intel.com> Reviewed-by: Shuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com> Reviewed-by: Jim Harris <james.r.harris@intel.com>
This commit is contained in:
parent
2f36777194
commit
aade7e3bc7
160
test/env/pci/pci_ut.c
vendored
160
test/env/pci/pci_ut.c
vendored
@ -38,7 +38,7 @@
|
||||
#include "env_dpdk/pci.c"
|
||||
|
||||
static void
|
||||
pci_test(void)
|
||||
pci_claim_test(void)
|
||||
{
|
||||
int rc = 0;
|
||||
pid_t childPid;
|
||||
@ -64,6 +64,161 @@ pci_test(void)
|
||||
}
|
||||
}
|
||||
|
||||
static struct spdk_pci_driver ut_pci_driver = {
|
||||
.is_registered = true,
|
||||
};
|
||||
|
||||
struct ut_pci_dev {
|
||||
struct spdk_pci_device pci;
|
||||
char config[16];
|
||||
char bar[16];
|
||||
bool attached;
|
||||
};
|
||||
|
||||
static int
|
||||
ut_map_bar(struct spdk_pci_device *dev, uint32_t bar,
|
||||
void **mapped_addr, uint64_t *phys_addr, uint64_t *size)
|
||||
{
|
||||
struct ut_pci_dev *ut_dev = (struct ut_pci_dev *)dev;
|
||||
|
||||
/* just one bar */
|
||||
if (bar > 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
*mapped_addr = ut_dev->bar;
|
||||
*phys_addr = 0;
|
||||
*size = sizeof(ut_dev->bar);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
ut_unmap_bar(struct spdk_pci_device *device, uint32_t bar, void *addr)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
ut_cfg_read(struct spdk_pci_device *dev, void *value, uint32_t len, uint32_t offset)
|
||||
{
|
||||
struct ut_pci_dev *ut_dev = (struct ut_pci_dev *)dev;
|
||||
|
||||
if (len + offset >= sizeof(ut_dev->config)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
memcpy(value, (void *)((uintptr_t)ut_dev->config + offset), len);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ut_cfg_write(struct spdk_pci_device *dev, void *value, uint32_t len, uint32_t offset)
|
||||
{
|
||||
struct ut_pci_dev *ut_dev = (struct ut_pci_dev *)dev;
|
||||
|
||||
if (len + offset >= sizeof(ut_dev->config)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
memcpy((void *)((uintptr_t)ut_dev->config + offset), value, len);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
ut_enum_cb(void *ctx, struct spdk_pci_device *dev)
|
||||
{
|
||||
struct ut_pci_dev *ut_dev = (struct ut_pci_dev *)dev;
|
||||
|
||||
ut_dev->attached = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
ut_detach(struct spdk_pci_device *dev)
|
||||
{
|
||||
struct ut_pci_dev *ut_dev = (struct ut_pci_dev *)dev;
|
||||
|
||||
ut_dev->attached = false;
|
||||
}
|
||||
|
||||
static void
|
||||
pci_hook_test(void)
|
||||
{
|
||||
struct ut_pci_dev ut_dev = {};
|
||||
uint32_t value_32;
|
||||
void *bar0_vaddr;
|
||||
uint64_t bar0_paddr, bar0_size;
|
||||
int rc;
|
||||
|
||||
ut_dev.pci.addr.domain = 0x10000;
|
||||
ut_dev.pci.addr.bus = 0x0;
|
||||
ut_dev.pci.addr.dev = 0x1;
|
||||
ut_dev.pci.addr.func = 0x0;
|
||||
ut_dev.pci.id.vendor_id = 0x4;
|
||||
ut_dev.pci.id.device_id = 0x8;
|
||||
|
||||
ut_dev.pci.map_bar = ut_map_bar;
|
||||
ut_dev.pci.unmap_bar = ut_unmap_bar;
|
||||
ut_dev.pci.cfg_read = ut_cfg_read;
|
||||
ut_dev.pci.cfg_write = ut_cfg_write;
|
||||
ut_dev.pci.detach = ut_detach;
|
||||
|
||||
/* hook the device into the PCI layer */
|
||||
spdk_pci_hook_device(&ut_pci_driver, &ut_dev.pci);
|
||||
|
||||
/* try to attach a device with the matching driver and bdf */
|
||||
rc = spdk_pci_device_attach(&ut_pci_driver, ut_enum_cb, NULL, &ut_dev.pci.addr);
|
||||
CU_ASSERT(rc == 0);
|
||||
CU_ASSERT(ut_dev.pci.internal.attached);
|
||||
CU_ASSERT(ut_dev.attached);
|
||||
|
||||
/* check PCI config writes and reads */
|
||||
value_32 = 0xDEADBEEF;
|
||||
rc = spdk_pci_device_cfg_write32(&ut_dev.pci, value_32, 0);
|
||||
CU_ASSERT(rc == 0);
|
||||
|
||||
value_32 = 0x0BADF00D;
|
||||
rc = spdk_pci_device_cfg_write32(&ut_dev.pci, value_32, 4);
|
||||
CU_ASSERT(rc == 0);
|
||||
|
||||
rc = spdk_pci_device_cfg_read32(&ut_dev.pci, &value_32, 0);
|
||||
CU_ASSERT(rc == 0);
|
||||
CU_ASSERT(value_32 == 0xDEADBEEF);
|
||||
CU_ASSERT(memcmp(&value_32, &ut_dev.config[0], 4) == 0);
|
||||
|
||||
rc = spdk_pci_device_cfg_read32(&ut_dev.pci, &value_32, 4);
|
||||
CU_ASSERT(rc == 0);
|
||||
CU_ASSERT(value_32 == 0x0BADF00D);
|
||||
CU_ASSERT(memcmp(&value_32, &ut_dev.config[4], 4) == 0);
|
||||
|
||||
/* out-of-bounds write */
|
||||
rc = spdk_pci_device_cfg_read32(&ut_dev.pci, &value_32, sizeof(ut_dev.config));
|
||||
CU_ASSERT(rc != 0);
|
||||
|
||||
/* map a bar */
|
||||
rc = spdk_pci_device_map_bar(&ut_dev.pci, 0, &bar0_vaddr, &bar0_paddr, &bar0_size);
|
||||
CU_ASSERT(rc == 0);
|
||||
CU_ASSERT(bar0_vaddr == ut_dev.bar);
|
||||
CU_ASSERT(bar0_size == sizeof(ut_dev.bar));
|
||||
spdk_pci_device_unmap_bar(&ut_dev.pci, 0, bar0_vaddr);
|
||||
|
||||
/* map an inaccessible bar */
|
||||
rc = spdk_pci_device_map_bar(&ut_dev.pci, 1, &bar0_vaddr, &bar0_paddr, &bar0_size);
|
||||
CU_ASSERT(rc != 0);
|
||||
|
||||
/* detach and verify our callback was called */
|
||||
spdk_pci_device_detach(&ut_dev.pci);
|
||||
CU_ASSERT(!ut_dev.attached);
|
||||
CU_ASSERT(!ut_dev.pci.internal.attached);
|
||||
|
||||
/* unhook the device */
|
||||
spdk_pci_unhook_device(&ut_dev.pci);
|
||||
|
||||
/* try to attach the same device again */
|
||||
rc = spdk_pci_device_attach(&ut_pci_driver, ut_enum_cb, NULL, &ut_dev.pci.addr);
|
||||
CU_ASSERT(rc != 0);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
CU_pSuite suite = NULL;
|
||||
@ -80,7 +235,8 @@ int main(int argc, char **argv)
|
||||
}
|
||||
|
||||
if (
|
||||
CU_add_test(suite, "pci_ut1", pci_test) == NULL
|
||||
CU_add_test(suite, "pci_claim", pci_claim_test) == NULL ||
|
||||
CU_add_test(suite, "pci_hook", pci_hook_test) == NULL
|
||||
) {
|
||||
CU_cleanup_registry();
|
||||
return CU_get_error();
|
||||
|
Loading…
Reference in New Issue
Block a user