Add new trace points trace_vfio_pci_config and trace_vfio_msix_table to dump PCI config space and MSI data.
Signed-off-by: Steve Sistare <steven.sist...@oracle.com> --- hw/vfio/pci.c | 99 ++++++++++++++++++++++++++++++++++++++++++++++++++++ hw/vfio/trace-events | 2 ++ 2 files changed, 101 insertions(+) diff --git a/hw/vfio/pci.c b/hw/vfio/pci.c index 5743807..f72e277 100644 --- a/hw/vfio/pci.c +++ b/hw/vfio/pci.c @@ -2715,6 +2715,90 @@ static void vfio_unregister_req_notifier(VFIOPCIDevice *vdev) vdev->req_enabled = false; } +/* To limit output, trace only this many bytes of config. */ +#define CONFIG_LEN 512 + +static void vfio_dump_config(const char *name, int fd, off_t offset) +{ + int i, j, n, config[CONFIG_LEN / 4]; + char buf[128]; + const char *fmt; + char *ptr = buf; + int *v = config; + int len = sizeof(buf) - 1; + +#ifdef CONFIG_TRACE_DTRACE + if (!QEMU_VFIO_PCI_CONFIG_ENABLED()) { + return; + } +#endif + + if (pread(fd, &config, sizeof(config), offset) < 0) { + perror("pread"); + return; + } + + trace_vfio_pci_config(name); + + for (i = 0; i < CONFIG_LEN; i += 32, v += 8) { + n = snprintf(buf, len, "+%3d:", i); + ptr += n; + len -= n; + for (j = 0; j < 8; j++) { + fmt = v[j] ? " %08x" : " %8x"; + n = snprintf(ptr, len, fmt, v[j]); + ptr += n; + len -= n; + } + *ptr = 0; /* terminate in case of truncation above */ + trace_vfio_pci_config(buf); + } +} + +static void vfio_dump_config_vdev(VFIOPCIDevice *vdev) +{ + vfio_dump_config(vdev->vbasedev.name, vdev->vbasedev.fd, + vdev->config_offset); +} + +static void vfio_dump_msix_vdev(VFIOPCIDevice *vdev) +{ + int i; + int *ptr = (int *) vdev->pdev.msix_table; + + for (i = 0; i < vdev->pdev.msix_entries_nr; i++, ptr += 4) { + trace_vfio_msix_table(vdev->vbasedev.name, i, + ptr[0], ptr[1], ptr[2], ptr[3]); + } +} + +static void vfio_diff_config(VFIOPCIDevice *vdev) +{ + int i; + unsigned char config[CONFIG_LEN]; + int n = sizeof(config); + unsigned char *c1 = (unsigned char *)config; + unsigned char *c2 = (unsigned char *)vdev->pdev.config; + char buf[128]; + +#ifdef CONFIG_TRACE_DTRACE + if (!QEMU_VFIO_PCI_CONFIG_ENABLED()) { + return; + } +#endif + + if (pread(vdev->vbasedev.fd, &config, n, vdev->config_offset) != n) { + error_report("vfio_diff_config pread failed"); + } + for (i = 0; i < CONFIG_LEN; i++) { + if (c1[i] != c2[i]) { + snprintf(buf, sizeof(buf), + "config mismatch at %d: %x vs %x", i, c1[i], c2[i]); + trace_vfio_pci_config(buf); + } + } +} + static void vfio_realize(PCIDevice *pdev, Error **errp) { VFIOPCIDevice *vdev = PCI_VFIO(pdev); @@ -3037,6 +3121,9 @@ static void vfio_realize(PCIDevice *pdev, Error **errp) if (pdev->reused) { pci_update_mappings(pdev); } + vfio_diff_config(vdev); + vfio_dump_config_vdev(vdev); + vfio_dump_msix_vdev(vdev); return; @@ -3207,6 +3294,15 @@ static Property vfio_pci_dev_properties[] = { DEFINE_PROP_END_OF_LIST(), }; +static int vfio_pci_pre_save(void *opaque) +{ + VFIOPCIDevice *vdev = opaque; + + vfio_dump_config_vdev(vdev); + vfio_dump_msix_vdev(vdev); + return 0; +} + static int vfio_pci_post_load(void *opaque, int version_id) { int vector; @@ -3226,6 +3322,8 @@ static int vfio_pci_post_load(void *opaque, int version_id) } } + vfio_dump_msix_vdev(vdev); + } else if (vfio_pci_read_config(pdev, PCI_INTERRUPT_PIN, 1)) { vfio_intx_enable(vdev, &err); if (err) { @@ -3246,6 +3344,7 @@ static const VMStateDescription vfio_pci_vmstate = { .version_id = 0, .minimum_version_id = 0, .post_load = vfio_pci_post_load, + .pre_save = vfio_pci_pre_save, .fields = (VMStateField[]) { VMSTATE_MSIX(pdev, VFIOPCIDevice), VMSTATE_END_OF_LIST() diff --git a/hw/vfio/trace-events b/hw/vfio/trace-events index b1ef55a..10d899c 100644 --- a/hw/vfio/trace-events +++ b/hw/vfio/trace-events @@ -47,6 +47,8 @@ vfio_pci_emulated_vendor_id(const char *name, uint16_t val) "%s 0x%04x" vfio_pci_emulated_device_id(const char *name, uint16_t val) "%s 0x%04x" vfio_pci_emulated_sub_vendor_id(const char *name, uint16_t val) "%s 0x%04x" vfio_pci_emulated_sub_device_id(const char *name, uint16_t val) "%s 0x%04x" +vfio_msix_table(const char *name, int index, int x0, int x1, int x2, int x3) "%s MSI-X[%d] = { %x %x %x %x }" +vfio_pci_config(const char *buf) "%s" # pci-quirks.c vfio_quirk_rom_blacklisted(const char *name, uint16_t vid, uint16_t did) "%s %04x:%04x" -- 1.8.3.1