diff options
author | Marcelo Tosatti <mtosatti@redhat.com> | 2012-09-11 13:30:22 -0300 |
---|---|---|
committer | Marcelo Tosatti <mtosatti@redhat.com> | 2012-09-11 13:30:22 -0300 |
commit | 6b414d9fb86527118f3ddb81a1d1a684b3548a9d (patch) | |
tree | 21973df930ee1bff414b15a42088dd97e256543c /hw/kvm/pci-assign.c | |
parent | 4c3e02beed9878a5f760eeceb6cd42c475cf0127 (diff) | |
parent | 8ca9e258af2921d41214b0b644bdaeedab0f7f64 (diff) |
Merge branch 'upstream-merge'
* upstream-merge: (88 commits)
Add ability to force enable/disable of tools build
Add ability to disable build of all targets
RTC: Remove the current_tm field
RTC: Get and set time without going through s->current_tm
RTC: Do not fire timer periodically to catch next alarm
RTC: Add divider reset support
RTC: Update the RTC clock only when reading it
vmstate: add VMSTATE_TIMER_V
RTC: Update interrupt state when interrupts are masked/unmasked
RTC: introduce RTC_CLOCK_RATE
RTC: Rename rtc_timer_update
RTC: Remove the logic to update time format when DM bit changed
socket: don't attempt to reconnect a TCP socket in server mode
use --libexecdir instead of ignoring it first and reinventing it later
hw/mcf5206: Fix buffer overflow for MBAR read / write
target-arm: Fix potential buffer overflow
hw/wm8750: Fix potential buffer overflow
kvm: i386: Add classic PCI device assignment
kvm: i386: Add services required for PCI device assignment
kvm: Introduce kvm_has_intx_set_mask
...
Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
Diffstat (limited to 'hw/kvm/pci-assign.c')
-rw-r--r-- | hw/kvm/pci-assign.c | 294 |
1 files changed, 140 insertions, 154 deletions
diff --git a/hw/kvm/pci-assign.c b/hw/kvm/pci-assign.c index 9cce02cbf..05b93d9a5 100644 --- a/hw/kvm/pci-assign.c +++ b/hw/kvm/pci-assign.c @@ -1,23 +1,18 @@ /* * Copyright (c) 2007, Neocleus Corporation. * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., 59 Temple - * Place - Suite 330, Boston, MA 02111-1307 USA. + * This work is licensed under the terms of the GNU GPL, version 2. See + * the COPYING file in the top-level directory. * * * Assign a PCI device from the host to a guest VM. * - * Adapted for KVM by Qumranet. + * This implementation uses the classic device assignment interface of KVM + * and is only available on x86 hosts. It is expected to be obsoleted by VFIO + * based device assignment. + * + * Adapted for KVM (qemu-kvm) by Qumranet. QEMU version was based on qemu-kvm + * revision 4144fe9d48. See its repository for the history. * * Copyright (c) 2007, Neocleus, Alex Novik (alex@neocleus.com) * Copyright (c) 2007, Neocleus, Guy Zana (guy@neocleus.com) @@ -52,7 +47,7 @@ #define IORESOURCE_DMA 0x00000800 #define IORESOURCE_PREFETCH 0x00002000 /* No side effects */ -/* #define DEVICE_ASSIGNMENT_DEBUG 1 */ +//#define DEVICE_ASSIGNMENT_DEBUG #ifdef DEVICE_ASSIGNMENT_DEBUG #define DEBUG(fmt, ...) \ @@ -63,15 +58,15 @@ #define DEBUG(fmt, ...) #endif -typedef struct { +typedef struct PCIRegion { int type; /* Memory or port I/O */ int valid; - uint32_t base_addr; - uint32_t size; /* size of the region */ + uint64_t base_addr; + uint64_t size; /* size of the region */ int resource_fd; } PCIRegion; -typedef struct { +typedef struct PCIDevRegions { uint8_t bus, dev, func; /* Bus inside domain, device and function */ int irq; /* IRQ number */ uint16_t region_number; /* number of active regions */ @@ -81,11 +76,11 @@ typedef struct { int config_fd; } PCIDevRegions; -typedef struct { +typedef struct AssignedDevRegion { MemoryRegion container; MemoryRegion real_iomem; union { - void *r_virtbase; /* mmapped access address for memory regions */ + uint8_t *r_virtbase; /* mmapped access address for memory regions */ uint32_t r_baseport; /* the base guest port for I/O regions */ } u; pcibus_t e_size; /* emulated size of region in bytes */ @@ -99,7 +94,7 @@ typedef struct { #define ASSIGNED_DEVICE_PREFER_MSI_MASK (1 << ASSIGNED_DEVICE_PREFER_MSI_BIT) #define ASSIGNED_DEVICE_SHARE_INTX_MASK (1 << ASSIGNED_DEVICE_SHARE_INTX_BIT) -typedef struct { +typedef struct MSIXTableEntry { uint32_t addr_lo; uint32_t addr_hi; uint32_t data; @@ -160,27 +155,27 @@ static uint64_t assigned_dev_ioport_rw(AssignedDevRegion *dev_region, if (fd >= 0) { if (data) { - DEBUG("pwrite data=%lx, size=%d, e_phys=%lx, addr=%lx\n", - *data, size, addr, addr); + DEBUG("pwrite data=%" PRIx64 ", size=%d, e_phys=" TARGET_FMT_plx + ", addr="TARGET_FMT_plx"\n", *data, size, addr, addr); if (pwrite(fd, data, size, addr) != size) { - fprintf(stderr, "%s - pwrite failed %s\n", - __func__, strerror(errno)); + error_report("%s - pwrite failed %s", + __func__, strerror(errno)); } } else { if (pread(fd, &val, size, addr) != size) { - fprintf(stderr, "%s - pread failed %s\n", - __func__, strerror(errno)); + error_report("%s - pread failed %s", + __func__, strerror(errno)); val = (1UL << (size * 8)) - 1; } - DEBUG("pread val=%lx, size=%d, e_phys=%lx, addr=%lx\n", - val, size, addr, addr); + DEBUG("pread val=%" PRIx64 ", size=%d, e_phys=" TARGET_FMT_plx + ", addr=" TARGET_FMT_plx "\n", val, size, addr, addr); } } else { uint32_t port = addr + dev_region->u.r_baseport; if (data) { - DEBUG("out data=%lx, size=%d, e_phys=%lx, host=%x\n", - *data, size, addr, port); + DEBUG("out data=%" PRIx64 ", size=%d, e_phys=" TARGET_FMT_plx + ", host=%x\n", *data, size, addr, port); switch (size) { case 1: outb(*data, port); @@ -204,8 +199,8 @@ static uint64_t assigned_dev_ioport_rw(AssignedDevRegion *dev_region, val = inl(port); break; } - DEBUG("in data=%lx, size=%d, e_phys=%lx, host=%x\n", - val, size, addr, port); + DEBUG("in data=%" PRIx64 ", size=%d, e_phys=" TARGET_FMT_plx + ", host=%x\n", val, size, addr, port); } } return val; @@ -238,7 +233,7 @@ static uint32_t slow_bar_readb(void *opaque, target_phys_addr_t addr) static uint32_t slow_bar_readw(void *opaque, target_phys_addr_t addr) { AssignedDevRegion *d = opaque; - uint16_t *in = d->u.r_virtbase + addr; + uint16_t *in = (uint16_t *)(d->u.r_virtbase + addr); uint32_t r; r = *in; @@ -250,7 +245,7 @@ static uint32_t slow_bar_readw(void *opaque, target_phys_addr_t addr) static uint32_t slow_bar_readl(void *opaque, target_phys_addr_t addr) { AssignedDevRegion *d = opaque; - uint32_t *in = d->u.r_virtbase + addr; + uint32_t *in = (uint32_t *)(d->u.r_virtbase + addr); uint32_t r; r = *in; @@ -271,7 +266,7 @@ static void slow_bar_writeb(void *opaque, target_phys_addr_t addr, uint32_t val) static void slow_bar_writew(void *opaque, target_phys_addr_t addr, uint32_t val) { AssignedDevRegion *d = opaque; - uint16_t *out = d->u.r_virtbase + addr; + uint16_t *out = (uint16_t *)(d->u.r_virtbase + addr); DEBUG("slow_bar_writew addr=0x" TARGET_FMT_plx " val=0x%04x\n", addr, val); *out = val; @@ -280,7 +275,7 @@ static void slow_bar_writew(void *opaque, target_phys_addr_t addr, uint32_t val) static void slow_bar_writel(void *opaque, target_phys_addr_t addr, uint32_t val) { AssignedDevRegion *d = opaque; - uint32_t *out = d->u.r_virtbase + addr; + uint32_t *out = (uint32_t *)(d->u.r_virtbase + addr); DEBUG("slow_bar_writel addr=0x" TARGET_FMT_plx " val=0x%08x\n", addr, val); *out = val; @@ -310,7 +305,7 @@ static void assigned_dev_iomem_setup(PCIDevice *pci_dev, int region_num, if (real_region->base_addr <= r_dev->msix_table_addr && real_region->base_addr + real_region->size > r_dev->msix_table_addr) { - int offset = r_dev->msix_table_addr - real_region->base_addr; + uint64_t offset = r_dev->msix_table_addr - real_region->base_addr; memory_region_add_subregion_overlap(®ion->container, offset, @@ -460,9 +455,8 @@ static int assigned_dev_register_regions(PCIRegion *io_regions, if (pci_dev->v_addrs[i].u.r_virtbase == MAP_FAILED) { pci_dev->v_addrs[i].u.r_virtbase = NULL; - fprintf(stderr, "%s: Error: Couldn't mmap 0x%x!" - "\n", __func__, - (uint32_t) (cur_region->base_addr)); + error_report("%s: Error: Couldn't mmap 0x%" PRIx64 "!", + __func__, cur_region->base_addr); return -1; } @@ -474,12 +468,11 @@ static int assigned_dev_register_regions(PCIRegion *io_regions, (cur_region->base_addr & 0xFFF); if (cur_region->size & 0xFFF) { - fprintf(stderr, "PCI region %d at address 0x%llx " - "has size 0x%x, which is not a multiple of 4K. " - "You might experience some performance hit " - "due to that.\n", - i, (unsigned long long)cur_region->base_addr, - cur_region->size); + error_report("PCI region %d at address 0x%" PRIx64 " has " + "size 0x%" PRIx64 ", which is not a multiple of " + "4K. You might experience some performance hit " + "due to that.", + i, cur_region->base_addr, cur_region->size); memory_region_init_io(&pci_dev->v_addrs[i].real_iomem, &slow_bar_ops, &pci_dev->v_addrs[i], "assigned-dev-slow-bar", @@ -510,12 +503,11 @@ static int assigned_dev_register_regions(PCIRegion *io_regions, * so should return EINVAL for a 3 byte read */ ret = pread(pci_dev->v_addrs[i].region->resource_fd, &val, 3, 0); if (ret >= 0) { - fprintf(stderr, "Unexpected return from I/O port read: %d\n", - ret); + error_report("Unexpected return from I/O port read: %d", ret); abort(); } else if (errno != EINVAL) { - fprintf(stderr, "Kernel doesn't support ioport resource " - "access, hiding this region.\n"); + error_report("Kernel doesn't support ioport resource " + "access, hiding this region."); close(pci_dev->v_addrs[i].region->resource_fd); cur_region->valid = 0; continue; @@ -545,7 +537,7 @@ static int get_real_id(const char *devpath, const char *idname, uint16_t *val) snprintf(name, sizeof(name), "%s%s", devpath, idname); f = fopen(name, "r"); if (f == NULL) { - fprintf(stderr, "%s: %s: %m\n", __func__, name); + error_report("%s: %s: %m", __func__, name); return -1; } if (fscanf(f, "%li\n", &id) == 1) { @@ -574,7 +566,7 @@ static int get_real_device(AssignedDevice *pci_dev, uint16_t r_seg, char dir[128], name[128]; int fd, r = 0, v; FILE *f; - unsigned long long start, end, size, flags; + uint64_t start, end, size, flags; uint16_t id; PCIRegion *rp; PCIDevRegions *dev = &pci_dev->real_device; @@ -592,8 +584,8 @@ static int get_real_device(AssignedDevice *pci_dev, uint16_t r_seg, } else { dev->config_fd = monitor_get_fd(cur_mon, pci_dev->configfd_name); if (dev->config_fd < 0) { - fprintf(stderr, "%s: (%s) unkown\n", __func__, - pci_dev->configfd_name); + error_report("%s: (%s) unkown", __func__, + pci_dev->configfd_name); return 1; } } @@ -601,7 +593,7 @@ static int get_real_device(AssignedDevice *pci_dev, uint16_t r_seg, dev->config_fd = open(name, O_RDWR); if (dev->config_fd == -1) { - fprintf(stderr, "%s: %s: %m\n", __func__, name); + error_report("%s: %s: %m", __func__, name); return 1; } } @@ -612,7 +604,7 @@ again: if (errno == EINTR || errno == EAGAIN) { goto again; } - fprintf(stderr, "%s: read failed, errno = %d\n", __func__, errno); + error_report("%s: read failed, errno = %d", __func__, errno); } /* Restore or clear multifunction, this is always controlled by qemu */ @@ -632,12 +624,13 @@ again: f = fopen(name, "r"); if (f == NULL) { - fprintf(stderr, "%s: %s: %m\n", __func__, name); + error_report("%s: %s: %m", __func__, name); return 1; } for (r = 0; r < PCI_ROM_SLOT; r++) { - if (fscanf(f, "%lli %lli %lli\n", &start, &end, &flags) != 3) { + if (fscanf(f, "%" SCNi64 " %" SCNi64 " %" SCNi64 "\n", + &start, &end, &flags) != 3) { break; } @@ -666,7 +659,8 @@ again: rp->base_addr = start; rp->size = size; pci_dev->v_addrs[r].region = rp; - DEBUG("region %d size %d start 0x%llx type %d resource_fd %d\n", + DEBUG("region %d size %" PRIu64 " start 0x%" PRIx64 + " type %d resource_fd %d\n", r, rp->size, start, rp->type, rp->resource_fd); } @@ -748,9 +742,8 @@ static void free_assigned_device(AssignedDevice *dev) memory_region_destroy(®ion->container); if (munmap(region->u.r_virtbase, (pci_region->size + 0xFFF) & 0xFFFFF000)) { - fprintf(stderr, - "Failed to unmap assigned device region: %s\n", - strerror(errno)); + error_report("Failed to unmap assigned device region: %s", + strerror(errno)); } } } @@ -772,11 +765,11 @@ static void assign_failed_examine(AssignedDevice *dev) uint16_t vendor_id, device_id; int r; - sprintf(dir, "/sys/bus/pci/devices/%04x:%02x:%02x.%01x/", + snprintf(dir, sizeof(dir), "/sys/bus/pci/devices/%04x:%02x:%02x.%01x/", dev->host.domain, dev->host.bus, dev->host.slot, dev->host.function); - sprintf(name, "%sdriver", dir); + snprintf(name, sizeof(name), "%sdriver", dir); r = readlink(name, driver, sizeof(driver)); if ((r <= 0) || r >= sizeof(driver)) { @@ -795,31 +788,31 @@ static void assign_failed_examine(AssignedDevice *dev) goto fail; } - fprintf(stderr, "*** The driver '%s' is occupying your device " - "%04x:%02x:%02x.%x.\n", - ns, dev->host.domain, dev->host.bus, dev->host.slot, - dev->host.function); - fprintf(stderr, "***\n"); - fprintf(stderr, "*** You can try the following commands to free it:\n"); - fprintf(stderr, "***\n"); - fprintf(stderr, "*** $ echo \"%04x %04x\" > /sys/bus/pci/drivers/pci-stub/" - "new_id\n", vendor_id, device_id); - fprintf(stderr, "*** $ echo \"%04x:%02x:%02x.%x\" > /sys/bus/pci/drivers/" - "%s/unbind\n", - dev->host.domain, dev->host.bus, dev->host.slot, - dev->host.function, ns); - fprintf(stderr, "*** $ echo \"%04x:%02x:%02x.%x\" > /sys/bus/pci/drivers/" - "pci-stub/bind\n", - dev->host.domain, dev->host.bus, dev->host.slot, - dev->host.function); - fprintf(stderr, "*** $ echo \"%04x %04x\" > /sys/bus/pci/drivers/pci-stub" - "/remove_id\n", vendor_id, device_id); - fprintf(stderr, "***\n"); + error_report("*** The driver '%s' is occupying your device " + "%04x:%02x:%02x.%x.", + ns, dev->host.domain, dev->host.bus, dev->host.slot, + dev->host.function); + error_report("***"); + error_report("*** You can try the following commands to free it:"); + error_report("***"); + error_report("*** $ echo \"%04x %04x\" > /sys/bus/pci/drivers/pci-stub/" + "new_id", vendor_id, device_id); + error_report("*** $ echo \"%04x:%02x:%02x.%x\" > /sys/bus/pci/drivers/" + "%s/unbind", + dev->host.domain, dev->host.bus, dev->host.slot, + dev->host.function, ns); + error_report("*** $ echo \"%04x:%02x:%02x.%x\" > /sys/bus/pci/drivers/" + "pci-stub/bind", + dev->host.domain, dev->host.bus, dev->host.slot, + dev->host.function); + error_report("*** $ echo \"%04x %04x\" > /sys/bus/pci/drivers/pci-stub" + "/remove_id", vendor_id, device_id); + error_report("***"); return; fail: - fprintf(stderr, "Couldn't find out why.\n"); + error_report("Couldn't find out why."); } static int assign_device(AssignedDevice *dev) @@ -830,14 +823,14 @@ static int assign_device(AssignedDevice *dev) /* Only pass non-zero PCI segment to capable module */ if (!kvm_check_extension(kvm_state, KVM_CAP_PCI_SEGMENT) && dev->host.domain) { - fprintf(stderr, "Can't assign device inside non-zero PCI segment " - "as this KVM module doesn't support it.\n"); + error_report("Can't assign device inside non-zero PCI segment " + "as this KVM module doesn't support it."); return -ENODEV; } if (!kvm_check_extension(kvm_state, KVM_CAP_IOMMU)) { - fprintf(stderr, "No IOMMU found. Unable to assign device \"%s\"\n", - dev->dev.qdev.id); + error_report("No IOMMU found. Unable to assign device \"%s\"", + dev->dev.qdev.id); return -ENODEV; } @@ -848,8 +841,8 @@ static int assign_device(AssignedDevice *dev) r = kvm_device_pci_assign(kvm_state, &dev->host, flags, &dev->dev_id); if (r < 0) { - fprintf(stderr, "Failed to assign device \"%s\" : %s\n", - dev->dev.qdev.id, strerror(-r)); + error_report("Failed to assign device \"%s\" : %s", + dev->dev.qdev.id, strerror(-r)); switch (r) { case -EBUSY: @@ -892,7 +885,7 @@ static int assign_intx(AssignedDevice *dev) pci_device_set_intx_routing_notifier(&dev->dev, assigned_dev_update_irq_routing); - intx_route = pci_device_route_intx_to_irq(&dev->dev, 0); + intx_route = pci_device_route_intx_to_irq(&dev->dev, dev->intpin); assert(intx_route.mode != PCI_INTX_INVERTED); if (dev->intx_route.mode == intx_route.mode && @@ -917,7 +910,7 @@ static int assign_intx(AssignedDevice *dev) break; } if (r) { - perror("assign_intx: deassign"); + perror("assign_intx: deassignment of previous interrupt failed"); } dev->assigned_irq_type = ASSIGNED_IRQ_NONE; @@ -943,17 +936,16 @@ retry: dev->cap.available & ASSIGNED_DEVICE_CAP_MSI) { /* Retry with host-side MSI. There might be an IRQ conflict and * either the kernel or the device doesn't support sharing. */ - fprintf(stderr, - "Host-side INTx sharing not supported, " - "using MSI instead.\n" - "Some devices do not to work properly in this mode.\n"); + error_report("Host-side INTx sharing not supported, " + "using MSI instead.\n" + "Some devices do not to work properly in this mode."); dev->features |= ASSIGNED_DEVICE_PREFER_MSI_MASK; goto retry; } - fprintf(stderr, "Failed to assign irq for \"%s\": %s\n", - dev->dev.qdev.id, strerror(-r)); - fprintf(stderr, "Perhaps you are assigning a device " - "that shares an IRQ with another device?\n"); + error_report("Failed to assign irq for \"%s\": %s", + dev->dev.qdev.id, strerror(-r)); + error_report("Perhaps you are assigning a device " + "that shares an IRQ with another device?"); return r; } @@ -967,10 +959,7 @@ static void deassign_device(AssignedDevice *dev) int r; r = kvm_device_pci_deassign(kvm_state, dev->dev_id); - if (r < 0) { - fprintf(stderr, "Failed to deassign device \"%s\" : %s\n", - dev->dev.qdev.id, strerror(-r)); - } + assert(r == 0); } /* The pci config space got updated. Check if irq numbers have changed @@ -1041,7 +1030,7 @@ static void assigned_dev_update_msi(PCIDevice *pci_dev) } } -static bool msix_masked(MSIXTableEntry *entry) +static bool assigned_dev_msix_masked(MSIXTableEntry *entry) { return (entry->ctrl & cpu_to_le32(0x1)) != 0; } @@ -1056,7 +1045,7 @@ static int assigned_dev_update_msix_mmio(PCIDevice *pci_dev) /* Get the usable entry number for allocating */ for (i = 0; i < adev->msix_max; i++, entry++) { - if (msix_masked(entry)) { + if (assigned_dev_msix_masked(entry)) { continue; } entries_nr++; @@ -1071,8 +1060,8 @@ static int assigned_dev_update_msix_mmio(PCIDevice *pci_dev) r = kvm_device_msix_init_vectors(kvm_state, adev->dev_id, entries_nr); if (r != 0) { - fprintf(stderr, "fail to set MSI-X entry number for MSIX! %s\n", - strerror(-r)); + error_report("fail to set MSI-X entry number for MSIX! %s", + strerror(-r)); return r; } @@ -1085,7 +1074,7 @@ static int assigned_dev_update_msix_mmio(PCIDevice *pci_dev) for (i = 0; i < adev->msix_max; i++, entry++) { adev->msi_virq[i] = -1; - if (msix_masked(entry)) { + if (assigned_dev_msix_masked(entry)) { continue; } @@ -1103,7 +1092,7 @@ static int assigned_dev_update_msix_mmio(PCIDevice *pci_dev) r = kvm_device_msix_set_vector(kvm_state, adev->dev_id, i, adev->msi_virq[i]); if (r) { - fprintf(stderr, "fail to set MSI-X entry! %s\n", strerror(-r)); + error_report("fail to set MSI-X entry! %s", strerror(-r)); break; } } @@ -1350,15 +1339,13 @@ static int assigned_device_pci_cap_init(PCIDevice *pci_dev) */ size = MIN(0x3c, PCI_CONFIG_SPACE_SIZE - pos); if (size < 0x34) { - fprintf(stderr, - "%s: Invalid size PCIe cap-id 0x%x\n", - __func__, PCI_CAP_ID_EXP); + error_report("%s: Invalid size PCIe cap-id 0x%x", + __func__, PCI_CAP_ID_EXP); return -EINVAL; } else if (size != 0x3c) { - fprintf(stderr, - "WARNING, %s: PCIe cap-id 0x%x has " - "non-standard size 0x%x; std size should be 0x3c\n", - __func__, PCI_CAP_ID_EXP, size); + error_report("WARNING, %s: PCIe cap-id 0x%x has " + "non-standard size 0x%x; std size should be 0x3c", + __func__, PCI_CAP_ID_EXP, size); } } else if (version == 0) { uint16_t vid, did; @@ -1374,9 +1361,8 @@ static int assigned_device_pci_cap_init(PCIDevice *pci_dev) } if (size == 0) { - fprintf(stderr, - "%s: Unsupported PCI express capability version %d\n", - __func__, version); + error_report("%s: Unsupported PCI express capability version %d", + __func__, version); return -EINVAL; } @@ -1391,9 +1377,8 @@ static int assigned_device_pci_cap_init(PCIDevice *pci_dev) type = (type & PCI_EXP_FLAGS_TYPE) >> 4; if (type != PCI_EXP_TYPE_ENDPOINT && type != PCI_EXP_TYPE_LEG_END && type != PCI_EXP_TYPE_RC_END) { - fprintf(stderr, - "Device assignment only supports endpoint assignment, " - "device type %d\n", type); + error_report("Device assignment only supports endpoint assignment," + " device type %d", type); return -EINVAL; } @@ -1519,8 +1504,9 @@ static int assigned_device_pci_cap_init(PCIDevice *pci_dev) return 0; } -static uint64_t msix_mmio_read(void *opaque, target_phys_addr_t addr, - unsigned size) +static uint64_t +assigned_dev_msix_mmio_read(void *opaque, target_phys_addr_t addr, + unsigned size) { AssignedDevice *adev = opaque; uint64_t val; @@ -1530,8 +1516,8 @@ static uint64_t msix_mmio_read(void *opaque, target_phys_addr_t addr, return val; } -static void msix_mmio_write(void *opaque, target_phys_addr_t addr, - uint64_t val, unsigned size) +static void assigned_dev_msix_mmio_write(void *opaque, target_phys_addr_t addr, + uint64_t val, unsigned size) { AssignedDevice *adev = opaque; PCIDevice *pdev = &adev->dev; @@ -1551,12 +1537,13 @@ static void msix_mmio_write(void *opaque, target_phys_addr_t addr, orig = adev->msix_table[i]; } - memcpy((void *)((uint8_t *)adev->msix_table + addr), &val, size); + memcpy((uint8_t *)adev->msix_table + addr, &val, size); if (ctrl & PCI_MSIX_FLAGS_ENABLE) { MSIXTableEntry *entry = &adev->msix_table[i]; - if (!msix_masked(&orig) && msix_masked(entry)) { + if (!assigned_dev_msix_masked(&orig) && + assigned_dev_msix_masked(entry)) { /* * Vector masked, disable it * @@ -1568,7 +1555,8 @@ static void msix_mmio_write(void *opaque, target_phys_addr_t addr, * are lost. Can we get away with always injecting an * interrupt on unmask? */ - } else if (msix_masked(&orig) && !msix_masked(entry)) { + } else if (assigned_dev_msix_masked(&orig) && + !assigned_dev_msix_masked(entry)) { /* Vector unmasked */ if (i >= adev->msi_virq_nr || adev->msi_virq[i] < 0) { /* Previously unassigned vector, start from scratch */ @@ -1586,17 +1574,16 @@ static void msix_mmio_write(void *opaque, target_phys_addr_t addr, ret = kvm_irqchip_update_msi_route(kvm_state, adev->msi_virq[i], msg); if (ret) { - fprintf(stderr, - "Error updating irq routing entry (%d)\n", ret); + error_report("Error updating irq routing entry (%d)", ret); } } } } } -static const MemoryRegionOps msix_mmio_ops = { - .read = msix_mmio_read, - .write = msix_mmio_write, +static const MemoryRegionOps assigned_dev_msix_mmio_ops = { + .read = assigned_dev_msix_mmio_read, + .write = assigned_dev_msix_mmio_write, .endianness = DEVICE_NATIVE_ENDIAN, .valid = { .min_access_size = 4, @@ -1608,7 +1595,7 @@ static const MemoryRegionOps msix_mmio_ops = { }, }; -static void msix_reset(AssignedDevice *dev) +static void assigned_dev_msix_reset(AssignedDevice *dev) { MSIXTableEntry *entry; int i; @@ -1629,13 +1616,13 @@ static int assigned_dev_register_msix_mmio(AssignedDevice *dev) dev->msix_table = mmap(NULL, MSIX_PAGE_SIZE, PROT_READ|PROT_WRITE, MAP_ANONYMOUS|MAP_PRIVATE, 0, 0); if (dev->msix_table == MAP_FAILED) { - fprintf(stderr, "fail allocate msix_table! %s\n", strerror(errno)); + error_report("fail allocate msix_table! %s", strerror(errno)); return -EFAULT; } - msix_reset(dev); + assigned_dev_msix_reset(dev); - memory_region_init_io(&dev->mmio, &msix_mmio_ops, dev, + memory_region_init_io(&dev->mmio, &assigned_dev_msix_mmio_ops, dev, "assigned-dev-msix", MSIX_PAGE_SIZE); return 0; } @@ -1649,8 +1636,7 @@ static void assigned_dev_unregister_msix_mmio(AssignedDevice *dev) memory_region_destroy(&dev->mmio); if (munmap(dev->msix_table, MSIX_PAGE_SIZE) == -1) { - fprintf(stderr, "error unmapping msix_table! %s\n", - strerror(errno)); + error_report("error unmapping msix_table! %s", strerror(errno)); } dev->msix_table = NULL; } @@ -1779,7 +1765,7 @@ static int assigned_initfn(struct PCIDevice *pci_dev) } /* handle interrupt routing */ - e_intx = dev->dev.config[0x3d] - 1; + e_intx = dev->dev.config[PCI_INTERRUPT_PIN] - 1; dev->intpin = e_intx; dev->intx_route.mode = PCI_INTX_DISABLED; dev->intx_route.irq = -1; @@ -1817,7 +1803,7 @@ static void assigned_exitfn(struct PCIDevice *pci_dev) free_assigned_device(dev); } -static Property da_properties[] = { +static Property assigned_dev_properties[] = { DEFINE_PROP_PCI_HOST_DEVADDR("host", AssignedDevice, host), DEFINE_PROP_BIT("prefer_msi", AssignedDevice, features, ASSIGNED_DEVICE_PREFER_MSI_BIT, false), @@ -1837,13 +1823,14 @@ static void assign_class_init(ObjectClass *klass, void *data) k->exit = assigned_exitfn; k->config_read = assigned_dev_pci_read_config; k->config_write = assigned_dev_pci_write_config; - dc->props = da_properties; + dc->props = assigned_dev_properties; dc->vmsd = &vmstate_assigned_device; dc->reset = reset_assigned_device; + dc->desc = "KVM-based PCI passthrough"; } -static TypeInfo assign_info = { - .name = "pci-assign", +static const TypeInfo assign_info = { + .name = "kvm-pci-assign", .parent = TYPE_PCI_DEVICE, .instance_size = sizeof(AssignedDevice), .class_init = assign_class_init, @@ -1884,8 +1871,7 @@ static void assigned_dev_load_option_rom(AssignedDevice *dev) } if (access(rom_file, F_OK)) { - fprintf(stderr, "pci-assign: Insufficient privileges for %s\n", - rom_file); + error_report("pci-assign: Insufficient privileges for %s", rom_file); return; } @@ -1908,10 +1894,10 @@ static void assigned_dev_load_option_rom(AssignedDevice *dev) memset(ptr, 0xff, st.st_size); if (!fread(ptr, 1, st.st_size, fp)) { - fprintf(stderr, "pci-assign: Cannot read from host %s\n" - "\tDevice option ROM contents are probably invalid " - "(check dmesg).\n\tSkip option ROM probe with rombar=0, " - "or load from file with romfile=\n", rom_file); + error_report("pci-assign: Cannot read from host %s\n" + "\tDevice option ROM contents are probably invalid " + "(check dmesg).\n\tSkip option ROM probe with rombar=0, " + "or load from file with romfile=", rom_file); memory_region_destroy(&dev->dev.rom); goto close_rom; } |