From nobody Tue Feb 10 15:29:14 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 1505730267575916.7975275855747; Mon, 18 Sep 2017 03:24:27 -0700 (PDT) Received: from localhost ([::1]:35616 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dttE2-00033W-SB for importer@patchew.org; Mon, 18 Sep 2017 06:24:26 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:42055) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dtt7L-0005ly-SK for qemu-devel@nongnu.org; Mon, 18 Sep 2017 06:17:32 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1dtt7K-0004HC-KL for qemu-devel@nongnu.org; Mon, 18 Sep 2017 06:17:31 -0400 Received: from ozlabs.ru ([107.173.13.209]:35254) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dtt7K-0004Dh-CV for qemu-devel@nongnu.org; Mon, 18 Sep 2017 06:17:30 -0400 Received: from vpl1.ozlabs.ibm.com (localhost [IPv6:::1]) by ozlabs.ru (Postfix) with ESMTP id 2A3C93A60055; Mon, 18 Sep 2017 06:18:44 -0400 (EDT) From: Alexey Kardashevskiy To: qemu-devel@nongnu.org Date: Mon, 18 Sep 2017 20:17:07 +1000 Message-Id: <20170918101709.30421-12-aik@ozlabs.ru> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20170918101709.30421-1-aik@ozlabs.ru> References: <20170918101709.30421-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] [PATCH qemu v3 11/13] memory: Share FlatView's 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 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. Signed-off-by: Alexey Kardashevskiy --- Changes: v3: * got rid of global and per-AS lists of FlatView objects --- I could also make all empty FlatViews (view->nr=3D=3D0 but they are still enabled) resolve to an empty FlatView but not sure it is worth it as in real life all devices and therefore FlatViews are expected not to be empty. --- memory.c | 92 ++++++++++++++++++++++++++++++++++++++++--------------------= ---- 1 file changed, 58 insertions(+), 34 deletions(-) diff --git a/memory.c b/memory.c index e18ef53cc2..6fca8bf932 100644 --- a/memory.c +++ b/memory.c @@ -917,36 +917,66 @@ static void address_space_update_topology_pass(Addres= sSpace *as, } } =20 -static void address_space_update_topology(AddressSpace *as) +static gboolean flatview_unref_g_hash(gpointer key, gpointer value, + gpointer user_data) +{ + flatview_unref((FlatView *) value); + return true; +} + +static void flatview_update_topology(void) { - FlatView *old_view =3D address_space_get_flatview(as); - MemoryRegion *physmr =3D memory_region_unalias_entire(old_view->root); - FlatView *new_view =3D generate_memory_topology(physmr); int i; + AddressSpace *as; + FlatView *old_view, *new_view; + GHashTable *views =3D g_hash_table_new(g_direct_hash, g_direct_equal); + MemoryRegion *physmr; + gpointer key; =20 - new_view->dispatch =3D address_space_dispatch_new(new_view); - for (i =3D 0; i < new_view->nr; i++) { - MemoryRegionSection mrs =3D - section_from_flat_range(&new_view->ranges[i], new_view); - flatview_add_to_dispatch(new_view, &mrs); + /* Render unique FVs */ + QTAILQ_FOREACH(as, &address_spaces, address_spaces_link) { + old_view =3D as->current_map; + physmr =3D memory_region_unalias_entire(old_view->root); + + key =3D !physmr->enabled ? 0 : physmr; + new_view =3D (FlatView *) g_hash_table_lookup(views, key); + if (new_view) { + continue; + } + + new_view =3D generate_memory_topology(physmr); + + new_view->dispatch =3D address_space_dispatch_new(new_view); + for (i =3D 0; i < new_view->nr; i++) { + MemoryRegionSection mrs =3D + section_from_flat_range(&new_view->ranges[i], new_view); + flatview_add_to_dispatch(new_view, &mrs); + } + address_space_dispatch_compact(new_view->dispatch); + + g_hash_table_insert(views, key, new_view); + } + + /* Replace FVs in ASes */ + QTAILQ_FOREACH(as, &address_spaces, address_spaces_link) { + old_view =3D as->current_map; + physmr =3D memory_region_unalias_entire(old_view->root); + + key =3D !physmr->enabled ? 0 : physmr; + new_view =3D (FlatView *) g_hash_table_lookup(views, key); + assert(new_view); + + address_space_update_topology_pass(as, old_view, new_view, false); + address_space_update_topology_pass(as, old_view, new_view, true); + + flatview_ref(new_view); + atomic_rcu_set(&as->current_map, new_view); + flatview_unref(old_view); } - address_space_dispatch_compact(new_view->dispatch); - address_space_update_topology_pass(as, old_view, new_view, false); - address_space_update_topology_pass(as, old_view, new_view, true); - - /* Writes are protected by the BQL. */ - atomic_rcu_set(&as->current_map, new_view); - call_rcu(old_view, flatview_unref, rcu); - - /* 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. - */ - flatview_unref(old_view); - - address_space_update_ioeventfds(as); + + /* Unref FVs from temporary table */ + g_hash_table_foreach_remove(views, flatview_unref_g_hash, 0); + g_hash_table_unref(views); } =20 void memory_region_transaction_begin(void) @@ -966,9 +996,10 @@ void memory_region_transaction_commit(void) if (!memory_region_transaction_depth) { if (memory_region_update_pending) { MEMORY_LISTENER_CALL_GLOBAL(begin, Forward); + flatview_update_topology(); =20 QTAILQ_FOREACH(as, &address_spaces, address_spaces_link) { - address_space_update_topology(as); + address_space_update_ioeventfds(as); } memory_region_update_pending =3D false; MEMORY_LISTENER_CALL_GLOBAL(commit, Forward); @@ -2690,13 +2721,6 @@ AddressSpace *address_space_init_shareable(MemoryReg= ion *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; --=20 2.11.0