From nobody Thu May 2 09:40:29 2024 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 1506093302031803.0527192769497; Fri, 22 Sep 2017 08:15:02 -0700 (PDT) Received: from localhost ([::1]:59407 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dvPfL-0004Ui-PR for importer@patchew.org; Fri, 22 Sep 2017 11:14:55 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:51489) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dvPcp-0002Tu-WE for qemu-devel@nongnu.org; Fri, 22 Sep 2017 11:12:21 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1dvPcl-0005B1-Bc for qemu-devel@nongnu.org; Fri, 22 Sep 2017 11:12:19 -0400 Received: from ozlabs.ru ([107.173.13.209]:50070) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dvPcl-0005Ab-1q for qemu-devel@nongnu.org; Fri, 22 Sep 2017 11:12:15 -0400 Received: from vpl1.ozlabs.ibm.com (localhost [IPv6:::1]) by ozlabs.ru (Postfix) with ESMTP id C11993A60027; Fri, 22 Sep 2017 11:13:28 -0400 (EDT) From: Alexey Kardashevskiy To: qemu-devel@nongnu.org Date: Sat, 23 Sep 2017 01:12:08 +1000 Message-Id: <20170922151208.24590-1-aik@ozlabs.ru> X-Mailer: git-send-email 2.11.0 X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x [fuzzy] X-Received-From: 107.173.13.209 Subject: [Qemu-devel] [RFC PATCH qemu] 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 , Paolo Bonzini , "Michael S. Tsirkin" 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 MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" 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 --- What is the easiest way to test it? Git history suggests that only SeaBIOS supports this, is this still correct? What is best to do if MR is not found (and is it possible in practice)? assert or redirect to unassigned memory? --- hw/virtio/virtio-pci.h | 17 +++++++----- hw/virtio/virtio-pci.c | 71 ++++++++++++++++++++++++++++------------------= ---- 2 files changed, 50 insertions(+), 38 deletions(-) diff --git a/hw/virtio/virtio-pci.h b/hw/virtio/virtio-pci.h index 69f5959623..12d3a90686 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 8b0d6b69cd..0fcb8589f7 100644 --- a/hw/virtio/virtio-pci.c +++ b/hw/virtio/virtio-pci.c @@ -545,6 +545,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. * @@ -558,63 +576,68 @@ 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); + assert(mr); + /* 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); + assert(mr); + /* 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. */ @@ -650,8 +673,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); } } } @@ -675,8 +697,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 @@ -1783,15 +1804,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; } @@ -1860,10 +1872,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 2.11.0