From nobody Tue Feb 10 19:48:00 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1508038755588452.5985091895799; Sat, 14 Oct 2017 20:39:15 -0700 (PDT) Received: from localhost ([::1]:56017 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1e3Zlc-0006WT-31 for importer@patchew.org; Sat, 14 Oct 2017 23:39:08 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:49363) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1e3ZX3-00035n-Lq for qemu-devel@nongnu.org; Sat, 14 Oct 2017 23:24:07 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1e3ZX2-0007Cr-30 for qemu-devel@nongnu.org; Sat, 14 Oct 2017 23:24:05 -0400 Received: from mx1.redhat.com ([209.132.183.28]:60618) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1e3ZX1-0007CM-PZ for qemu-devel@nongnu.org; Sat, 14 Oct 2017 23:24:04 -0400 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 2A382369C4; Sun, 15 Oct 2017 03:24:02 +0000 (UTC) Received: from redhat.com (ovpn-120-178.rdu2.redhat.com [10.10.120.178]) by smtp.corp.redhat.com (Postfix) with SMTP id 075DB61F40; Sun, 15 Oct 2017 03:24:00 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com 2A382369C4 Authentication-Results: ext-mx06.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx06.extmail.prod.ext.phx2.redhat.com; spf=fail smtp.mailfrom=mst@redhat.com Date: Sun, 15 Oct 2017 06:24:00 +0300 From: "Michael S. Tsirkin" To: qemu-devel@nongnu.org Message-ID: <1508036858-13479-24-git-send-email-mst@redhat.com> References: <1508036858-13479-1-git-send-email-mst@redhat.com> MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: <1508036858-13479-1-git-send-email-mst@redhat.com> X-Mutt-Fcc: =sent X-Scanned-By: MIMEDefang 2.79 on 10.5.11.15 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.30]); Sun, 15 Oct 2017 03:24:03 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PULL 23/26] virtio-pci: Replace modern_as with direct access to modern_bar X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Alexey Kardashevskiy , Peter Maydell Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Alexey Kardashevskiy The modern bar is accessed now via yet another address space created just for that purpose and it does not really need FlatView and dispatch tree as it has a single memory region so it is just a waste of memory. Things get even worse when there are dozens or hundreds of virtio-pci devices - since these address spaces are global, changing any of them triggers rebuilding all address spaces. This replaces indirect accesses to the modern BAR with a simple lookup and direct calls to memory_region_dispatch_read/write. This is expected to save lots of memory at boot time after applying: [Qemu-devel] [PULL 00/32] Misc changes for 2017-09-22 Signed-off-by: Alexey Kardashevskiy Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/virtio/virtio-pci.h | 17 +++++++----- hw/virtio/virtio-pci.c | 75 +++++++++++++++++++++++++++++-----------------= ---- 2 files changed, 54 insertions(+), 38 deletions(-) diff --git a/hw/virtio/virtio-pci.h b/hw/virtio/virtio-pci.h index 69f5959..12d3a90 100644 --- a/hw/virtio/virtio-pci.h +++ b/hw/virtio/virtio-pci.h @@ -155,15 +155,18 @@ typedef struct VirtIOPCIQueue { struct VirtIOPCIProxy { PCIDevice pci_dev; MemoryRegion bar; - VirtIOPCIRegion common; - VirtIOPCIRegion isr; - VirtIOPCIRegion device; - VirtIOPCIRegion notify; - VirtIOPCIRegion notify_pio; + union { + struct { + VirtIOPCIRegion common; + VirtIOPCIRegion isr; + VirtIOPCIRegion device; + VirtIOPCIRegion notify; + VirtIOPCIRegion notify_pio; + }; + VirtIOPCIRegion regs[5]; + }; MemoryRegion modern_bar; MemoryRegion io_bar; - MemoryRegion modern_cfg; - AddressSpace modern_as; uint32_t legacy_io_bar_idx; uint32_t msix_bar_idx; uint32_t modern_io_bar_idx; diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c index 6c60aa0..e92837c 100644 --- a/hw/virtio/virtio-pci.c +++ b/hw/virtio/virtio-pci.c @@ -491,6 +491,24 @@ static const MemoryRegionOps virtio_pci_config_ops =3D= { .endianness =3D DEVICE_LITTLE_ENDIAN, }; =20 +static MemoryRegion *virtio_address_space_lookup(VirtIOPCIProxy *proxy, + hwaddr *off, int len) +{ + int i; + VirtIOPCIRegion *reg; + + for (i =3D 0; i < ARRAY_SIZE(proxy->regs); ++i) { + reg =3D &proxy->regs[i]; + if (*off >=3D reg->offset && + *off + len <=3D reg->offset + reg->size) { + *off -=3D reg->offset; + return ®->mr; + } + } + + return NULL; +} + /* Below are generic functions to do memcpy from/to an address space, * without byteswaps, with input validation. * @@ -504,63 +522,72 @@ static const MemoryRegionOps virtio_pci_config_ops = =3D { * Note: host pointer must be aligned. */ static -void virtio_address_space_write(AddressSpace *as, hwaddr addr, +void virtio_address_space_write(VirtIOPCIProxy *proxy, hwaddr addr, const uint8_t *buf, int len) { - uint32_t val; + uint64_t val; + MemoryRegion *mr; =20 /* address_space_* APIs assume an aligned address. * As address is under guest control, handle illegal values. */ addr &=3D ~(len - 1); =20 + mr =3D virtio_address_space_lookup(proxy, &addr, len); + if (!mr) { + return; + } + /* Make sure caller aligned buf properly */ assert(!(((uintptr_t)buf) & (len - 1))); =20 switch (len) { case 1: val =3D pci_get_byte(buf); - address_space_stb(as, addr, val, MEMTXATTRS_UNSPECIFIED, NULL); break; case 2: - val =3D pci_get_word(buf); - address_space_stw_le(as, addr, val, MEMTXATTRS_UNSPECIFIED, NULL); + val =3D cpu_to_le16(pci_get_word(buf)); break; case 4: - val =3D pci_get_long(buf); - address_space_stl_le(as, addr, val, MEMTXATTRS_UNSPECIFIED, NULL); + val =3D cpu_to_le32(pci_get_long(buf)); break; default: /* As length is under guest control, handle illegal values. */ - break; + return; } + memory_region_dispatch_write(mr, addr, val, len, MEMTXATTRS_UNSPECIFIE= D); } =20 static void -virtio_address_space_read(AddressSpace *as, hwaddr addr, uint8_t *buf, int= len) +virtio_address_space_read(VirtIOPCIProxy *proxy, hwaddr addr, + uint8_t *buf, int len) { - uint32_t val; + uint64_t val; + MemoryRegion *mr; =20 /* address_space_* APIs assume an aligned address. * As address is under guest control, handle illegal values. */ addr &=3D ~(len - 1); =20 + mr =3D virtio_address_space_lookup(proxy, &addr, len); + if (!mr) { + return; + } + /* Make sure caller aligned buf properly */ assert(!(((uintptr_t)buf) & (len - 1))); =20 + memory_region_dispatch_read(mr, addr, &val, len, MEMTXATTRS_UNSPECIFIE= D); switch (len) { case 1: - val =3D address_space_ldub(as, addr, MEMTXATTRS_UNSPECIFIED, NULL); pci_set_byte(buf, val); break; case 2: - val =3D address_space_lduw_le(as, addr, MEMTXATTRS_UNSPECIFIED, NU= LL); - pci_set_word(buf, val); + pci_set_word(buf, le16_to_cpu(val)); break; case 4: - val =3D address_space_ldl_le(as, addr, MEMTXATTRS_UNSPECIFIED, NUL= L); - pci_set_long(buf, val); + pci_set_long(buf, le32_to_cpu(val)); break; default: /* As length is under guest control, handle illegal values. */ @@ -596,8 +623,7 @@ static void virtio_write_config(PCIDevice *pci_dev, uin= t32_t address, =20 if (len =3D=3D 1 || len =3D=3D 2 || len =3D=3D 4) { assert(len <=3D sizeof cfg->pci_cfg_data); - virtio_address_space_write(&proxy->modern_as, off, - cfg->pci_cfg_data, len); + virtio_address_space_write(proxy, off, cfg->pci_cfg_data, len); } } } @@ -621,8 +647,7 @@ static uint32_t virtio_read_config(PCIDevice *pci_dev, =20 if (len =3D=3D 1 || len =3D=3D 2 || len =3D=3D 4) { assert(len <=3D sizeof cfg->pci_cfg_data); - virtio_address_space_read(&proxy->modern_as, off, - cfg->pci_cfg_data, len); + virtio_address_space_read(proxy, off, cfg->pci_cfg_data, len); } } =20 @@ -1729,15 +1754,6 @@ static void virtio_pci_realize(PCIDevice *pci_dev, E= rror **errp) /* PCI BAR regions must be powers of 2 */ pow2ceil(proxy->notify.offset + proxy->notify.size)= ); =20 - memory_region_init_alias(&proxy->modern_cfg, - OBJECT(proxy), - "virtio-pci-cfg", - &proxy->modern_bar, - 0, - memory_region_size(&proxy->modern_bar)); - - address_space_init(&proxy->modern_as, &proxy->modern_cfg, "virtio-pci-= cfg-as"); - if (proxy->disable_legacy =3D=3D ON_OFF_AUTO_AUTO) { proxy->disable_legacy =3D pcie_port ? ON_OFF_AUTO_ON : ON_OFF_AUTO= _OFF; } @@ -1806,10 +1822,7 @@ static void virtio_pci_realize(PCIDevice *pci_dev, E= rror **errp) =20 static void virtio_pci_exit(PCIDevice *pci_dev) { - VirtIOPCIProxy *proxy =3D VIRTIO_PCI(pci_dev); - msix_uninit_exclusive_bar(pci_dev); - address_space_destroy(&proxy->modern_as); } =20 static void virtio_pci_reset(DeviceState *qdev) --=20 MST