From patchwork Fri Oct 31 14:05:38 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Auger Eric X-Patchwork-Id: 39903 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-wg0-f71.google.com (mail-wg0-f71.google.com [74.125.82.71]) by ip-10-151-82-157.ec2.internal (Postfix) with ESMTPS id 1189D202FE for ; Fri, 31 Oct 2014 14:06:12 +0000 (UTC) Received: by mail-wg0-f71.google.com with SMTP id b13sf3182805wgh.10 for ; Fri, 31 Oct 2014 07:06:12 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:mime-version:delivered-to:from:to:cc:subject :date:message-id:in-reply-to:references:x-original-sender :x-original-authentication-results:precedence:mailing-list:list-id :list-post:list-help:list-archive:list-unsubscribe; bh=qVTesFWTuFLMncXkEZzzQyj+zhEyT7ePj316AuCPwn0=; b=mNv7sIrP2e17sMVD5UKohHhvYx2aPYWpZQ/k2Tfni5+KOGLu51mmTFfV32bvUZy3YW RLR+fWNgxcdFPuyEftni1Xjg+icqn/N6l+p7jdLs1U6yprmhSJCkTNIsczrWQ+SygIxT g9mLO7j5qUVfKic2jIbey1SDFw9zHaYUuk2EgTJF4AF9kkIWoC5PDb63o4Q2S6Dwd2ZL wpRpCF5liVdPVNtonGWDpaPt0+HNy/dJVcV0uGxGEF5mGvsUopZZh2/DXLr9ALoiNkGe CSiGvrdosWJ9Xg6Q2ggNkymCeB7acKdr1RltazZi+Gq2DFURxjrQY2ADRDblxOCAEePR FcRQ== X-Gm-Message-State: ALoCoQmFaVh33azwX6RCy8uELdPvw/5rqQzIHd6aH82/1HIQsBqO3cSp/YuvnIi5k73jUFTtDCrS X-Received: by 10.152.88.4 with SMTP id bc4mr1561460lab.1.1414764372230; Fri, 31 Oct 2014 07:06:12 -0700 (PDT) MIME-Version: 1.0 X-BeenThere: patchwork-forward@linaro.org Received: by 10.152.23.103 with SMTP id l7ls203490laf.6.gmail; Fri, 31 Oct 2014 07:06:11 -0700 (PDT) X-Received: by 10.152.87.18 with SMTP id t18mr22362291laz.0.1414764371925; Fri, 31 Oct 2014 07:06:11 -0700 (PDT) Received: from mail-lb0-f174.google.com (mail-lb0-f174.google.com. [209.85.217.174]) by mx.google.com with ESMTPS id lm8si16921275lac.7.2014.10.31.07.06.11 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Fri, 31 Oct 2014 07:06:11 -0700 (PDT) Received-SPF: pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.217.174 as permitted sender) client-ip=209.85.217.174; Received: by mail-lb0-f174.google.com with SMTP id z11so4141956lbi.19 for ; Fri, 31 Oct 2014 07:06:11 -0700 (PDT) X-Received: by 10.112.12.35 with SMTP id v3mr26463142lbb.80.1414764371801; Fri, 31 Oct 2014 07:06:11 -0700 (PDT) X-Forwarded-To: patchwork-forward@linaro.org X-Forwarded-For: patch@linaro.org patchwork-forward@linaro.org Delivered-To: patches@linaro.org Received: by 10.112.84.229 with SMTP id c5csp207491lbz; Fri, 31 Oct 2014 07:06:10 -0700 (PDT) X-Received: by 10.194.60.109 with SMTP id g13mr3338900wjr.109.1414764370468; Fri, 31 Oct 2014 07:06:10 -0700 (PDT) Received: from mail-wi0-f175.google.com (mail-wi0-f175.google.com. [209.85.212.175]) by mx.google.com with ESMTPS id pc3si14211570wjb.176.2014.10.31.07.06.10 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Fri, 31 Oct 2014 07:06:10 -0700 (PDT) Received-SPF: pass (google.com: domain of eric.auger@linaro.org designates 209.85.212.175 as permitted sender) client-ip=209.85.212.175; Received: by mail-wi0-f175.google.com with SMTP id ex7so1402750wid.14 for ; Fri, 31 Oct 2014 07:06:10 -0700 (PDT) X-Received: by 10.194.81.70 with SMTP id y6mr2929410wjx.113.1414764370218; Fri, 31 Oct 2014 07:06:10 -0700 (PDT) Received: from midway01-04-00.lavalab ([88.98.47.97]) by mx.google.com with ESMTPSA id v10sm12504563wiy.23.2014.10.31.07.06.09 for (version=TLSv1.1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Fri, 31 Oct 2014 07:06:09 -0700 (PDT) From: Eric Auger To: eric.auger@st.com, christoffer.dall@linaro.org, qemu-devel@nongnu.org, agraf@suse.de, pbonzini@redhat.com, kim.phillips@freescale.com, a.rigo@virtualopensystems.com, manish.jaggi@caviumnetworks.com, joel.schopp@amd.com Cc: eric.auger@linaro.org, kvmarm@lists.cs.columbia.edu, patches@linaro.org, alex.williamson@redhat.com, peter.maydell@linaro.org, will.deacon@arm.com, Bharat.Bhushan@freescale.com, stuart.yoder@freescale.com, a.motakis@virtualopensystems.com Subject: [PATCH v7 04/16] hw/vfio/pci: Introduce VFIORegion Date: Fri, 31 Oct 2014 14:05:38 +0000 Message-Id: <1414764350-5140-5-git-send-email-eric.auger@linaro.org> X-Mailer: git-send-email 1.8.3.2 In-Reply-To: <1414764350-5140-1-git-send-email-eric.auger@linaro.org> References: <1414764350-5140-1-git-send-email-eric.auger@linaro.org> X-Removed-Original-Auth: Dkim didn't pass. X-Original-Sender: eric.auger@linaro.org X-Original-Authentication-Results: mx.google.com; spf=pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.217.174 as permitted sender) smtp.mail=patch+caf_=patchwork-forward=linaro.org@linaro.org Precedence: list Mailing-list: list patchwork-forward@linaro.org; contact patchwork-forward+owners@linaro.org List-ID: X-Google-Group-Id: 836684582541 List-Post: , List-Help: , List-Archive: List-Unsubscribe: , This structure is going to be shared by VFIOPCIDevice and VFIOPlatformDevice. VFIOBAR includes it. vfio_eoi becomes an ops of VFIODevice specialized by parent device. This makes possible to transform vfio_bar_write/read into generic vfio_region_write/read that will be used by VFIOPlatformDevice too. vfio_mmap_bar becomes vfio_map_region Signed-off-by: Eric Auger --- v4->v5: - remove fd field from VFIORegion - change error_report format string in vfio_region_write/read - remove #ifdef DEBUG_VFIO in the same function - correct missing initialization of bar region's vbasedev field - change Object * parameter name of vfio_mmap_region and remove useless OBJECT() Conflicts: hw/vfio/pci.c --- hw/vfio/pci.c | 193 ++++++++++++++++++++++++++++++---------------------------- trace-events | 4 +- 2 files changed, 103 insertions(+), 94 deletions(-) diff --git a/hw/vfio/pci.c b/hw/vfio/pci.c index 0531744..186dfd0 100644 --- a/hw/vfio/pci.c +++ b/hw/vfio/pci.c @@ -78,15 +78,19 @@ typedef struct VFIOQuirk { } data; } VFIOQuirk; -typedef struct VFIOBAR { - off_t fd_offset; /* offset of BAR within device fd */ - int fd; /* device fd, allows us to pass VFIOBAR as opaque data */ +typedef struct VFIORegion { + struct VFIODevice *vbasedev; + off_t fd_offset; /* offset of region within device fd */ MemoryRegion mem; /* slow, read/write access */ MemoryRegion mmap_mem; /* direct mapped access */ void *mmap; size_t size; uint32_t flags; /* VFIO region flags (rd/wr/mmap) */ - uint8_t nr; /* cache the BAR number for debug */ + uint8_t nr; /* cache the region number for debug */ +} VFIORegion; + +typedef struct VFIOBAR { + VFIORegion region; bool ioport; bool mem64; QLIST_HEAD(, VFIOQuirk) quirks; @@ -206,6 +210,7 @@ typedef struct VFIODevice { struct VFIODeviceOps { bool (*vfio_compute_needs_reset)(VFIODevice *vdev); int (*vfio_hot_reset_multi)(VFIODevice *vdev); + void (*vfio_eoi)(VFIODevice *vdev); }; typedef struct VFIOPCIDevice { @@ -389,8 +394,10 @@ static void vfio_intx_interrupt(void *opaque) } } -static void vfio_eoi(VFIOPCIDevice *vdev) +static void vfio_eoi(VFIODevice *vbasedev) { + VFIOPCIDevice *vdev = container_of(vbasedev, VFIOPCIDevice, vbasedev); + if (!vdev->intx.pending) { return; } @@ -400,7 +407,7 @@ static void vfio_eoi(VFIOPCIDevice *vdev) vdev->intx.pending = false; pci_irq_deassert(&vdev->pdev); - vfio_unmask_irqindex(&vdev->vbasedev, VFIO_PCI_INTX_IRQ_INDEX); + vfio_unmask_irqindex(vbasedev, VFIO_PCI_INTX_IRQ_INDEX); } static void vfio_enable_intx_kvm(VFIOPCIDevice *vdev) @@ -553,7 +560,7 @@ static void vfio_update_irq(PCIDevice *pdev) vfio_enable_intx_kvm(vdev); /* Re-enable the interrupt in cased we missed an EOI */ - vfio_eoi(vdev); + vfio_eoi(&vdev->vbasedev); } static int vfio_enable_intx(VFIOPCIDevice *vdev) @@ -1090,10 +1097,11 @@ static void vfio_update_msi(VFIOPCIDevice *vdev) /* * IO Port/MMIO - Beware of the endians, VFIO is always little endian */ -static void vfio_bar_write(void *opaque, hwaddr addr, - uint64_t data, unsigned size) +static void vfio_region_write(void *opaque, hwaddr addr, + uint64_t data, unsigned size) { - VFIOBAR *bar = opaque; + VFIORegion *region = opaque; + VFIODevice *vbasedev = region->vbasedev; union { uint8_t byte; uint16_t word; @@ -1116,20 +1124,14 @@ static void vfio_bar_write(void *opaque, hwaddr addr, break; } - if (pwrite(bar->fd, &buf, size, bar->fd_offset + addr) != size) { - error_report("%s(,0x%"HWADDR_PRIx", 0x%"PRIx64", %d) failed: %m", - __func__, addr, data, size); + if (pwrite(vbasedev->fd, &buf, size, region->fd_offset + addr) != size) { + error_report("%s(%s:region%d+0x%"HWADDR_PRIx", 0x%"PRIx64 + ",%d) failed: %m", + __func__, vbasedev->name, region->nr, + addr, data, size); } -#ifdef DEBUG_VFIO - { - VFIOPCIDevice *vdev = container_of(bar, VFIOPCIDevice, bars[bar->nr]); - - trace_vfio_bar_write(vdev->host.domain, vdev->host.bus, - vdev->host.slot, vdev->host.function, - region->nr, addr, data, size); - } -#endif + trace_vfio_region_write(vbasedev->name, region->nr, addr, data, size); /* * A read or write to a BAR always signals an INTx EOI. This will @@ -1139,13 +1141,14 @@ static void vfio_bar_write(void *opaque, hwaddr addr, * which access will service the interrupt, so we're potentially * getting quite a few host interrupts per guest interrupt. */ - vfio_eoi(container_of(bar, VFIOPCIDevice, bars[bar->nr])); + vbasedev->ops->vfio_eoi(vbasedev); } -static uint64_t vfio_bar_read(void *opaque, - hwaddr addr, unsigned size) +static uint64_t vfio_region_read(void *opaque, + hwaddr addr, unsigned size) { - VFIOBAR *bar = opaque; + VFIORegion *region = opaque; + VFIODevice *vbasedev = region->vbasedev; union { uint8_t byte; uint16_t word; @@ -1154,9 +1157,10 @@ static uint64_t vfio_bar_read(void *opaque, } buf; uint64_t data = 0; - if (pread(bar->fd, &buf, size, bar->fd_offset + addr) != size) { - error_report("%s(,0x%"HWADDR_PRIx", %d) failed: %m", - __func__, addr, size); + if (pread(vbasedev->fd, &buf, size, region->fd_offset + addr) != size) { + error_report("%s(%s:region%d+0x%"HWADDR_PRIx", %d) failed: %m", + __func__, vbasedev->name, region->nr, + addr, size); return (uint64_t)-1; } @@ -1175,25 +1179,17 @@ static uint64_t vfio_bar_read(void *opaque, break; } -#ifdef DEBUG_VFIO - { - VFIOPCIDevice *vdev = container_of(bar, VFIOPCIDevice, bars[bar->nr]); - - trace_vfio_bar_read(vdev->host.domain, vdev->host.bus, - vdev->host.slot, vdev->host.function, - region->nr, addr, size, data); - } -#endif + trace_vfio_region_read(vbasedev->name, region->nr, addr, size, data); /* Same as write above */ - vfio_eoi(container_of(bar, VFIOPCIDevice, bars[bar->nr])); + vbasedev->ops->vfio_eoi(vbasedev); return data; } -static const MemoryRegionOps vfio_bar_ops = { - .read = vfio_bar_read, - .write = vfio_bar_write, +static const MemoryRegionOps vfio_region_ops = { + .read = vfio_region_read, + .write = vfio_region_write, .endianness = DEVICE_LITTLE_ENDIAN, }; @@ -1530,8 +1526,8 @@ static uint64_t vfio_generic_window_quirk_read(void *opaque, quirk->data.bar, addr, size, data); } else { - data = vfio_bar_read(&vdev->bars[quirk->data.bar], - addr + quirk->data.base_offset, size); + data = vfio_region_read(&vdev->bars[quirk->data.bar].region, + addr + quirk->data.base_offset, size); } return data; @@ -1585,7 +1581,7 @@ static void vfio_generic_window_quirk_write(void *opaque, hwaddr addr, return; } - vfio_bar_write(&vdev->bars[quirk->data.bar], + vfio_region_write(&vdev->bars[quirk->data.bar].region, addr + quirk->data.base_offset, data, size); } @@ -1622,7 +1618,8 @@ static uint64_t vfio_generic_quirk_read(void *opaque, quirk->data.bar, addr + base, size, data); } else { - data = vfio_bar_read(&vdev->bars[quirk->data.bar], addr + base, size); + data = vfio_region_read(&vdev->bars[quirk->data.bar].region, + addr + base, size); } return data; @@ -1654,7 +1651,8 @@ static void vfio_generic_quirk_write(void *opaque, hwaddr addr, quirk->data.bar, addr + base, data, size); } else { - vfio_bar_write(&vdev->bars[quirk->data.bar], addr + base, data, size); + vfio_region_write(&vdev->bars[quirk->data.bar].region, + addr + base, data, size); } } @@ -1707,7 +1705,7 @@ static void vfio_vga_probe_ati_3c3_quirk(VFIOPCIDevice *vdev) * As long as the BAR is >= 256 bytes it will be aligned such that the * lower byte is always zero. Filter out anything else, if it exists. */ - if (!vdev->bars[4].ioport || vdev->bars[4].size < 256) { + if (!vdev->bars[4].ioport || vdev->bars[4].region.size < 256) { return; } @@ -1759,7 +1757,7 @@ static void vfio_probe_ati_bar4_window_quirk(VFIOPCIDevice *vdev, int nr) memory_region_init_io(&quirk->mem, OBJECT(vdev), &vfio_generic_window_quirk, quirk, "vfio-ati-bar4-window-quirk", 8); - memory_region_add_subregion_overlap(&vdev->bars[nr].mem, + memory_region_add_subregion_overlap(&vdev->bars[nr].region.mem, quirk->data.base_offset, &quirk->mem, 1); QLIST_INSERT_HEAD(&vdev->bars[nr].quirks, quirk, next); @@ -1838,7 +1836,8 @@ static uint64_t vfio_rtl8168_window_quirk_read(void *opaque, vdev->host.domain, vdev->host.bus, vdev->host.slot, vdev->host.function); - return vfio_bar_read(&vdev->bars[quirk->data.bar], addr + 0x70, size); + return vfio_region_read(&vdev->bars[quirk->data.bar].region, + addr + 0x70, size); } static void vfio_rtl8168_window_quirk_write(void *opaque, hwaddr addr, @@ -1880,7 +1879,8 @@ static void vfio_rtl8168_window_quirk_write(void *opaque, hwaddr addr, vdev->host.domain, vdev->host.bus, vdev->host.slot, vdev->host.function); - vfio_bar_write(&vdev->bars[quirk->data.bar], addr + 0x70, data, size); + vfio_region_write(&vdev->bars[quirk->data.bar].region, + addr + 0x70, data, size); } static const MemoryRegionOps vfio_rtl8168_window_quirk = { @@ -1910,7 +1910,7 @@ static void vfio_probe_rtl8168_bar2_window_quirk(VFIOPCIDevice *vdev, int nr) memory_region_init_io(&quirk->mem, OBJECT(vdev), &vfio_rtl8168_window_quirk, quirk, "vfio-rtl8168-window-quirk", 8); - memory_region_add_subregion_overlap(&vdev->bars[nr].mem, + memory_region_add_subregion_overlap(&vdev->bars[nr].region.mem, 0x70, &quirk->mem, 1); QLIST_INSERT_HEAD(&vdev->bars[nr].quirks, quirk, next); @@ -1944,7 +1944,7 @@ static void vfio_probe_ati_bar2_4000_quirk(VFIOPCIDevice *vdev, int nr) memory_region_init_io(&quirk->mem, OBJECT(vdev), &vfio_generic_quirk, quirk, "vfio-ati-bar2-4000-quirk", TARGET_PAGE_ALIGN(quirk->data.address_mask + 1)); - memory_region_add_subregion_overlap(&vdev->bars[nr].mem, + memory_region_add_subregion_overlap(&vdev->bars[nr].region.mem, quirk->data.address_match & TARGET_PAGE_MASK, &quirk->mem, 1); @@ -2064,7 +2064,7 @@ static void vfio_vga_probe_nvidia_3d0_quirk(VFIOPCIDevice *vdev) VFIOQuirk *quirk; if (pci_get_word(pdev->config + PCI_VENDOR_ID) != PCI_VENDOR_ID_NVIDIA || - !vdev->bars[1].size) { + !vdev->bars[1].region.size) { return; } @@ -2173,7 +2173,8 @@ static void vfio_probe_nvidia_bar5_window_quirk(VFIOPCIDevice *vdev, int nr) memory_region_init_io(&quirk->mem, OBJECT(vdev), &vfio_nvidia_bar5_window_quirk, quirk, "vfio-nvidia-bar5-window-quirk", 16); - memory_region_add_subregion_overlap(&vdev->bars[nr].mem, 0, &quirk->mem, 1); + memory_region_add_subregion_overlap(&vdev->bars[nr].region.mem, + 0, &quirk->mem, 1); QLIST_INSERT_HEAD(&vdev->bars[nr].quirks, quirk, next); @@ -2201,7 +2202,8 @@ static void vfio_nvidia_88000_quirk_write(void *opaque, hwaddr addr, */ if ((pdev->cap_present & QEMU_PCI_CAP_MSI) && vfio_range_contained(addr, size, pdev->msi_cap, PCI_MSI_FLAGS)) { - vfio_bar_write(&vdev->bars[quirk->data.bar], addr + base, data, size); + vfio_region_write(&vdev->bars[quirk->data.bar].region, + addr + base, data, size); } } @@ -2244,7 +2246,7 @@ static void vfio_probe_nvidia_bar0_88000_quirk(VFIOPCIDevice *vdev, int nr) memory_region_init_io(&quirk->mem, OBJECT(vdev), &vfio_nvidia_88000_quirk, quirk, "vfio-nvidia-bar0-88000-quirk", TARGET_PAGE_ALIGN(quirk->data.address_mask + 1)); - memory_region_add_subregion_overlap(&vdev->bars[nr].mem, + memory_region_add_subregion_overlap(&vdev->bars[nr].region.mem, quirk->data.address_match & TARGET_PAGE_MASK, &quirk->mem, 1); @@ -2271,7 +2273,8 @@ static void vfio_probe_nvidia_bar0_1800_quirk(VFIOPCIDevice *vdev, int nr) /* Log the chipset ID */ trace_vfio_probe_nvidia_bar0_1800_quirk_id( - (unsigned int)(vfio_bar_read(&vdev->bars[0], 0, 4) >> 20) & 0xff); + (unsigned int)(vfio_region_read(&vdev->bars[0].region, 0, 4) >> 20) + & 0xff); quirk = g_malloc0(sizeof(*quirk)); quirk->vdev = vdev; @@ -2283,7 +2286,7 @@ static void vfio_probe_nvidia_bar0_1800_quirk(VFIOPCIDevice *vdev, int nr) memory_region_init_io(&quirk->mem, OBJECT(vdev), &vfio_generic_quirk, quirk, "vfio-nvidia-bar0-1800-quirk", TARGET_PAGE_ALIGN(quirk->data.address_mask + 1)); - memory_region_add_subregion_overlap(&vdev->bars[nr].mem, + memory_region_add_subregion_overlap(&vdev->bars[nr].region.mem, quirk->data.address_match & TARGET_PAGE_MASK, &quirk->mem, 1); @@ -2341,7 +2344,7 @@ static void vfio_bar_quirk_teardown(VFIOPCIDevice *vdev, int nr) while (!QLIST_EMPTY(&bar->quirks)) { VFIOQuirk *quirk = QLIST_FIRST(&bar->quirks); - memory_region_del_subregion(&bar->mem, &quirk->mem); + memory_region_del_subregion(&bar->region.mem, &quirk->mem); object_unparent(OBJECT(&quirk->mem)); QLIST_REMOVE(quirk, next); g_free(quirk); @@ -2852,9 +2855,9 @@ static int vfio_setup_msix(VFIOPCIDevice *vdev, int pos) int ret; ret = msix_init(&vdev->pdev, vdev->msix->entries, - &vdev->bars[vdev->msix->table_bar].mem, + &vdev->bars[vdev->msix->table_bar].region.mem, vdev->msix->table_bar, vdev->msix->table_offset, - &vdev->bars[vdev->msix->pba_bar].mem, + &vdev->bars[vdev->msix->pba_bar].region.mem, vdev->msix->pba_bar, vdev->msix->pba_offset, pos); if (ret < 0) { if (ret == -ENOTSUP) { @@ -2872,8 +2875,9 @@ static void vfio_teardown_msi(VFIOPCIDevice *vdev) msi_uninit(&vdev->pdev); if (vdev->msix) { - msix_uninit(&vdev->pdev, &vdev->bars[vdev->msix->table_bar].mem, - &vdev->bars[vdev->msix->pba_bar].mem); + msix_uninit(&vdev->pdev, + &vdev->bars[vdev->msix->table_bar].region.mem, + &vdev->bars[vdev->msix->pba_bar].region.mem); } } @@ -2887,11 +2891,11 @@ static void vfio_mmap_set_enabled(VFIOPCIDevice *vdev, bool enabled) for (i = 0; i < PCI_ROM_SLOT; i++) { VFIOBAR *bar = &vdev->bars[i]; - if (!bar->size) { + if (!bar->region.size) { continue; } - memory_region_set_enabled(&bar->mmap_mem, enabled); + memory_region_set_enabled(&bar->region.mmap_mem, enabled); if (vdev->msix && vdev->msix->table_bar == i) { memory_region_set_enabled(&vdev->msix->mmap_mem, enabled); } @@ -2902,52 +2906,54 @@ static void vfio_unmap_bar(VFIOPCIDevice *vdev, int nr) { VFIOBAR *bar = &vdev->bars[nr]; - if (!bar->size) { + if (!bar->region.size) { return; } vfio_bar_quirk_teardown(vdev, nr); - memory_region_del_subregion(&bar->mem, &bar->mmap_mem); - munmap(bar->mmap, memory_region_size(&bar->mmap_mem)); + memory_region_del_subregion(&bar->region.mem, &bar->region.mmap_mem); + munmap(bar->region.mmap, memory_region_size(&bar->region.mmap_mem)); if (vdev->msix && vdev->msix->table_bar == nr) { - memory_region_del_subregion(&bar->mem, &vdev->msix->mmap_mem); + memory_region_del_subregion(&bar->region.mem, &vdev->msix->mmap_mem); munmap(vdev->msix->mmap, memory_region_size(&vdev->msix->mmap_mem)); } } -static int vfio_mmap_bar(VFIOPCIDevice *vdev, VFIOBAR *bar, - MemoryRegion *mem, MemoryRegion *submem, - void **map, size_t size, off_t offset, - const char *name) +static int vfio_mmap_region(Object *obj, VFIORegion *region, + MemoryRegion *mem, MemoryRegion *submem, + void **map, size_t size, off_t offset, + const char *name) { int ret = 0; + VFIODevice *vbasedev = region->vbasedev; - if (VFIO_ALLOW_MMAP && size && bar->flags & VFIO_REGION_INFO_FLAG_MMAP) { + if (VFIO_ALLOW_MMAP && size && region->flags & + VFIO_REGION_INFO_FLAG_MMAP) { int prot = 0; - if (bar->flags & VFIO_REGION_INFO_FLAG_READ) { + if (region->flags & VFIO_REGION_INFO_FLAG_READ) { prot |= PROT_READ; } - if (bar->flags & VFIO_REGION_INFO_FLAG_WRITE) { + if (region->flags & VFIO_REGION_INFO_FLAG_WRITE) { prot |= PROT_WRITE; } *map = mmap(NULL, size, prot, MAP_SHARED, - bar->fd, bar->fd_offset + offset); + vbasedev->fd, region->fd_offset + offset); if (*map == MAP_FAILED) { *map = NULL; ret = -errno; goto empty_region; } - memory_region_init_ram_ptr(submem, OBJECT(vdev), name, size, *map); + memory_region_init_ram_ptr(submem, obj, name, size, *map); } else { empty_region: /* Create a zero sized sub-region to make cleanup easy. */ - memory_region_init(submem, OBJECT(vdev), name, 0); + memory_region_init(submem, obj, name, 0); } memory_region_add_subregion(mem, offset, submem); @@ -2958,7 +2964,7 @@ empty_region: static void vfio_map_bar(VFIOPCIDevice *vdev, int nr) { VFIOBAR *bar = &vdev->bars[nr]; - unsigned size = bar->size; + unsigned size = bar->region.size; char name[64]; uint32_t pci_bar; uint8_t type; @@ -2988,9 +2994,9 @@ static void vfio_map_bar(VFIOPCIDevice *vdev, int nr) ~PCI_BASE_ADDRESS_MEM_MASK); /* A "slow" read/write mapping underlies all BARs */ - memory_region_init_io(&bar->mem, OBJECT(vdev), &vfio_bar_ops, + memory_region_init_io(&bar->region.mem, OBJECT(vdev), &vfio_region_ops, bar, name, size); - pci_register_bar(&vdev->pdev, nr, type, &bar->mem); + pci_register_bar(&vdev->pdev, nr, type, &bar->region.mem); /* * We can't mmap areas overlapping the MSIX vector table, so we @@ -3001,8 +3007,9 @@ static void vfio_map_bar(VFIOPCIDevice *vdev, int nr) } strncat(name, " mmap", sizeof(name) - strlen(name) - 1); - if (vfio_mmap_bar(vdev, bar, &bar->mem, - &bar->mmap_mem, &bar->mmap, size, 0, name)) { + if (vfio_mmap_region(OBJECT(vdev), &bar->region, &bar->region.mem, + &bar->region.mmap_mem, &bar->region.mmap, + size, 0, name)) { error_report("%s unsupported. Performance may be slow", name); } @@ -3012,10 +3019,11 @@ static void vfio_map_bar(VFIOPCIDevice *vdev, int nr) start = HOST_PAGE_ALIGN(vdev->msix->table_offset + (vdev->msix->entries * PCI_MSIX_ENTRY_SIZE)); - size = start < bar->size ? bar->size - start : 0; + size = start < bar->region.size ? bar->region.size - start : 0; strncat(name, " msix-hi", sizeof(name) - strlen(name) - 1); /* VFIOMSIXInfo contains another MemoryRegion for this mapping */ - if (vfio_mmap_bar(vdev, bar, &bar->mem, &vdev->msix->mmap_mem, + if (vfio_mmap_region(OBJECT(vdev), &bar->region, &bar->region.mem, + &vdev->msix->mmap_mem, &vdev->msix->mmap, size, start, name)) { error_report("%s unsupported. Performance may be slow", name); } @@ -3602,6 +3610,7 @@ static bool vfio_pci_compute_needs_reset(VFIODevice *vbasedev) static VFIODeviceOps vfio_pci_ops = { .vfio_compute_needs_reset = vfio_pci_compute_needs_reset, .vfio_hot_reset_multi = vfio_pci_hot_reset_multi, + .vfio_eoi = vfio_eoi, }; static void vfio_reset_handler(void *opaque) @@ -4006,11 +4015,11 @@ static int vfio_get_device(VFIOGroup *group, const char *name, (unsigned long)reg_info.offset, (unsigned long)reg_info.flags); - vdev->bars[i].flags = reg_info.flags; - vdev->bars[i].size = reg_info.size; - vdev->bars[i].fd_offset = reg_info.offset; - vdev->bars[i].fd = vdev->vbasedev.fd; - vdev->bars[i].nr = i; + vdev->bars[i].region.vbasedev = &vdev->vbasedev; + vdev->bars[i].region.flags = reg_info.flags; + vdev->bars[i].region.size = reg_info.size; + vdev->bars[i].region.fd_offset = reg_info.offset; + vdev->bars[i].region.nr = i; QLIST_INIT(&vdev->bars[i].quirks); } diff --git a/trace-events b/trace-events index edf4be8..b598931 100644 --- a/trace-events +++ b/trace-events @@ -1410,8 +1410,8 @@ vfio_pci_reset(int domain, int bus, int slot, int fn) " (%04x:%02x:%02x.%x)" vfio_pci_reset_flr(int domain, int bus, int slot, int fn) "%04x:%02x:%02x.%x FLR/VFIO_DEVICE_RESET" vfio_pci_reset_pm(int domain, int bus, int slot, int fn) "%04x:%02x:%02x.%x PCI PM Reset" -vfio_bar_write(int domain, int bus, int slot, int fn, int index, uint64_t addr, uint64_t data, unsigned size) " (%04x:%02x:%02x.%x:region%d+0x%"PRIx64", 0x%"PRIx64 ", %d)" -vfio_bar_read(int domain, int bus, int slot, int fn, int index, uint64_t addr, unsigned size, uint64_t data) " (%04x:%02x:%02x.%x:region%d+0x%"PRIx64", %d) = 0x%"PRIx64 +vfio_region_write(const char *name, int index, uint64_t addr, uint64_t data, unsigned size) " (%s:region%d+0x%"PRIx64", 0x%"PRIx64 ", %d)" +vfio_region_read(const char *name, int index, uint64_t addr, unsigned size, uint64_t data) " (%s:region%d+0x%"PRIx64", %d) = 0x%"PRIx64 vfio_iommu_map_notify(uint64_t iova_start, uint64_t iova_end) "iommu map @ %"PRIx64" - %"PRIx64 vfio_listener_region_add_skip(uint64_t start, uint64_t end) "SKIPPING region_add %"PRIx64" - %"PRIx64 vfio_listener_region_add_iommu(uint64_t start, uint64_t end) "region_add [iommu] %"PRIx64" - %"PRIx64