From nobody Sat Apr 27 20:51: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 1504776175631277.1734922083475; Thu, 7 Sep 2017 02:22:55 -0700 (PDT) Received: from localhost ([::1]:39517 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dpt1S-0002fT-HT for importer@patchew.org; Thu, 07 Sep 2017 05:22:54 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:57239) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dpszZ-0001Fa-Ci for qemu-devel@nongnu.org; Thu, 07 Sep 2017 05:21:02 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1dpszU-0007ev-QZ for qemu-devel@nongnu.org; Thu, 07 Sep 2017 05:20:57 -0400 Received: from ozlabs.ru ([107.173.13.209]:51572) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dpszU-0007e8-Kl for qemu-devel@nongnu.org; Thu, 07 Sep 2017 05:20:52 -0400 Received: from vpl1.ozlabs.ibm.com (localhost [IPv6:::1]) by ozlabs.ru (Postfix) with ESMTP id 21F1E3A60027; Thu, 7 Sep 2017 05:21:31 -0400 (EDT) From: Alexey Kardashevskiy To: qemu-devel@nongnu.org Date: Thu, 7 Sep 2017 19:20:07 +1000 Message-Id: <20170907092010.3605-2-aik@ozlabs.ru> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20170907092010.3605-1-aik@ozlabs.ru> References: <20170907092010.3605-1-aik@ozlabs.ru> 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 1/4] memory: Postpone flatview and dispatch tree building till all devices are added 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 , Stefan Hajnoczi , Peter Maydell , David Gibson 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" Most devices use at least one address space and every time a new address space is added, flat views and dispatch trees are rebuild for all address spaces. This is not a problem for a relatively small amount of devices but even 50 virtio-pci devices use more than 8GB of RAM. What happens that on every flatview/dispatch rebuild, new arrays are allocated and old ones release but the release is done via RCU so until an entire machine is build, they are not released. This wraps devices creation into memory_region_transaction_begin/commit to massively reduce amount of flat view/dispatch tree (re)allocations. Signed-off-by: Alexey Kardashevskiy --- vl.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/vl.c b/vl.c index 8e247cc2a2..3c39cc8b3a 100644 --- a/vl.c +++ b/vl.c @@ -4655,12 +4655,16 @@ int main(int argc, char **argv, char **envp) igd_gfx_passthru(); =20 /* init generic devices */ + memory_region_transaction_begin(); + rom_set_order_override(FW_CFG_ORDER_OVERRIDE_DEVICE); if (qemu_opts_foreach(qemu_find_opts("device"), device_init_func, NULL, NULL)) { exit(1); } =20 + memory_region_transaction_commit(); + cpu_synchronize_all_post_init(); =20 rom_reset_order_override(); --=20 2.11.0 From nobody Sat Apr 27 20:51: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 1504776378646381.7265317960122; Thu, 7 Sep 2017 02:26:18 -0700 (PDT) Received: from localhost ([::1]:39530 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dpt4j-0005N1-BS for importer@patchew.org; Thu, 07 Sep 2017 05:26:17 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:57253) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dpsza-0001Gn-Si for qemu-devel@nongnu.org; Thu, 07 Sep 2017 05:21:06 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1dpszW-0007iX-Tq for qemu-devel@nongnu.org; Thu, 07 Sep 2017 05:20:58 -0400 Received: from ozlabs.ru ([107.173.13.209]:51582) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dpszW-0007gt-CV for qemu-devel@nongnu.org; Thu, 07 Sep 2017 05:20:54 -0400 Received: from vpl1.ozlabs.ibm.com (localhost [IPv6:::1]) by ozlabs.ru (Postfix) with ESMTP id F19BA3A604CE; Thu, 7 Sep 2017 05:21:33 -0400 (EDT) From: Alexey Kardashevskiy To: qemu-devel@nongnu.org Date: Thu, 7 Sep 2017 19:20:08 +1000 Message-Id: <20170907092010.3605-3-aik@ozlabs.ru> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20170907092010.3605-1-aik@ozlabs.ru> References: <20170907092010.3605-1-aik@ozlabs.ru> 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 2/4] memory: Prepare for shared flat views 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 , Stefan Hajnoczi , Peter Maydell , David Gibson 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" We are going to share flat views and dispatch trees between address spaces. This moves bits around but no change in behaviour is expected here. The following patch will implement sharing. This switches from AddressSpace to AddressSpaceDispatch as in many places this is what is used actually. Also, since multiple address spaces will be sharing a flat view, MemoryRegionSection cannot store the address space pointer, this changes it to AddressSpaceDispatch as well. As a not very obvious result, IOMMUTLBEntry also switched from AddressSpace to AddressSpaceDispatch to make address_space_get_iotlb_entry() work. Signed-off-by: Alexey Kardashevskiy --- include/exec/memory.h | 79 +++++++++++++++++++++++------- exec.c | 128 +++++++++++++++++++++++++++-----------------= ---- hw/alpha/typhoon.c | 2 +- hw/dma/rc4030.c | 4 +- hw/i386/amd_iommu.c | 2 +- hw/i386/intel_iommu.c | 9 ++-- hw/intc/openpic_kvm.c | 2 +- hw/pci-host/apb.c | 2 +- hw/ppc/spapr_iommu.c | 4 +- hw/s390x/s390-pci-bus.c | 2 +- hw/vfio/common.c | 6 +-- hw/virtio/vhost.c | 6 +-- memory.c | 26 ++++++---- 13 files changed, 170 insertions(+), 102 deletions(-) diff --git a/include/exec/memory.h b/include/exec/memory.h index 400dd4491b..83e82e90d5 100644 --- a/include/exec/memory.h +++ b/include/exec/memory.h @@ -48,6 +48,7 @@ =20 typedef struct MemoryRegionOps MemoryRegionOps; typedef struct MemoryRegionMmio MemoryRegionMmio; +typedef struct AddressSpaceDispatch AddressSpaceDispatch; =20 struct MemoryRegionMmio { CPUReadMemoryFunc *read[3]; @@ -67,7 +68,7 @@ typedef enum { #define IOMMU_ACCESS_FLAG(r, w) (((r) ? IOMMU_RO : 0) | ((w) ? IOMMU_WO : = 0)) =20 struct IOMMUTLBEntry { - AddressSpace *target_as; + AddressSpaceDispatch *target_dispatch; hwaddr iova; hwaddr translated_addr; hwaddr addr_mask; /* 0xfff =3D 4k translation */ @@ -310,6 +311,8 @@ struct MemoryListener { QTAILQ_ENTRY(MemoryListener) link_as; }; =20 +AddressSpaceDispatch *address_space_to_dispatch(AddressSpace *as); + /** * AddressSpace: describes a mapping of addresses to #MemoryRegion objects */ @@ -346,7 +349,7 @@ struct AddressSpace { */ struct MemoryRegionSection { MemoryRegion *mr; - AddressSpace *address_space; + AddressSpaceDispatch *dispatch; hwaddr offset_within_region; Int128 size; hwaddr offset_within_address_space; @@ -1635,10 +1638,19 @@ void address_space_destroy(AddressSpace *as); * @buf: buffer with the data transferred * @is_write: indicates the transfer direction */ -MemTxResult address_space_rw(AddressSpace *as, hwaddr addr, +MemTxResult address_space_dispatch_rw(AddressSpaceDispatch *d, hwaddr addr, MemTxAttrs attrs, uint8_t *buf, int len, bool is_write); =20 +static inline MemTxResult address_space_rw(AddressSpace *as, hwaddr addr, + MemTxAttrs attrs, uint8_t *buf, + int len, bool is_write) +{ + return address_space_dispatch_rw(address_space_to_dispatch(as), + addr, attrs, buf, len, is_write); +} + + /** * address_space_write: write to address space. * @@ -1651,10 +1663,18 @@ MemTxResult address_space_rw(AddressSpace *as, hwad= dr addr, * @attrs: memory transaction attributes * @buf: buffer with the data transferred */ -MemTxResult address_space_write(AddressSpace *as, hwaddr addr, +MemTxResult address_space_dispatch_write(AddressSpaceDispatch *d, hwaddr a= ddr, MemTxAttrs attrs, const uint8_t *buf, int len); =20 +static inline MemTxResult address_space_write(AddressSpace *as, hwaddr add= r, + MemTxAttrs attrs, + const uint8_t *buf, int len) +{ + return address_space_dispatch_write(address_space_to_dispatch(as), + addr, attrs, buf, len); +} + /* address_space_ld*: load from an address space * address_space_st*: store to an address space * @@ -1840,8 +1860,8 @@ void stq_be_phys_cached(MemoryRegionCache *cache, hwa= ddr addr, uint64_t val); /* address_space_get_iotlb_entry: translate an address into an IOTLB * entry. Should be called from an RCU critical section. */ -IOMMUTLBEntry address_space_get_iotlb_entry(AddressSpace *as, hwaddr addr, - bool is_write); +IOMMUTLBEntry address_space_get_iotlb_entry(AddressSpaceDispatch *d, + hwaddr addr, bool is_write); =20 /* address_space_translate: translate an address range into an address spa= ce * into a MemoryRegion and an address range into that section. Should be @@ -1855,9 +1875,17 @@ IOMMUTLBEntry address_space_get_iotlb_entry(AddressS= pace *as, hwaddr addr, * @len: pointer to length * @is_write: indicates the transfer direction */ -MemoryRegion *address_space_translate(AddressSpace *as, hwaddr addr, - hwaddr *xlat, hwaddr *len, - bool is_write); +MemoryRegion *address_space_dispatch_translate(AddressSpaceDispatch *d, + hwaddr addr, hwaddr *xlat, + hwaddr *len, bool is_write); + +static inline MemoryRegion *address_space_translate(AddressSpace *as, + hwaddr addr, hwaddr *x= lat, + hwaddr *len, bool is_w= rite) +{ + return address_space_dispatch_translate(address_space_to_dispatch(as), + addr, xlat, len, is_write); +} =20 /* address_space_access_valid: check for validity of accessing an address * space range @@ -1874,7 +1902,15 @@ MemoryRegion *address_space_translate(AddressSpace *= as, hwaddr addr, * @len: length of the area to be checked * @is_write: indicates the transfer direction */ -bool address_space_access_valid(AddressSpace *as, hwaddr addr, int len, bo= ol is_write); +bool address_space_dispatch_access_valid(AddressSpaceDispatch *d, hwaddr a= ddr, + int len, bool is_write); + +static inline bool address_space_access_valid(AddressSpace *as, hwaddr add= r, + int len, bool is_write) +{ + return address_space_dispatch_access_valid(address_space_to_dispatch(a= s), + addr, len, is_write); +} =20 /* address_space_map: map a physical memory region into a host virtual add= ress * @@ -1908,11 +1944,11 @@ void address_space_unmap(AddressSpace *as, void *bu= ffer, hwaddr len, =20 =20 /* Internal functions, part of the implementation of address_space_read. = */ -MemTxResult address_space_read_continue(AddressSpace *as, hwaddr addr, +MemTxResult address_space_read_continue(AddressSpaceDispatch *d, hwaddr ad= dr, MemTxAttrs attrs, uint8_t *buf, int len, hwaddr addr1, hwaddr l, MemoryRegion *mr); -MemTxResult address_space_read_full(AddressSpace *as, hwaddr addr, +MemTxResult address_space_read_full(AddressSpaceDispatch *d, hwaddr addr, MemTxAttrs attrs, uint8_t *buf, int le= n); void *qemu_map_ram_ptr(RAMBlock *ram_block, ram_addr_t addr); =20 @@ -1940,8 +1976,9 @@ static inline bool memory_access_is_direct(MemoryRegi= on *mr, bool is_write) * @buf: buffer with the data transferred */ static inline __attribute__((__always_inline__)) -MemTxResult address_space_read(AddressSpace *as, hwaddr addr, MemTxAttrs a= ttrs, - uint8_t *buf, int len) +MemTxResult address_space_dispatch_read(AddressSpaceDispatch *d, hwaddr ad= dr, + MemTxAttrs attrs, uint8_t *buf, + int len) { MemTxResult result =3D MEMTX_OK; hwaddr l, addr1; @@ -1952,22 +1989,30 @@ MemTxResult address_space_read(AddressSpace *as, hw= addr addr, MemTxAttrs attrs, if (len) { rcu_read_lock(); l =3D len; - mr =3D address_space_translate(as, addr, &addr1, &l, false); + mr =3D address_space_dispatch_translate(d, addr, &addr1, &l, f= alse); if (len =3D=3D l && memory_access_is_direct(mr, false)) { ptr =3D qemu_map_ram_ptr(mr->ram_block, addr1); memcpy(buf, ptr, len); } else { - result =3D address_space_read_continue(as, addr, attrs, bu= f, len, + result =3D address_space_read_continue(d, addr, attrs, buf= , len, addr1, l, mr); } rcu_read_unlock(); } } else { - result =3D address_space_read_full(as, addr, attrs, buf, len); + result =3D address_space_read_full(d, addr, attrs, buf, len); } return result; } =20 +static inline MemTxResult address_space_read(AddressSpace *as, hwaddr addr, + MemTxAttrs attrs, uint8_t *bu= f, + int len) +{ + return address_space_dispatch_read(address_space_to_dispatch(as), + addr, attrs, buf, len); +} + /** * address_space_read_cached: read from a cached RAM region * diff --git a/exec.c b/exec.c index d20c34ca83..66f01f5fce 100644 --- a/exec.c +++ b/exec.c @@ -199,10 +199,12 @@ struct AddressSpaceDispatch { AddressSpace *as; }; =20 +typedef struct AddressSpaceDispatch AddressSpaceDispatch; + #define SUBPAGE_IDX(addr) ((addr) & ~TARGET_PAGE_MASK) typedef struct subpage_t { MemoryRegion iomem; - AddressSpace *as; + AddressSpaceDispatch *d; hwaddr base; uint16_t sub_section[]; } subpage_t; @@ -238,6 +240,11 @@ struct DirtyBitmapSnapshot { unsigned long dirty[]; }; =20 +AddressSpaceDispatch *address_space_to_dispatch(AddressSpace *as) +{ + return atomic_rcu_read(&as->dispatch); +} + #endif =20 #if !defined(CONFIG_USER_ONLY) @@ -437,8 +444,9 @@ static MemoryRegionSection *address_space_lookup_region= (AddressSpaceDispatch *d, =20 /* Called from RCU critical section */ static MemoryRegionSection * -address_space_translate_internal(AddressSpaceDispatch *d, hwaddr addr, hwa= ddr *xlat, - hwaddr *plen, bool resolve_subpage) +address_space_translate_internal(AddressSpaceDispatch *d, hwaddr addr, + hwaddr *xlat, hwaddr *plen, + bool resolve_subpage) { MemoryRegionSection *section; MemoryRegion *mr; @@ -472,7 +480,7 @@ address_space_translate_internal(AddressSpaceDispatch *= d, hwaddr addr, hwaddr *x } =20 /* Called from RCU critical section */ -static MemoryRegionSection address_space_do_translate(AddressSpace *as, +static MemoryRegionSection address_space_do_translate(AddressSpaceDispatch= *d, hwaddr addr, hwaddr *xlat, hwaddr *plen, @@ -485,8 +493,8 @@ static MemoryRegionSection address_space_do_translate(A= ddressSpace *as, IOMMUMemoryRegionClass *imrc; =20 for (;;) { - AddressSpaceDispatch *d =3D atomic_rcu_read(&as->dispatch); - section =3D address_space_translate_internal(d, addr, &addr, plen,= is_mmio); + section =3D address_space_translate_internal(d, addr, &addr, + plen, is_mmio); =20 iommu_mr =3D memory_region_get_iommu(section->mr); if (!iommu_mr) { @@ -503,7 +511,7 @@ static MemoryRegionSection address_space_do_translate(A= ddressSpace *as, goto translate_fail; } =20 - as =3D iotlb.target_as; + d =3D atomic_rcu_read(&iotlb.target_dispatch); } =20 *xlat =3D addr; @@ -515,8 +523,8 @@ translate_fail: } =20 /* Called from RCU critical section */ -IOMMUTLBEntry address_space_get_iotlb_entry(AddressSpace *as, hwaddr addr, - bool is_write) +IOMMUTLBEntry address_space_get_iotlb_entry(AddressSpaceDispatch *d, + hwaddr addr, bool is_write) { MemoryRegionSection section; hwaddr xlat, plen; @@ -525,7 +533,7 @@ IOMMUTLBEntry address_space_get_iotlb_entry(AddressSpac= e *as, hwaddr addr, plen =3D (hwaddr)-1; =20 /* This can never be MMIO. */ - section =3D address_space_do_translate(as, addr, &xlat, &plen, + section =3D address_space_do_translate(d, addr, &xlat, &plen, is_write, false); =20 /* Illegal translation */ @@ -549,7 +557,7 @@ IOMMUTLBEntry address_space_get_iotlb_entry(AddressSpac= e *as, hwaddr addr, plen -=3D 1; =20 return (IOMMUTLBEntry) { - .target_as =3D section.address_space, + .target_dispatch =3D section.dispatch, .iova =3D addr & ~plen, .translated_addr =3D xlat & ~plen, .addr_mask =3D plen, @@ -562,15 +570,15 @@ iotlb_fail: } =20 /* Called from RCU critical section */ -MemoryRegion *address_space_translate(AddressSpace *as, hwaddr addr, - hwaddr *xlat, hwaddr *plen, - bool is_write) +MemoryRegion *address_space_dispatch_translate(AddressSpaceDispatch *d, + hwaddr addr, hwaddr *xlat, + hwaddr *plen, bool is_write) { MemoryRegion *mr; MemoryRegionSection section; =20 /* This can be MMIO, so setup MMIO bit. */ - section =3D address_space_do_translate(as, addr, xlat, plen, is_write,= true); + section =3D address_space_do_translate(d, addr, xlat, plen, is_write, = true); mr =3D section.mr; =20 if (xen_enabled() && memory_access_is_direct(mr, is_write)) { @@ -587,7 +595,8 @@ address_space_translate_for_iotlb(CPUState *cpu, int as= idx, hwaddr addr, hwaddr *xlat, hwaddr *plen) { MemoryRegionSection *section; - AddressSpaceDispatch *d =3D atomic_rcu_read(&cpu->cpu_ases[asidx].memo= ry_dispatch); + AddressSpaceDispatch *d =3D + atomic_rcu_read(&cpu->cpu_ases[asidx].memory_dispatch); =20 section =3D address_space_translate_internal(d, addr, xlat, plen, fals= e); =20 @@ -1220,7 +1229,7 @@ hwaddr memory_region_section_get_iotlb(CPUState *cpu, } else { AddressSpaceDispatch *d; =20 - d =3D atomic_rcu_read(§ion->address_space->dispatch); + d =3D atomic_rcu_read(§ion->dispatch); iotlb =3D section - d->map.sections; iotlb +=3D xlat; } @@ -1246,7 +1255,7 @@ hwaddr memory_region_section_get_iotlb(CPUState *cpu, =20 static int subpage_register (subpage_t *mmio, uint32_t start, uint32_t end, uint16_t section); -static subpage_t *subpage_init(AddressSpace *as, hwaddr base); +static subpage_t *subpage_init(AddressSpaceDispatch *d, hwaddr base); =20 static void *(*phys_mem_alloc)(size_t size, uint64_t *align) =3D qemu_anon_ram_alloc; @@ -1318,8 +1327,8 @@ static void register_subpage(AddressSpaceDispatch *d,= MemoryRegionSection *secti assert(existing->mr->subpage || existing->mr =3D=3D &io_mem_unassigned= ); =20 if (!(existing->mr->subpage)) { - subpage =3D subpage_init(d->as, base); - subsection.address_space =3D d->as; + subpage =3D subpage_init(d, base); + subsection.dispatch =3D d; subsection.mr =3D &subpage->iomem; phys_page_set(d, base >> TARGET_PAGE_BITS, 1, phys_section_add(&d->map, &subsection)); @@ -2512,7 +2521,7 @@ static MemTxResult subpage_read(void *opaque, hwaddr = addr, uint64_t *data, printf("%s: subpage %p len %u addr " TARGET_FMT_plx "\n", __func__, subpage, len, addr); #endif - res =3D address_space_read(subpage->as, addr + subpage->base, + res =3D address_space_dispatch_read(subpage->d, addr + subpage->base, attrs, buf, len); if (res) { return res; @@ -2562,7 +2571,7 @@ static MemTxResult subpage_write(void *opaque, hwaddr= addr, default: abort(); } - return address_space_write(subpage->as, addr + subpage->base, + return address_space_dispatch_write(subpage->d, addr + subpage->base, attrs, buf, len); } =20 @@ -2575,8 +2584,8 @@ static bool subpage_accepts(void *opaque, hwaddr addr, __func__, subpage, is_write ? 'w' : 'r', len, addr); #endif =20 - return address_space_access_valid(subpage->as, addr + subpage->base, - len, is_write); + return address_space_dispatch_access_valid(subpage->d, addr + subpage-= >base, + len, is_write); } =20 static const MemoryRegionOps subpage_ops =3D { @@ -2610,12 +2619,12 @@ static int subpage_register (subpage_t *mmio, uint3= 2_t start, uint32_t end, return 0; } =20 -static subpage_t *subpage_init(AddressSpace *as, hwaddr base) +static subpage_t *subpage_init(AddressSpaceDispatch *d, hwaddr base) { subpage_t *mmio; =20 mmio =3D g_malloc0(sizeof(subpage_t) + TARGET_PAGE_SIZE * sizeof(uint1= 6_t)); - mmio->as =3D as; + mmio->d =3D d; mmio->base =3D base; memory_region_init_io(&mmio->iomem, NULL, &subpage_ops, mmio, NULL, TARGET_PAGE_SIZE); @@ -2629,12 +2638,12 @@ static subpage_t *subpage_init(AddressSpace *as, hw= addr base) return mmio; } =20 -static uint16_t dummy_section(PhysPageMap *map, AddressSpace *as, +static uint16_t dummy_section(PhysPageMap *map, AddressSpaceDispatch *d, MemoryRegion *mr) { - assert(as); + assert(d); MemoryRegionSection section =3D { - .address_space =3D as, + .dispatch =3D d, .mr =3D mr, .offset_within_address_space =3D 0, .offset_within_region =3D 0, @@ -2677,17 +2686,16 @@ static void mem_begin(MemoryListener *listener) AddressSpaceDispatch *d =3D g_new0(AddressSpaceDispatch, 1); uint16_t n; =20 - n =3D dummy_section(&d->map, as, &io_mem_unassigned); + n =3D dummy_section(&d->map, d, &io_mem_unassigned); assert(n =3D=3D PHYS_SECTION_UNASSIGNED); - n =3D dummy_section(&d->map, as, &io_mem_notdirty); + n =3D dummy_section(&d->map, d, &io_mem_notdirty); assert(n =3D=3D PHYS_SECTION_NOTDIRTY); - n =3D dummy_section(&d->map, as, &io_mem_rom); + n =3D dummy_section(&d->map, d, &io_mem_rom); assert(n =3D=3D PHYS_SECTION_ROM); - n =3D dummy_section(&d->map, as, &io_mem_watch); + n =3D dummy_section(&d->map, d, &io_mem_watch); assert(n =3D=3D PHYS_SECTION_WATCH); =20 d->phys_map =3D (PhysPageEntry) { .ptr =3D PHYS_MAP_NODE_NIL, .skip = =3D 1 }; - d->as =3D as; as->next_dispatch =3D d; } =20 @@ -2900,7 +2908,8 @@ static bool prepare_mmio_access(MemoryRegion *mr) } =20 /* Called within RCU critical section. */ -static MemTxResult address_space_write_continue(AddressSpace *as, hwaddr a= ddr, +static MemTxResult address_space_write_continue(AddressSpaceDispatch *d, + hwaddr addr, MemTxAttrs attrs, const uint8_t *buf, int len, hwaddr addr1, @@ -2966,14 +2975,15 @@ static MemTxResult address_space_write_continue(Add= ressSpace *as, hwaddr addr, } =20 l =3D len; - mr =3D address_space_translate(as, addr, &addr1, &l, true); + mr =3D address_space_dispatch_translate(d, addr, &addr1, &l, true); } =20 return result; } =20 -MemTxResult address_space_write(AddressSpace *as, hwaddr addr, MemTxAttrs = attrs, - const uint8_t *buf, int len) +MemTxResult address_space_dispatch_write(AddressSpaceDispatch *d, hwaddr a= ddr, + MemTxAttrs attrs, const uint8_t *= buf, + int len) { hwaddr l; hwaddr addr1; @@ -2983,8 +2993,8 @@ MemTxResult address_space_write(AddressSpace *as, hwa= ddr addr, MemTxAttrs attrs, if (len > 0) { rcu_read_lock(); l =3D len; - mr =3D address_space_translate(as, addr, &addr1, &l, true); - result =3D address_space_write_continue(as, addr, attrs, buf, len, + mr =3D address_space_dispatch_translate(d, addr, &addr1, &l, true); + result =3D address_space_write_continue(d, addr, attrs, buf, len, addr1, l, mr); rcu_read_unlock(); } @@ -2993,7 +3003,7 @@ MemTxResult address_space_write(AddressSpace *as, hwa= ddr addr, MemTxAttrs attrs, } =20 /* Called within RCU critical section. */ -MemTxResult address_space_read_continue(AddressSpace *as, hwaddr addr, +MemTxResult address_space_read_continue(AddressSpaceDispatch *d, hwaddr ad= dr, MemTxAttrs attrs, uint8_t *buf, int len, hwaddr addr1, hwaddr l, MemoryRegion *mr) @@ -3056,13 +3066,13 @@ MemTxResult address_space_read_continue(AddressSpac= e *as, hwaddr addr, } =20 l =3D len; - mr =3D address_space_translate(as, addr, &addr1, &l, false); + mr =3D address_space_dispatch_translate(d, addr, &addr1, &l, false= ); } =20 return result; } =20 -MemTxResult address_space_read_full(AddressSpace *as, hwaddr addr, +MemTxResult address_space_read_full(AddressSpaceDispatch *d, hwaddr addr, MemTxAttrs attrs, uint8_t *buf, int le= n) { hwaddr l; @@ -3073,8 +3083,8 @@ MemTxResult address_space_read_full(AddressSpace *as,= hwaddr addr, if (len > 0) { rcu_read_lock(); l =3D len; - mr =3D address_space_translate(as, addr, &addr1, &l, false); - result =3D address_space_read_continue(as, addr, attrs, buf, len, + mr =3D address_space_dispatch_translate(d, addr, &addr1, &l, false= ); + result =3D address_space_read_continue(d, addr, attrs, buf, len, addr1, l, mr); rcu_read_unlock(); } @@ -3082,13 +3092,14 @@ MemTxResult address_space_read_full(AddressSpace *a= s, hwaddr addr, return result; } =20 -MemTxResult address_space_rw(AddressSpace *as, hwaddr addr, MemTxAttrs att= rs, - uint8_t *buf, int len, bool is_write) +MemTxResult address_space_dispatch_rw(AddressSpaceDispatch *d, hwaddr addr, + MemTxAttrs attrs, uint8_t *buf, + int len, bool is_write) { if (is_write) { - return address_space_write(as, addr, attrs, (uint8_t *)buf, len); + return address_space_dispatch_write(d, addr, attrs, buf, len); } else { - return address_space_read(as, addr, attrs, (uint8_t *)buf, len); + return address_space_dispatch_read(d, addr, attrs, buf, len); } } =20 @@ -3249,7 +3260,8 @@ static void cpu_notify_map_clients(void) qemu_mutex_unlock(&map_client_list_lock); } =20 -bool address_space_access_valid(AddressSpace *as, hwaddr addr, int len, bo= ol is_write) +bool address_space_dispatch_access_valid(AddressSpaceDispatch *d, hwaddr a= ddr, + int len, bool is_write) { MemoryRegion *mr; hwaddr l, xlat; @@ -3257,7 +3269,7 @@ bool address_space_access_valid(AddressSpace *as, hwa= ddr addr, int len, bool is_ rcu_read_lock(); while (len > 0) { l =3D len; - mr =3D address_space_translate(as, addr, &xlat, &l, is_write); + mr =3D address_space_dispatch_translate(d, addr, &xlat, &l, is_wri= te); if (!memory_access_is_direct(mr, is_write)) { l =3D memory_access_size(mr, l, addr); if (!memory_region_access_valid(mr, xlat, l, is_write)) { @@ -3274,7 +3286,8 @@ bool address_space_access_valid(AddressSpace *as, hwa= ddr addr, int len, bool is_ } =20 static hwaddr -address_space_extend_translation(AddressSpace *as, hwaddr addr, hwaddr tar= get_len, +address_space_extend_translation(AddressSpaceDispatch *d, hwaddr addr, + hwaddr target_len, MemoryRegion *mr, hwaddr base, hwaddr len, bool is_write) { @@ -3291,7 +3304,8 @@ address_space_extend_translation(AddressSpace *as, hw= addr addr, hwaddr target_le } =20 len =3D target_len; - this_mr =3D address_space_translate(as, addr, &xlat, &len, is_writ= e); + this_mr =3D address_space_dispatch_translate(d, addr, &xlat, + &len, is_write); if (this_mr !=3D mr || xlat !=3D base + done) { return done; } @@ -3314,6 +3328,7 @@ void *address_space_map(AddressSpace *as, hwaddr l, xlat; MemoryRegion *mr; void *ptr; + AddressSpaceDispatch *d =3D address_space_to_dispatch(as); =20 if (len =3D=3D 0) { return NULL; @@ -3321,7 +3336,7 @@ void *address_space_map(AddressSpace *as, =20 l =3D len; rcu_read_lock(); - mr =3D address_space_translate(as, addr, &xlat, &l, is_write); + mr =3D address_space_dispatch_translate(d, addr, &xlat, &l, is_write); =20 if (!memory_access_is_direct(mr, is_write)) { if (atomic_xchg(&bounce.in_use, true)) { @@ -3337,7 +3352,7 @@ void *address_space_map(AddressSpace *as, memory_region_ref(mr); bounce.mr =3D mr; if (!is_write) { - address_space_read(as, addr, MEMTXATTRS_UNSPECIFIED, + address_space_dispatch_read(d, addr, MEMTXATTRS_UNSPECIFIED, bounce.buffer, l); } =20 @@ -3348,7 +3363,8 @@ void *address_space_map(AddressSpace *as, =20 =20 memory_region_ref(mr); - *plen =3D address_space_extend_translation(as, addr, len, mr, xlat, l,= is_write); + *plen =3D address_space_extend_translation(d, addr, len, mr, xlat, + l, is_write); ptr =3D qemu_ram_ptr_length(mr->ram_block, xlat, plen, true); rcu_read_unlock(); =20 diff --git a/hw/alpha/typhoon.c b/hw/alpha/typhoon.c index ae11e012c7..b3dedf5b74 100644 --- a/hw/alpha/typhoon.c +++ b/hw/alpha/typhoon.c @@ -604,7 +604,7 @@ static const MemoryRegionOps pchip_ops =3D { static bool make_iommu_tlbe(hwaddr taddr, hwaddr mask, IOMMUTLBEntry *ret) { *ret =3D (IOMMUTLBEntry) { - .target_as =3D &address_space_memory, + .target_dispatch =3D address_space_to_dispatch(&address_space_memo= ry), .translated_addr =3D taddr, .addr_mask =3D mask, .perm =3D IOMMU_RW, diff --git a/hw/dma/rc4030.c b/hw/dma/rc4030.c index 5d4833eeca..d771020b78 100644 --- a/hw/dma/rc4030.c +++ b/hw/dma/rc4030.c @@ -495,7 +495,7 @@ static IOMMUTLBEntry rc4030_dma_translate(IOMMUMemoryRe= gion *iommu, hwaddr addr, { rc4030State *s =3D container_of(iommu, rc4030State, dma_mr); IOMMUTLBEntry ret =3D { - .target_as =3D &address_space_memory, + .target_dispatch =3D address_space_to_dispatch(&address_space_memo= ry), .iova =3D addr & ~(DMA_PAGESIZE - 1), .translated_addr =3D 0, .addr_mask =3D DMA_PAGESIZE - 1, @@ -507,7 +507,7 @@ static IOMMUTLBEntry rc4030_dma_translate(IOMMUMemoryRe= gion *iommu, hwaddr addr, i =3D addr / DMA_PAGESIZE; if (i < s->dma_tl_limit / sizeof(entry)) { entry_address =3D (s->dma_tl_base & 0x7fffffff) + i * sizeof(entry= ); - if (address_space_read(ret.target_as, entry_address, + if (address_space_dispatch_read(ret.target_dispatch, entry_address, MEMTXATTRS_UNSPECIFIED, (unsigned char *)&e= ntry, sizeof(entry)) =3D=3D MEMTX_OK) { ret.translated_addr =3D entry.frame & ~(DMA_PAGESIZE - 1); diff --git a/hw/i386/amd_iommu.c b/hw/i386/amd_iommu.c index 334938a280..dc3303fdad 100644 --- a/hw/i386/amd_iommu.c +++ b/hw/i386/amd_iommu.c @@ -993,7 +993,7 @@ static IOMMUTLBEntry amdvi_translate(IOMMUMemoryRegion = *iommu, hwaddr addr, AMDVIAddressSpace *as =3D container_of(iommu, AMDVIAddressSpace, iommu= ); AMDVIState *s =3D as->iommu_state; IOMMUTLBEntry ret =3D { - .target_as =3D &address_space_memory, + .target_dispatch =3D address_space_to_dispatch(&address_space_memo= ry), .iova =3D addr, .translated_addr =3D 0, .addr_mask =3D ~(hwaddr)0, diff --git a/hw/i386/intel_iommu.c b/hw/i386/intel_iommu.c index a7bf87a19e..b31fe2af75 100644 --- a/hw/i386/intel_iommu.c +++ b/hw/i386/intel_iommu.c @@ -787,7 +787,8 @@ static int vtd_page_walk_level(dma_addr_t addr, uint64_= t start, entry_valid =3D read_cur | write_cur; =20 if (vtd_is_last_slpte(slpte, level)) { - entry.target_as =3D &address_space_memory; + entry.target_dispatch =3D + address_space_to_dispatch(&address_space_memory); entry.iova =3D iova & subpage_mask; /* NOTE: this is only meaningful if entry_valid =3D=3D true */ entry.translated_addr =3D vtd_get_slpte_addr(slpte); @@ -1810,7 +1811,7 @@ static bool vtd_process_device_iotlb_desc(IntelIOMMUS= tate *s, sz =3D VTD_PAGE_SIZE; } =20 - entry.target_as =3D &vtd_dev_as->as; + entry.target_dispatch =3D address_space_to_dispatch(&vtd_dev_as->as); entry.addr_mask =3D sz - 1; entry.iova =3D addr; entry.perm =3D IOMMU_NONE; @@ -2270,7 +2271,7 @@ static IOMMUTLBEntry vtd_iommu_translate(IOMMUMemoryR= egion *iommu, hwaddr addr, IntelIOMMUState *s =3D vtd_as->iommu_state; IOMMUTLBEntry iotlb =3D { /* We'll fill in the rest later. */ - .target_as =3D &address_space_memory, + .target_dispatch =3D address_space_to_dispatch(&address_space_memo= ry), }; bool success; =20 @@ -2781,7 +2782,7 @@ static void vtd_address_space_unmap(VTDAddressSpace *= as, IOMMUNotifier *n) size =3D 1ULL << n; } =20 - entry.target_as =3D &address_space_memory; + entry.target_dispatch =3D address_space_to_dispatch(&address_space_mem= ory); /* Adjust iova for the size */ entry.iova =3D n->start & ~(size - 1); /* This field is meaningless for unmap */ diff --git a/hw/intc/openpic_kvm.c b/hw/intc/openpic_kvm.c index 0518e017c4..99578e7f7a 100644 --- a/hw/intc/openpic_kvm.c +++ b/hw/intc/openpic_kvm.c @@ -124,7 +124,7 @@ static void kvm_openpic_region_add(MemoryListener *list= ener, uint64_t reg_base; int ret; =20 - if (section->address_space !=3D &address_space_memory) { + if (section->dispatch !=3D address_space_to_dispatch(&address_space_me= mory)) { abort(); } =20 diff --git a/hw/pci-host/apb.c b/hw/pci-host/apb.c index 96e5d0b60d..ecfc9060b9 100644 --- a/hw/pci-host/apb.c +++ b/hw/pci-host/apb.c @@ -218,7 +218,7 @@ static IOMMUTLBEntry pbm_translate_iommu(IOMMUMemoryReg= ion *iommu, hwaddr addr, uint64_t tte; uint32_t tsbsize; IOMMUTLBEntry ret =3D { - .target_as =3D &address_space_memory, + .target_dispatch =3D address_space_to_dispatch(&address_space_memo= ry), .iova =3D 0, .translated_addr =3D 0, .addr_mask =3D ~(hwaddr)0, diff --git a/hw/ppc/spapr_iommu.c b/hw/ppc/spapr_iommu.c index ed2d53559a..566d7779bc 100644 --- a/hw/ppc/spapr_iommu.c +++ b/hw/ppc/spapr_iommu.c @@ -117,7 +117,7 @@ static IOMMUTLBEntry spapr_tce_translate_iommu(IOMMUMem= oryRegion *iommu, sPAPRTCETable *tcet =3D container_of(iommu, sPAPRTCETable, iommu); uint64_t tce; IOMMUTLBEntry ret =3D { - .target_as =3D &address_space_memory, + .target_dispatch =3D address_space_to_dispatch(&address_space_memo= ry), .iova =3D 0, .translated_addr =3D 0, .addr_mask =3D ~(hwaddr)0, @@ -407,7 +407,7 @@ static target_ulong put_tce_emu(sPAPRTCETable *tcet, ta= rget_ulong ioba, =20 tcet->table[index] =3D tce; =20 - entry.target_as =3D &address_space_memory, + entry.target_dispatch =3D address_space_to_dispatch(&address_space_mem= ory), entry.iova =3D (ioba - tcet->bus_offset) & page_mask; entry.translated_addr =3D tce & page_mask; entry.addr_mask =3D ~page_mask; diff --git a/hw/s390x/s390-pci-bus.c b/hw/s390x/s390-pci-bus.c index 61cfd2138f..2f667ddf07 100644 --- a/hw/s390x/s390-pci-bus.c +++ b/hw/s390x/s390-pci-bus.c @@ -363,7 +363,7 @@ static IOMMUTLBEntry s390_translate_iommu(IOMMUMemoryRe= gion *mr, hwaddr addr, uint32_t flags; S390PCIIOMMU *iommu =3D container_of(mr, S390PCIIOMMU, iommu_mr); IOMMUTLBEntry ret =3D { - .target_as =3D &address_space_memory, + .target_dispatch =3D address_space_to_dispatch(&address_space_memo= ry), .iova =3D 0, .translated_addr =3D 0, .addr_mask =3D ~(hwaddr)0, diff --git a/hw/vfio/common.c b/hw/vfio/common.c index 7b2924c0ef..04d21b92c1 100644 --- a/hw/vfio/common.c +++ b/hw/vfio/common.c @@ -358,9 +358,9 @@ static void vfio_iommu_map_notify(IOMMUNotifier *n, IOM= MUTLBEntry *iotlb) trace_vfio_iommu_map_notify(iotlb->perm =3D=3D IOMMU_NONE ? "UNMAP" : = "MAP", iova, iova + iotlb->addr_mask); =20 - if (iotlb->target_as !=3D &address_space_memory) { - error_report("Wrong target AS \"%s\", only system memory is allowe= d", - iotlb->target_as->name ? iotlb->target_as->name : "no= ne"); + if (iotlb->target_dispatch !=3D + address_space_to_dispatch(&address_space_memory)) { + error_report("Wrong target, only system memory is allowed"); return; } =20 diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c index 6eddb099b0..ae2a3f5dd7 100644 --- a/hw/virtio/vhost.c +++ b/hw/virtio/vhost.c @@ -976,12 +976,12 @@ int vhost_device_iotlb_miss(struct vhost_dev *dev, ui= nt64_t iova, int write) IOMMUTLBEntry iotlb; uint64_t uaddr, len; int ret =3D -EFAULT; + AddressSpaceDispatch *d =3D address_space_to_dispatch(dev->vdev->dma_a= s); =20 rcu_read_lock(); =20 - iotlb =3D address_space_get_iotlb_entry(dev->vdev->dma_as, - iova, write); - if (iotlb.target_as !=3D NULL) { + iotlb =3D address_space_get_iotlb_entry(d, iova, write); + if (iotlb.target_dispatch !=3D NULL) { ret =3D vhost_memory_region_lookup(dev, iotlb.translated_addr, &uaddr, &len); if (ret) { diff --git a/memory.c b/memory.c index c0adc35410..c6904a7deb 100644 --- a/memory.c +++ b/memory.c @@ -154,7 +154,8 @@ enum ListenerDirection { Forward, Reverse }; /* No need to ref/unref .mr, the FlatRange keeps it alive. */ #define MEMORY_LISTENER_UPDATE_REGION(fr, as, dir, callback, _args...) \ do { \ - MemoryRegionSection mrs =3D section_from_flat_range(fr, as); \ + MemoryRegionSection mrs =3D section_from_flat_range(fr, \ + address_space_to_dispatch(as)); \ MEMORY_LISTENER_CALL(as, callback, dir, &mrs, ##_args); \ } while(0) =20 @@ -237,11 +238,11 @@ typedef struct AddressSpaceOps AddressSpaceOps; for (var =3D (view)->ranges; var < (view)->ranges + (view)->nr; ++var) =20 static inline MemoryRegionSection -section_from_flat_range(FlatRange *fr, AddressSpace *as) +section_from_flat_range(FlatRange *fr, AddressSpaceDispatch *d) { return (MemoryRegionSection) { .mr =3D fr->mr, - .address_space =3D as, + .dispatch =3D d, .offset_within_region =3D fr->offset_in_region, .size =3D fr->addr.size, .offset_within_address_space =3D int128_get64(fr->addr.start), @@ -727,6 +728,7 @@ static void address_space_add_del_ioeventfds(AddressSpa= ce *as, unsigned iold, inew; MemoryRegionIoeventfd *fd; MemoryRegionSection section; + AddressSpaceDispatch *d =3D address_space_to_dispatch(as); =20 /* Generate a symmetric difference of the old and new fd sets, adding * and deleting as necessary. @@ -740,7 +742,7 @@ static void address_space_add_del_ioeventfds(AddressSpa= ce *as, fds_new[inew]))) { fd =3D &fds_old[iold]; section =3D (MemoryRegionSection) { - .address_space =3D as, + .dispatch =3D d, .offset_within_address_space =3D int128_get64(fd->addr.sta= rt), .size =3D fd->addr.size, }; @@ -753,7 +755,7 @@ static void address_space_add_del_ioeventfds(AddressSpa= ce *as, fds_old[iold]))) { fd =3D &fds_new[inew]; section =3D (MemoryRegionSection) { - .address_space =3D as, + .dispatch =3D d, .offset_within_address_space =3D int128_get64(fd->addr.sta= rt), .size =3D fd->addr.size, }; @@ -1835,7 +1837,9 @@ void memory_region_sync_dirty_bitmap(MemoryRegion *mr) view =3D address_space_get_flatview(as); FOR_EACH_FLAT_RANGE(fr, view) { if (fr->mr =3D=3D mr) { - MemoryRegionSection mrs =3D section_from_flat_range(fr, as= ); + MemoryRegionSection mrs =3D section_from_flat_range(fr, + address_space_to_dispatch(as)); + listener->log_sync(listener, &mrs); } } @@ -1938,7 +1942,7 @@ static void memory_region_update_coalesced_range_as(M= emoryRegion *mr, AddressSpa FOR_EACH_FLAT_RANGE(fr, view) { if (fr->mr =3D=3D mr) { section =3D (MemoryRegionSection) { - .address_space =3D as, + .dispatch =3D address_space_to_dispatch(as), .offset_within_address_space =3D int128_get64(fr->addr.sta= rt), .size =3D fr->addr.size, }; @@ -2300,7 +2304,7 @@ static MemoryRegionSection memory_region_find_rcu(Mem= oryRegion *mr, } =20 ret.mr =3D fr->mr; - ret.address_space =3D as; + ret.dispatch =3D address_space_to_dispatch(as); range =3D addrrange_intersection(range, fr->addr); ret.offset_within_region =3D fr->offset_in_region; ret.offset_within_region +=3D int128_get64(int128_sub(range.start, @@ -2349,7 +2353,9 @@ void memory_global_dirty_log_sync(void) view =3D address_space_get_flatview(as); FOR_EACH_FLAT_RANGE(fr, view) { if (fr->dirty_log_mask) { - MemoryRegionSection mrs =3D section_from_flat_range(fr, as= ); + MemoryRegionSection mrs =3D section_from_flat_range(fr, + address_space_to_dispatch(as)); + listener->log_sync(listener, &mrs); } } @@ -2434,7 +2440,7 @@ static void listener_add_address_space(MemoryListener= *listener, FOR_EACH_FLAT_RANGE(fr, view) { MemoryRegionSection section =3D { .mr =3D fr->mr, - .address_space =3D as, + .dispatch =3D address_space_to_dispatch(as), .offset_within_region =3D fr->offset_in_region, .size =3D fr->addr.size, .offset_within_address_space =3D int128_get64(fr->addr.start), --=20 2.11.0 From nobody Sat Apr 27 20:51: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 1504776216704288.62230806814887; Thu, 7 Sep 2017 02:23:36 -0700 (PDT) Received: from localhost ([::1]:39519 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dpt27-0003Cs-JN for importer@patchew.org; Thu, 07 Sep 2017 05:23:35 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:57255) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dpszb-0001H1-6g for qemu-devel@nongnu.org; Thu, 07 Sep 2017 05:21:05 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1dpszY-0007jF-Nu for qemu-devel@nongnu.org; Thu, 07 Sep 2017 05:20:59 -0400 Received: from ozlabs.ru ([107.173.13.209]:51600) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dpszY-0007j2-95 for qemu-devel@nongnu.org; Thu, 07 Sep 2017 05:20:56 -0400 Received: from vpl1.ozlabs.ibm.com (localhost [IPv6:::1]) by ozlabs.ru (Postfix) with ESMTP id CE94D3A604D3; Thu, 7 Sep 2017 05:21:35 -0400 (EDT) From: Alexey Kardashevskiy To: qemu-devel@nongnu.org Date: Thu, 7 Sep 2017 19:20:09 +1000 Message-Id: <20170907092010.3605-4-aik@ozlabs.ru> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20170907092010.3605-1-aik@ozlabs.ru> References: <20170907092010.3605-1-aik@ozlabs.ru> 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 3/4] memory: Share flat views and dispatch trees between address spaces 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 , Stefan Hajnoczi , Peter Maydell , David Gibson 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" This allows sharing flat views between address spaces when the same root memory region is used when creating a new address space. This adds a global list of flat views and a list of attached address spaces per a flat view. Each address space references a flat view. This hard codes the dispatch tree building instead of doing so via a memory listener. Signed-off-by: Alexey Kardashevskiy --- This was suggested by Paolo in https://lists.gnu.org/archive/html/qemu-devel/2017-08/msg05011.html I am not putting "Suggested-by" as I want to make sure that this is doing what was actually suggested. --- include/exec/memory-internal.h | 6 +- include/exec/memory.h | 9 +- exec.c | 58 ++-------- hw/pci/pci.c | 3 +- memory.c | 253 +++++++++++++++++++++++++++----------= ---- 5 files changed, 187 insertions(+), 142 deletions(-) diff --git a/include/exec/memory-internal.h b/include/exec/memory-internal.h index fb467acdba..8516e0b48f 100644 --- a/include/exec/memory-internal.h +++ b/include/exec/memory-internal.h @@ -22,9 +22,11 @@ #ifndef CONFIG_USER_ONLY typedef struct AddressSpaceDispatch AddressSpaceDispatch; =20 -void address_space_init_dispatch(AddressSpace *as); void address_space_unregister(AddressSpace *as); -void address_space_destroy_dispatch(AddressSpace *as); +void address_space_dispatch_free(AddressSpaceDispatch *d); +AddressSpaceDispatch *mem_begin(void); +void mem_commit(AddressSpaceDispatch *d); +void mem_add(AddressSpaceDispatch *d, MemoryRegionSection *section); =20 extern const MemoryRegionOps unassigned_mem_ops; =20 diff --git a/include/exec/memory.h b/include/exec/memory.h index 83e82e90d5..41ab165302 100644 --- a/include/exec/memory.h +++ b/include/exec/memory.h @@ -27,6 +27,7 @@ #include "qemu/rcu.h" #include "hw/qdev-core.h" =20 +typedef struct AddressSpaceDispatch AddressSpaceDispatch; #define RAM_ADDR_INVALID (~(ram_addr_t)0) =20 #define MAX_PHYS_ADDR_SPACE_BITS 62 @@ -312,6 +313,7 @@ struct MemoryListener { }; =20 AddressSpaceDispatch *address_space_to_dispatch(AddressSpace *as); +MemoryRegion *address_space_root(AddressSpace *as); =20 /** * AddressSpace: describes a mapping of addresses to #MemoryRegion objects @@ -320,20 +322,17 @@ struct AddressSpace { /* All fields are private. */ struct rcu_head rcu; char *name; - MemoryRegion *root; - int ref_count; - bool malloced; =20 /* Accessed via RCU. */ struct FlatView *current_map; =20 int ioeventfd_nb; struct MemoryRegionIoeventfd *ioeventfds; - struct AddressSpaceDispatch *dispatch; - struct AddressSpaceDispatch *next_dispatch; + MemoryListener dispatch_listener; QTAILQ_HEAD(memory_listeners_as, MemoryListener) listeners; QTAILQ_ENTRY(AddressSpace) address_spaces_link; + QTAILQ_ENTRY(AddressSpace) flat_view_link; }; =20 /** diff --git a/exec.c b/exec.c index 66f01f5fce..51243f57f4 100644 --- a/exec.c +++ b/exec.c @@ -188,15 +188,12 @@ typedef struct PhysPageMap { } PhysPageMap; =20 struct AddressSpaceDispatch { - struct rcu_head rcu; - MemoryRegionSection *mru_section; /* This is a multi-level map on the physical address space. * The bottom level has pointers to MemoryRegionSections. */ PhysPageEntry phys_map; PhysPageMap map; - AddressSpace *as; }; =20 typedef struct AddressSpaceDispatch AddressSpaceDispatch; @@ -240,11 +237,6 @@ struct DirtyBitmapSnapshot { unsigned long dirty[]; }; =20 -AddressSpaceDispatch *address_space_to_dispatch(AddressSpace *as) -{ - return atomic_rcu_read(&as->dispatch); -} - #endif =20 #if !defined(CONFIG_USER_ONLY) @@ -1354,10 +1346,8 @@ static void register_multipage(AddressSpaceDispatch = *d, phys_page_set(d, start_addr >> TARGET_PAGE_BITS, num_pages, section_in= dex); } =20 -static void mem_add(MemoryListener *listener, MemoryRegionSection *section) +void mem_add(AddressSpaceDispatch *d, MemoryRegionSection *section) { - AddressSpace *as =3D container_of(listener, AddressSpace, dispatch_lis= tener); - AddressSpaceDispatch *d =3D as->next_dispatch; MemoryRegionSection now =3D *section, remain =3D *section; Int128 page_size =3D int128_make64(TARGET_PAGE_SIZE); =20 @@ -2680,9 +2670,8 @@ static void io_mem_init(void) NULL, UINT64_MAX); } =20 -static void mem_begin(MemoryListener *listener) +AddressSpaceDispatch *mem_begin(void) { - AddressSpace *as =3D container_of(listener, AddressSpace, dispatch_lis= tener); AddressSpaceDispatch *d =3D g_new0(AddressSpaceDispatch, 1); uint16_t n; =20 @@ -2696,27 +2685,19 @@ static void mem_begin(MemoryListener *listener) assert(n =3D=3D PHYS_SECTION_WATCH); =20 d->phys_map =3D (PhysPageEntry) { .ptr =3D PHYS_MAP_NODE_NIL, .skip = =3D 1 }; - as->next_dispatch =3D d; + + return d; } =20 -static void address_space_dispatch_free(AddressSpaceDispatch *d) +void address_space_dispatch_free(AddressSpaceDispatch *d) { phys_sections_free(&d->map); g_free(d); } =20 -static void mem_commit(MemoryListener *listener) +void mem_commit(AddressSpaceDispatch *d) { - AddressSpace *as =3D container_of(listener, AddressSpace, dispatch_lis= tener); - AddressSpaceDispatch *cur =3D as->dispatch; - AddressSpaceDispatch *next =3D as->next_dispatch; - - phys_page_compact_all(next, next->map.nodes_nb); - - atomic_rcu_set(&as->dispatch, next); - if (cur) { - call_rcu(cur, address_space_dispatch_free, rcu); - } + phys_page_compact_all(d, d->map.nodes_nb); } =20 static void tcg_commit(MemoryListener *listener) @@ -2732,39 +2713,16 @@ static void tcg_commit(MemoryListener *listener) * We reload the dispatch pointer now because cpu_reloading_memory_map= () * may have split the RCU critical section. */ - d =3D atomic_rcu_read(&cpuas->as->dispatch); + d =3D address_space_to_dispatch(cpuas->as); atomic_rcu_set(&cpuas->memory_dispatch, d); tlb_flush(cpuas->cpu); } =20 -void address_space_init_dispatch(AddressSpace *as) -{ - as->dispatch =3D NULL; - as->dispatch_listener =3D (MemoryListener) { - .begin =3D mem_begin, - .commit =3D mem_commit, - .region_add =3D mem_add, - .region_nop =3D mem_add, - .priority =3D 0, - }; - memory_listener_register(&as->dispatch_listener, as); -} - void address_space_unregister(AddressSpace *as) { memory_listener_unregister(&as->dispatch_listener); } =20 -void address_space_destroy_dispatch(AddressSpace *as) -{ - AddressSpaceDispatch *d =3D as->dispatch; - - atomic_rcu_set(&as->dispatch, NULL); - if (d) { - call_rcu(d, address_space_dispatch_free, rcu); - } -} - static void memory_map_init(void) { system_memory =3D g_malloc(sizeof(*system_memory)); diff --git a/hw/pci/pci.c b/hw/pci/pci.c index 258fbe51e2..86b9e419fd 100644 --- a/hw/pci/pci.c +++ b/hw/pci/pci.c @@ -88,7 +88,8 @@ static void pci_init_bus_master(PCIDevice *pci_dev) =20 memory_region_init_alias(&pci_dev->bus_master_enable_region, OBJECT(pci_dev), "bus master", - dma_as->root, 0, memory_region_size(dma_as->r= oot)); + address_space_root(dma_as), 0, + memory_region_size(address_space_root(dma_as)= )); memory_region_set_enabled(&pci_dev->bus_master_enable_region, false); memory_region_add_subregion(&pci_dev->bus_master_container_region, 0, &pci_dev->bus_master_enable_region); diff --git a/memory.c b/memory.c index c6904a7deb..385a507511 100644 --- a/memory.c +++ b/memory.c @@ -47,6 +47,9 @@ static QTAILQ_HEAD(memory_listeners, MemoryListener) memo= ry_listeners static QTAILQ_HEAD(, AddressSpace) address_spaces =3D QTAILQ_HEAD_INITIALIZER(address_spaces); =20 +static QTAILQ_HEAD(FlatViewList, FlatView) flat_views + =3D QTAILQ_HEAD_INITIALIZER(flat_views); + typedef struct AddrRange AddrRange; =20 /* @@ -230,6 +233,11 @@ struct FlatView { FlatRange *ranges; unsigned nr; unsigned nr_allocated; + MemoryRegion *root; + struct AddressSpaceDispatch *dispatch; + + QTAILQ_ENTRY(FlatView) flat_views_link; + QTAILQ_HEAD(address_spaces, AddressSpace) address_spaces; }; =20 typedef struct AddressSpaceOps AddressSpaceOps; @@ -259,12 +267,19 @@ static bool flatrange_equal(FlatRange *a, FlatRange *= b) && a->readonly =3D=3D b->readonly; } =20 -static void flatview_init(FlatView *view) +static void flatview_ref(FlatView *view); + +static FlatView *flatview_alloc(MemoryRegion *mr_root) { + FlatView *view; + + view =3D g_new0(FlatView, 1); view->ref =3D 1; - view->ranges =3D NULL; - view->nr =3D 0; - view->nr_allocated =3D 0; + view->root =3D mr_root; + memory_region_ref(mr_root); + QTAILQ_INIT(&view->address_spaces); + + return view; } =20 /* Insert a range into a given position. Caller is responsible for mainta= ining @@ -292,6 +307,10 @@ static void flatview_destroy(FlatView *view) memory_region_unref(view->ranges[i].mr); } g_free(view->ranges); + if (view->dispatch) { + address_space_dispatch_free(view->dispatch); + } + memory_region_unref(view->root); g_free(view); } =20 @@ -303,7 +322,7 @@ static void flatview_ref(FlatView *view) static void flatview_unref(FlatView *view) { if (atomic_fetch_dec(&view->ref) =3D=3D 1) { - flatview_destroy(view); + call_rcu(view, flatview_destroy, rcu); } } =20 @@ -608,7 +627,7 @@ static AddressSpace *memory_region_to_address_space(Mem= oryRegion *mr) mr =3D mr->container; } QTAILQ_FOREACH(as, &address_spaces, address_spaces_link) { - if (mr =3D=3D as->root) { + if (mr =3D=3D as->current_map->root) { return as; } } @@ -702,23 +721,6 @@ static void render_memory_region(FlatView *view, } } =20 -/* Render a memory topology into a list of disjoint absolute ranges. */ -static FlatView *generate_memory_topology(MemoryRegion *mr) -{ - FlatView *view; - - view =3D g_new(FlatView, 1); - flatview_init(view); - - if (mr) { - render_memory_region(view, mr, int128_zero(), - addrrange_make(int128_zero(), int128_2_64()),= false); - } - flatview_simplify(view); - - return view; -} - static void address_space_add_del_ioeventfds(AddressSpace *as, MemoryRegionIoeventfd *fds_ne= w, unsigned fds_new_nb, @@ -769,12 +771,10 @@ static void address_space_add_del_ioeventfds(AddressS= pace *as, } } =20 -static FlatView *address_space_get_flatview(AddressSpace *as) +static FlatView *flatview_get(FlatView *view) { - FlatView *view; - rcu_read_lock(); - view =3D atomic_rcu_read(&as->current_map); + view =3D atomic_rcu_read(&view); flatview_ref(view); rcu_read_unlock(); return view; @@ -789,7 +789,7 @@ static void address_space_update_ioeventfds(AddressSpac= e *as) AddrRange tmp; unsigned i; =20 - view =3D address_space_get_flatview(as); + view =3D flatview_get(as->current_map); FOR_EACH_FLAT_RANGE(fr, view) { for (i =3D 0; i < fr->mr->ioeventfd_nb; ++i) { tmp =3D addrrange_shift(fr->mr->ioeventfds[i].addr, @@ -881,28 +881,89 @@ static void address_space_update_topology_pass(Addres= sSpace *as, } } =20 - -static void address_space_update_topology(AddressSpace *as) +static FlatView *address_space_update_flatview(FlatView *view) { - FlatView *old_view =3D address_space_get_flatview(as); - FlatView *new_view =3D generate_memory_topology(as->root); + AddressSpace *as, *asnext; + FlatView *old_view =3D flatview_get(view); + MemoryRegion *root =3D old_view->root; + FlatView *new_view =3D flatview_alloc(root); + unsigned iold, inew; + FlatRange *frold, *frnew; =20 - address_space_update_topology_pass(as, old_view, new_view, false); - address_space_update_topology_pass(as, old_view, new_view, true); + if (root) { + render_memory_region(new_view, root, int128_zero(), + addrrange_make(int128_zero(), int128_2_64()), + false); + flatview_simplify(new_view); + } =20 - /* Writes are protected by the BQL. */ - atomic_rcu_set(&as->current_map, new_view); - call_rcu(old_view, flatview_unref, rcu); + new_view->dispatch =3D mem_begin(); =20 - /* Note that all the old MemoryRegions are still alive up to this - * point. This relieves most MemoryListeners from the need to - * ref/unref the MemoryRegions they get---unless they use them - * outside the iothread mutex, in which case precise reference - * counting is necessary. + /* + * FIXME: this is cut-n-paste from address_space_update_topology_pass, + * simplify it */ + iold =3D inew =3D 0; + while (iold < old_view->nr || inew < new_view->nr) { + if (iold < old_view->nr) { + frold =3D &old_view->ranges[iold]; + } else { + frold =3D NULL; + } + if (inew < new_view->nr) { + frnew =3D &new_view->ranges[inew]; + } else { + frnew =3D NULL; + } + + if (frold + && (!frnew + || int128_lt(frold->addr.start, frnew->addr.start) + || (int128_eq(frold->addr.start, frnew->addr.start) + && !flatrange_equal(frold, frnew)))) { + ++iold; + } else if (frold && frnew && flatrange_equal(frold, frnew)) { + /* In both and unchanged (except logging may have changed) */ + MemoryRegionSection mrs =3D section_from_flat_range(frnew, + new_view->dispatch); + + mem_add(new_view->dispatch, &mrs); + + ++iold; + ++inew; + } else { + /* In new */ + MemoryRegionSection mrs =3D section_from_flat_range(frnew, + new_view->dispatch); + + mem_add(new_view->dispatch, &mrs); + + ++inew; + } + } + + mem_commit(new_view->dispatch); + + QTAILQ_FOREACH(as, &old_view->address_spaces, flat_view_link) { + address_space_update_topology_pass(as, old_view, new_view, false); + address_space_update_topology_pass(as, old_view, new_view, true); + } + + QTAILQ_FOREACH_SAFE(as, &old_view->address_spaces, flat_view_link, asn= ext) { + QTAILQ_REMOVE(&old_view->address_spaces, as, flat_view_link); + flatview_unref(old_view); + + atomic_rcu_set(&as->current_map, new_view); + + flatview_ref(new_view); + QTAILQ_INSERT_TAIL(&new_view->address_spaces, as, flat_view_link); + + address_space_update_ioeventfds(as); + } + flatview_unref(old_view); =20 - address_space_update_ioeventfds(as); + return new_view; } =20 void memory_region_transaction_begin(void) @@ -921,11 +982,31 @@ void memory_region_transaction_commit(void) --memory_region_transaction_depth; if (!memory_region_transaction_depth) { if (memory_region_update_pending) { + FlatView *view, *vnext; + struct FlatViewList fwstmp =3D QTAILQ_HEAD_INITIALIZER(fwstmp); + MEMORY_LISTENER_CALL_GLOBAL(begin, Forward); =20 - QTAILQ_FOREACH(as, &address_spaces, address_spaces_link) { - address_space_update_topology(as); + QTAILQ_FOREACH_SAFE(view, &flat_views, flat_views_link, vnext)= { + FlatView *old_view, *new_view; + + old_view =3D flatview_get(view); + new_view =3D address_space_update_flatview(old_view); + + QTAILQ_REMOVE(&flat_views, old_view, flat_views_link); + flatview_unref(old_view); + flatview_unref(old_view); + + QTAILQ_INSERT_HEAD(&fwstmp, new_view, flat_views_link); + + flatview_unref(new_view); } + + QTAILQ_FOREACH_SAFE(view, &fwstmp, flat_views_link, vnext) { + QTAILQ_REMOVE(&fwstmp, view, flat_views_link); + QTAILQ_INSERT_HEAD(&flat_views, view, flat_views_link); + } + memory_region_update_pending =3D false; MEMORY_LISTENER_CALL_GLOBAL(commit, Forward); } else if (ioeventfd_update_pending) { @@ -1834,7 +1915,7 @@ void memory_region_sync_dirty_bitmap(MemoryRegion *mr) continue; } as =3D listener->address_space; - view =3D address_space_get_flatview(as); + view =3D flatview_get(as->current_map); FOR_EACH_FLAT_RANGE(fr, view) { if (fr->mr =3D=3D mr) { MemoryRegionSection mrs =3D section_from_flat_range(fr, @@ -1938,7 +2019,7 @@ static void memory_region_update_coalesced_range_as(M= emoryRegion *mr, AddressSpa AddrRange tmp; MemoryRegionSection section; =20 - view =3D address_space_get_flatview(as); + view =3D flatview_get(as->current_map); FOR_EACH_FLAT_RANGE(fr, view) { if (fr->mr =3D=3D mr) { section =3D (MemoryRegionSection) { @@ -2350,7 +2431,7 @@ void memory_global_dirty_log_sync(void) continue; } as =3D listener->address_space; - view =3D address_space_get_flatview(as); + view =3D flatview_get(as->current_map); FOR_EACH_FLAT_RANGE(fr, view) { if (fr->dirty_log_mask) { MemoryRegionSection mrs =3D section_from_flat_range(fr, @@ -2436,7 +2517,7 @@ static void listener_add_address_space(MemoryListener= *listener, } } =20 - view =3D address_space_get_flatview(as); + view =3D flatview_get(as->current_map); FOR_EACH_FLAT_RANGE(fr, view) { MemoryRegionSection section =3D { .mr =3D fr->mr, @@ -2615,67 +2696,72 @@ void memory_region_invalidate_mmio_ptr(MemoryRegion= *mr, hwaddr offset, =20 void address_space_init(AddressSpace *as, MemoryRegion *root, const char *= name) { - memory_region_ref(root); - memory_region_transaction_begin(); - as->ref_count =3D 1; - as->root =3D root; - as->malloced =3D false; - as->current_map =3D g_new(FlatView, 1); - flatview_init(as->current_map); + FlatView *view; + + as->current_map =3D NULL; as->ioeventfd_nb =3D 0; as->ioeventfds =3D NULL; QTAILQ_INIT(&as->listeners); QTAILQ_INSERT_TAIL(&address_spaces, as, address_spaces_link); as->name =3D g_strdup(name ? name : "anonymous"); - address_space_init_dispatch(as); - memory_region_update_pending |=3D root->enabled; - memory_region_transaction_commit(); + + QTAILQ_FOREACH(view, &flat_views, flat_views_link) { + assert(root); + if (view->root =3D=3D root) { + as->current_map =3D flatview_get(view); + break; + } + } + + if (!as->current_map) { + as->current_map =3D flatview_alloc(root); + + QTAILQ_INSERT_TAIL(&flat_views, as->current_map, flat_views_link); + } + + QTAILQ_INSERT_TAIL(&as->current_map->address_spaces, as, flat_view_lin= k); +} + +MemoryRegion *address_space_root(AddressSpace *as) +{ + return as->current_map->root; +} + +AddressSpaceDispatch *address_space_to_dispatch(AddressSpace *as) +{ + return atomic_rcu_read(&as->current_map)->dispatch; } =20 static void do_address_space_destroy(AddressSpace *as) { - bool do_free =3D as->malloced; + FlatView *view =3D flatview_get(as->current_map); =20 - address_space_destroy_dispatch(as); assert(QTAILQ_EMPTY(&as->listeners)); =20 - flatview_unref(as->current_map); + QTAILQ_REMOVE(&view->address_spaces, as, flat_view_link); + flatview_unref(view); + + flatview_unref(view); + g_free(as->name); g_free(as->ioeventfds); - memory_region_unref(as->root); - if (do_free) { - g_free(as); - } + g_free(as); } =20 AddressSpace *address_space_init_shareable(MemoryRegion *root, const char = *name) { AddressSpace *as; =20 - QTAILQ_FOREACH(as, &address_spaces, address_spaces_link) { - if (root =3D=3D as->root && as->malloced) { - as->ref_count++; - return as; - } - } - as =3D g_malloc0(sizeof *as); address_space_init(as, root, name); - as->malloced =3D true; + return as; } =20 void address_space_destroy(AddressSpace *as) { - MemoryRegion *root =3D as->root; - - as->ref_count--; - if (as->ref_count) { - return; - } /* Flush out anything from MemoryListeners listening in on this */ memory_region_transaction_begin(); - as->root =3D NULL; memory_region_transaction_commit(); QTAILQ_REMOVE(&address_spaces, as, address_spaces_link); address_space_unregister(as); @@ -2684,7 +2770,6 @@ void address_space_destroy(AddressSpace *as) * entries that the guest should never use. Wait for the old * values to expire before freeing the data. */ - as->root =3D root; call_rcu(as, do_address_space_destroy, rcu); } =20 @@ -2816,7 +2901,7 @@ static void mtree_print_mr(fprintf_function mon_print= f, void *f, static void mtree_print_flatview(fprintf_function p, void *f, AddressSpace *as) { - FlatView *view =3D address_space_get_flatview(as); + FlatView *view =3D flatview_get(as->current_map); FlatRange *range =3D &view->ranges[0]; MemoryRegion *mr; int n =3D view->nr; @@ -2873,7 +2958,7 @@ void mtree_info(fprintf_function mon_printf, void *f,= bool flatview) =20 QTAILQ_FOREACH(as, &address_spaces, address_spaces_link) { mon_printf(f, "address-space: %s\n", as->name); - mtree_print_mr(mon_printf, f, as->root, 1, 0, &ml_head); + mtree_print_mr(mon_printf, f, as->current_map->root, 1, 0, &ml_hea= d); mon_printf(f, "\n"); } =20 --=20 2.11.0 From nobody Sat Apr 27 20:51: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 1504776138323453.10804087581596; Thu, 7 Sep 2017 02:22:18 -0700 (PDT) Received: from localhost ([::1]:39515 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dpt0r-00022O-6E for importer@patchew.org; Thu, 07 Sep 2017 05:22:17 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:57112) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dpszB-00010T-CE for qemu-devel@nongnu.org; Thu, 07 Sep 2017 05:20:38 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1dpsz7-0007If-03 for qemu-devel@nongnu.org; Thu, 07 Sep 2017 05:20:33 -0400 Received: from ozlabs.ru ([107.173.13.209]:51158) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dpsz6-0007Hc-LT for qemu-devel@nongnu.org; Thu, 07 Sep 2017 05:20:28 -0400 Received: from vpl1.ozlabs.ibm.com (localhost [IPv6:::1]) by ozlabs.ru (Postfix) with ESMTP id A8CC23A604D5; Thu, 7 Sep 2017 05:21:37 -0400 (EDT) From: Alexey Kardashevskiy To: qemu-devel@nongnu.org Date: Thu, 7 Sep 2017 19:20:10 +1000 Message-Id: <20170907092010.3605-5-aik@ozlabs.ru> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20170907092010.3605-1-aik@ozlabs.ru> References: <20170907092010.3605-1-aik@ozlabs.ru> 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 4/4] memory: Add flat views to HMP "info mtree" 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 , Stefan Hajnoczi , Peter Maydell , David Gibson 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" This adds a new switch to "info mtree" to print dispatch tree internals. Signed-off-by: Alexey Kardashevskiy --- Example: aik@fstn1-p1:~$ echo "info mtree -f -d" | nc localhost 30000 QEMU 2.9.94 monitor - type 'help' for more information (qemu) info mtree -f -d FlatView #0 AS "memory" 0000000000000000-000000007fffffff (prio 0, ram): ppc_spapr.ram AS "cpu-memory" 0000000000000000-000000007fffffff (prio 0, ram): ppc_spapr.ram AS "cpu-memory" 0000000000000000-000000007fffffff (prio 0, ram): ppc_spapr.ram Dispatch Physical sections #0 @0000000000000000 root=3D"(noname)" [unassigned] #1 @0000000000000000 root=3D"(noname)" [not dirty] #2 @0000000000000000 root=3D"(noname)" [ROM] #3 @0000000000000000 root=3D"(noname)" [watch] #4 @0000000000000000 root=3D"ppc_spapr.ram" Nodes (9 bits per level, 6 levels) ptr=3D[3] skip=3D4 [0] 0 skip=3D3 ptr=3D[3] 1..511 skip=3D1 ptr=3DNIL [1] 0 skip=3D2 ptr=3D[3] 1..511 skip=3D1 ptr=3DNIL [2] 0 skip=3D1 ptr=3D[3] 1..511 skip=3D1 ptr=3DNIL [3] 0..1 skip=3D0 ptr=3D#4 2..511 skip=3D1 ptr=3DNIL FlatView #1 AS "I/O" 0000000000000000-000000000000ffff (prio 0, i/o): io Dispatch Physical sections #0 @0000000000000000 root=3D"(noname)" [unassigned] #1 @0000000000000000 root=3D"(noname)" [not dirty] #2 @0000000000000000 root=3D"(noname)" [ROM] #3 @0000000000000000 root=3D"(noname)" [watch] #4 @0000000000000000 root=3D"io" Nodes (9 bits per level, 6 levels) ptr=3D[5] skip=3D6 [0] 0 skip=3D5 ptr=3D[5] 1..511 skip=3D1 ptr=3DNIL [1] 0 skip=3D4 ptr=3D[5] 1..511 skip=3D1 ptr=3DNIL [2] 0 skip=3D3 ptr=3D[5] 1..511 skip=3D1 ptr=3DNIL [3] 0 skip=3D2 ptr=3D[5] 1..511 skip=3D1 ptr=3DNIL [4] 0 skip=3D1 ptr=3D[5] 1..511 skip=3D1 ptr=3DNIL [5] 0..15 skip=3D0 ptr=3D#4 16..511 skip=3D0 ptr=3D#0 FlatView #2 AS "pci@800000020000000" 0000000000000000-000000003fffffff (prio 0, i/o): tce-iommu-80000000 0000040000000000-000004000000ffff (prio 0, i/o): msi Dispatch Physical sections #0 @0000000000000000 root=3D"(noname)" [unassigned] #1 @0000000000000000 root=3D"(noname)" [not dirty] #2 @0000000000000000 root=3D"(noname)" [ROM] #3 @0000000000000000 root=3D"(noname)" [watch] #4 @0000000000000000 root=3D"tce-iommu-80000000" #5 @0000040000000000 root=3D"msi" Nodes (9 bits per level, 6 levels) ptr=3D[2] skip=3D3 [0] 0 skip=3D2 ptr=3D[2] 1..511 skip=3D1 ptr=3DNIL [1] 0 skip=3D1 ptr=3D[2] 1..511 skip=3D1 ptr=3DNIL [2] 0 skip=3D0 ptr=3D#4 1..7 skip=3D1 ptr=3DNIL 8 skip=3D3 ptr=3D[6] 9..511 skip=3D1 ptr=3DNIL [3] 0 skip=3D0 ptr=3D#4 1..511 skip=3D1 ptr=3DNIL [4] 0 skip=3D2 ptr=3D[6] 1..511 skip=3D1 ptr=3DNIL [5] 0 skip=3D1 ptr=3D[6] 1..511 skip=3D1 ptr=3DNIL [6] 0..15 skip=3D0 ptr=3D#5 16..511 skip=3D0 ptr=3D#0 (qemu) --- include/exec/memory.h | 5 +++- exec.c | 66 +++++++++++++++++++++++++++++++++++++++++++++++= ++++ memory.c | 20 ++++++++++++---- monitor.c | 3 ++- hmp-commands-info.hx | 7 +++--- 5 files changed, 92 insertions(+), 9 deletions(-) diff --git a/include/exec/memory.h b/include/exec/memory.h index 41ab165302..2a50bbe79f 100644 --- a/include/exec/memory.h +++ b/include/exec/memory.h @@ -1527,7 +1527,10 @@ void memory_global_dirty_log_start(void); */ void memory_global_dirty_log_stop(void); =20 -void mtree_info(fprintf_function mon_printf, void *f, bool flatview); +void mtree_info(fprintf_function mon_printf, void *f, bool flatview, + bool dispatch_tree); +void mtree_print_dispatch(fprintf_function mon, void *f, + struct AddressSpaceDispatch *d); =20 /** * memory_region_request_mmio_ptr: request a pointer to an mmio diff --git a/exec.c b/exec.c index 51243f57f4..8c565e9102 100644 --- a/exec.c +++ b/exec.c @@ -3605,3 +3605,69 @@ void page_size_init(void) } qemu_host_page_mask =3D -(intptr_t)qemu_host_page_size; } + +static void mtree_print_phys_entries(fprintf_function mon, void *f, + int start, int end, int skip, int ptr) +{ + if (start =3D=3D end - 1) { + mon(f, "\t%3d ", start); + } else { + mon(f, "\t%3d..%-3d ", start, end - 1); + } + mon(f, " skip=3D%d ", skip); + if (ptr =3D=3D PHYS_MAP_NODE_NIL) { + mon(f, " ptr=3DNIL"); + } else if (!skip) { + mon(f, " ptr=3D#%d", ptr); + } else { + mon(f, " ptr=3D[%d]", ptr); + } + mon(f, "\n"); +} + +void mtree_print_dispatch(fprintf_function mon, void *f, + AddressSpaceDispatch *d) +{ + int i; + + mon(f, " Dispatch\n"); + mon(f, " Physical sections\n"); + + for (i =3D 0; i < d->map.sections_nb; ++i) { + MemoryRegionSection *s =3D d->map.sections + i; + const char *names[] =3D { "[unassigned]", "[not dirty]", + "[ROM]", "[watch]" }; + + mon(f, " #%d @%016lX root=3D\"%s\" %s\n", i, + s->offset_within_address_space, + s->mr->name ? s->mr->name : "(noname)", + i < ARRAY_SIZE(names) ? names[i] : ""); + } + + mon(f, " Nodes (%d bits per level, %d levels) ptr=3D[%d] skip=3D%d\= n", + P_L2_BITS, P_L2_LEVELS, d->phys_map.ptr, d->phys_map.skip); + for (i =3D 0; i < d->map.nodes_nb; ++i) { + int j, jprev; + PhysPageEntry prev; + Node *n =3D d->map.nodes + i; + + mon(f, " [%d]\n", i); + + for (j =3D 0, jprev =3D 0, prev =3D *n[0]; j < ARRAY_SIZE(*n); ++j= ) { + PhysPageEntry *pe =3D *n + j; + + if (pe->ptr =3D=3D prev.ptr && pe->skip =3D=3D prev.skip) { + continue; + } + + mtree_print_phys_entries(mon, f, jprev, j, prev.skip, prev.ptr= ); + + jprev =3D j; + prev =3D *pe; + } + + if (jprev !=3D ARRAY_SIZE(*n)) { + mtree_print_phys_entries(mon, f, jprev, j, prev.skip, prev.ptr= ); + } + } +} diff --git a/memory.c b/memory.c index 385a507511..24938036c8 100644 --- a/memory.c +++ b/memory.c @@ -2939,16 +2939,28 @@ static void mtree_print_flatview(fprintf_function p= , void *f, flatview_unref(view); } =20 -void mtree_info(fprintf_function mon_printf, void *f, bool flatview) +void mtree_info(fprintf_function mon_printf, void *f, bool flatview, + bool dispatch_tree) { MemoryRegionListHead ml_head; MemoryRegionList *ml, *ml2; AddressSpace *as; + FlatView *view; + int n; =20 if (flatview) { - QTAILQ_FOREACH(as, &address_spaces, address_spaces_link) { - mon_printf(f, "address-space (flat view): %s\n", as->name); - mtree_print_flatview(mon_printf, f, as); + n =3D 0; + QTAILQ_FOREACH(view, &flat_views, flat_views_link) { + mon_printf(f, "FlatView #%d\n", n); + ++n; + + QTAILQ_FOREACH(as, &view->address_spaces, flat_view_link) { + mon_printf(f, " AS \"%s\"\n", as->name); + mtree_print_flatview(mon_printf, f, as); + } + if (dispatch_tree) { + mtree_print_dispatch(mon_printf, f, view->dispatch); + } mon_printf(f, "\n"); } return; diff --git a/monitor.c b/monitor.c index e0f880107f..191c4b016d 100644 --- a/monitor.c +++ b/monitor.c @@ -1703,8 +1703,9 @@ static void hmp_boot_set(Monitor *mon, const QDict *q= dict) static void hmp_info_mtree(Monitor *mon, const QDict *qdict) { bool flatview =3D qdict_get_try_bool(qdict, "flatview", false); + bool dispatch_tree =3D qdict_get_try_bool(qdict, "dispatch_tree", fals= e); =20 - mtree_info((fprintf_function)monitor_printf, mon, flatview); + mtree_info((fprintf_function)monitor_printf, mon, flatview, dispatch_t= ree); } =20 static void hmp_info_numa(Monitor *mon, const QDict *qdict) diff --git a/hmp-commands-info.hx b/hmp-commands-info.hx index d9df238a5f..3d2edff940 100644 --- a/hmp-commands-info.hx +++ b/hmp-commands-info.hx @@ -249,9 +249,10 @@ ETEXI =20 { .name =3D "mtree", - .args_type =3D "flatview:-f", - .params =3D "[-f]", - .help =3D "show memory tree (-f: dump flat view for address = spaces)", + .args_type =3D "flatview:-f,dispatch_tree:-d", + .params =3D "[-f][-d]", + .help =3D "show memory tree (-f: dump flat view for address = spaces;" + "-d: dump dispatch tree, valid with -f only)", .cmd =3D hmp_info_mtree, }, =20 --=20 2.11.0