qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Paolo Bonzini <pbonzini@redhat.com>
To: qemu-devel@nongnu.org
Cc: Peter Maydell <peter.maydell@linaro.org>
Subject: [Qemu-devel] [PULL 07/49] exec.c: Collect AddressSpace related fields into a CPUAddressSpace struct
Date: Fri, 16 Oct 2015 10:49:29 +0200	[thread overview]
Message-ID: <1444985411-17803-8-git-send-email-pbonzini@redhat.com> (raw)
In-Reply-To: <1444985411-17803-1-git-send-email-pbonzini@redhat.com>

From: Peter Maydell <peter.maydell@linaro.org>

Gather up all the fields currently in CPUState which deal with the CPU's
AddressSpace into a separate CPUAddressSpace struct. This paves the way
for allowing the CPU to know about more than one AddressSpace.

The rearrangement also allows us to make the MemoryListener a directly
embedded object in the CPUAddressSpace (it could not be embedded in
CPUState because 'struct MemoryListener' isn't defined for the user-only
builds). This allows us to resolve the FIXME in tcg_commit() by going
directly from the MemoryListener to the CPUAddressSpace.

This patch extracts the actual update of the cached dispatch pointer
from cpu_reload_memory_map() (which is renamed accordingly to
cpu_reloading_memory_map() as it is only responsible for breaking
cpu-exec.c's RCU critical section now). This lets us keep the definition
of the CPUAddressSpace struct private to exec.c.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Message-Id: <1443709790-25180-4-git-send-email-peter.maydell@linaro.org>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 cpu-exec-common.c       | 13 +++---------
 exec.c                  | 56 +++++++++++++++++++++++++++++++++----------------
 include/exec/exec-all.h |  2 +-
 include/qemu/typedefs.h |  1 +
 include/qom/cpu.h       |  7 +++++--
 5 files changed, 48 insertions(+), 31 deletions(-)

diff --git a/cpu-exec-common.c b/cpu-exec-common.c
index b95b09a..43edf36 100644
--- a/cpu-exec-common.c
+++ b/cpu-exec-common.c
@@ -37,10 +37,8 @@ void cpu_resume_from_signal(CPUState *cpu, void *puc)
     siglongjmp(cpu->jmp_env, 1);
 }
 
-void cpu_reload_memory_map(CPUState *cpu)
+void cpu_reloading_memory_map(void)
 {
-    AddressSpaceDispatch *d;
-
     if (qemu_in_vcpu_thread()) {
         /* The guest can in theory prolong the RCU critical section as long
          * as it feels like. The major problem with this is that because it
@@ -59,17 +57,12 @@ void cpu_reload_memory_map(CPUState *cpu)
          * part of this callback might become unnecessary.)
          *
          * This pair matches cpu_exec's rcu_read_lock()/rcu_read_unlock(), which
-         * only protects cpu->as->dispatch.  Since we reload it below, we can
-         * split the critical section.
+         * only protects cpu->as->dispatch. Since we know our caller is about
+         * to reload it, it's safe to split the critical section.
          */
         rcu_read_unlock();
         rcu_read_lock();
     }
-
-    /* The CPU and TLB are protected by the iothread lock.  */
-    d = atomic_rcu_read(&cpu->as->dispatch);
-    cpu->memory_dispatch = d;
-    tlb_flush(cpu, 1);
 }
 #endif
 
diff --git a/exec.c b/exec.c
index ab5d8a8..aad94a0 100644
--- a/exec.c
+++ b/exec.c
@@ -161,6 +161,21 @@ static void memory_map_init(void);
 static void tcg_commit(MemoryListener *listener);
 
 static MemoryRegion io_mem_watch;
+
+/**
+ * CPUAddressSpace: all the information a CPU needs about an AddressSpace
+ * @cpu: the CPU whose AddressSpace this is
+ * @as: the AddressSpace itself
+ * @memory_dispatch: its dispatch pointer (cached, RCU protected)
+ * @tcg_as_listener: listener for tracking changes to the AddressSpace
+ */
+struct CPUAddressSpace {
+    CPUState *cpu;
+    AddressSpace *as;
+    struct AddressSpaceDispatch *memory_dispatch;
+    MemoryListener tcg_as_listener;
+};
+
 #endif
 
 #if !defined(CONFIG_USER_ONLY)
@@ -431,7 +446,7 @@ address_space_translate_for_iotlb(CPUState *cpu, hwaddr addr,
                                   hwaddr *xlat, hwaddr *plen)
 {
     MemoryRegionSection *section;
-    section = address_space_translate_internal(cpu->memory_dispatch,
+    section = address_space_translate_internal(cpu->cpu_ases[0].memory_dispatch,
                                                addr, xlat, plen, false);
 
     assert(!section->mr->iommu_ops);
@@ -537,13 +552,16 @@ void tcg_cpu_address_space_init(CPUState *cpu, AddressSpace *as)
     /* We only support one address space per cpu at the moment.  */
     assert(cpu->as == as);
 
-    if (cpu->tcg_as_listener) {
-        memory_listener_unregister(cpu->tcg_as_listener);
-    } else {
-        cpu->tcg_as_listener = g_new0(MemoryListener, 1);
+    if (cpu->cpu_ases) {
+        /* We've already registered the listener for our only AS */
+        return;
     }
-    cpu->tcg_as_listener->commit = tcg_commit;
-    memory_listener_register(cpu->tcg_as_listener, as);
+
+    cpu->cpu_ases = g_new0(CPUAddressSpace, 1);
+    cpu->cpu_ases[0].cpu = cpu;
+    cpu->cpu_ases[0].as = as;
+    cpu->cpu_ases[0].tcg_as_listener.commit = tcg_commit;
+    memory_listener_register(&cpu->cpu_ases[0].tcg_as_listener, as);
 }
 #endif
 
@@ -2218,7 +2236,8 @@ static uint16_t dummy_section(PhysPageMap *map, AddressSpace *as,
 
 MemoryRegion *iotlb_to_region(CPUState *cpu, hwaddr index)
 {
-    AddressSpaceDispatch *d = atomic_rcu_read(&cpu->memory_dispatch);
+    CPUAddressSpace *cpuas = &cpu->cpu_ases[0];
+    AddressSpaceDispatch *d = atomic_rcu_read(&cpuas->memory_dispatch);
     MemoryRegionSection *sections = d->map.sections;
 
     return sections[index & ~TARGET_PAGE_MASK].mr;
@@ -2277,19 +2296,20 @@ static void mem_commit(MemoryListener *listener)
 
 static void tcg_commit(MemoryListener *listener)
 {
-    CPUState *cpu;
+    CPUAddressSpace *cpuas;
+    AddressSpaceDispatch *d;
 
     /* since each CPU stores ram addresses in its TLB cache, we must
        reset the modified entries */
-    /* XXX: slow ! */
-    CPU_FOREACH(cpu) {
-        /* FIXME: Disentangle the cpu.h circular files deps so we can
-           directly get the right CPU from listener.  */
-        if (cpu->tcg_as_listener != listener) {
-            continue;
-        }
-        cpu_reload_memory_map(cpu);
-    }
+    cpuas = container_of(listener, CPUAddressSpace, tcg_as_listener);
+    cpu_reloading_memory_map();
+    /* The CPU and TLB are protected by the iothread lock.
+     * We reload the dispatch pointer now because cpu_reloading_memory_map()
+     * may have split the RCU critical section.
+     */
+    d = atomic_rcu_read(&cpuas->as->dispatch);
+    cpuas->memory_dispatch = d;
+    tlb_flush(cpuas->cpu, 1);
 }
 
 void address_space_init_dispatch(AddressSpace *as)
diff --git a/include/exec/exec-all.h b/include/exec/exec-all.h
index a63fd60..4e8afbf 100644
--- a/include/exec/exec-all.h
+++ b/include/exec/exec-all.h
@@ -85,7 +85,7 @@ void QEMU_NORETURN cpu_loop_exit_restore(CPUState *cpu, uintptr_t pc);
 
 #if !defined(CONFIG_USER_ONLY)
 bool qemu_in_vcpu_thread(void);
-void cpu_reload_memory_map(CPUState *cpu);
+void cpu_reloading_memory_map(void);
 void tcg_cpu_address_space_init(CPUState *cpu, AddressSpace *as);
 /* cputlb.c */
 /**
diff --git a/include/qemu/typedefs.h b/include/qemu/typedefs.h
index ee1ce1d..d4a8f7a 100644
--- a/include/qemu/typedefs.h
+++ b/include/qemu/typedefs.h
@@ -16,6 +16,7 @@ typedef struct BusClass BusClass;
 typedef struct BusState BusState;
 typedef struct CharDriverState CharDriverState;
 typedef struct CompatProperty CompatProperty;
+typedef struct CPUAddressSpace CPUAddressSpace;
 typedef struct DeviceState DeviceState;
 typedef struct DeviceListener DeviceListener;
 typedef struct DisplayChangeListener DisplayChangeListener;
diff --git a/include/qom/cpu.h b/include/qom/cpu.h
index b613ff0..51a1323 100644
--- a/include/qom/cpu.h
+++ b/include/qom/cpu.h
@@ -234,6 +234,10 @@ struct kvm_run;
  * @can_do_io: Nonzero if memory-mapped IO is safe. Deterministic execution
  * requires that IO only be performed on the last instruction of a TB
  * so that interrupts take effect immediately.
+ * @cpu_ases: Pointer to array of CPUAddressSpaces (which define the
+ *            AddressSpaces this CPU has)
+ * @as: Pointer to the first AddressSpace, for the convenience of targets which
+ *      only have a single AddressSpace
  * @env_ptr: Pointer to subclass-specific CPUArchState field.
  * @current_tb: Currently executing TB.
  * @gdb_regs: Additional GDB registers.
@@ -280,9 +284,8 @@ struct CPUState {
     QemuMutex work_mutex;
     struct qemu_work_item *queued_work_first, *queued_work_last;
 
+    CPUAddressSpace *cpu_ases;
     AddressSpace *as;
-    struct AddressSpaceDispatch *memory_dispatch;
-    MemoryListener *tcg_as_listener;
 
     void *env_ptr; /* CPUArchState */
     struct TranslationBlock *current_tb;
-- 
2.5.0

  parent reply	other threads:[~2015-10-16  8:50 UTC|newest]

Thread overview: 52+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-10-16  8:49 [Qemu-devel] [PULL 00/49] Misc patches for 2015-10-16 Paolo Bonzini
2015-10-16  8:49 ` [Qemu-devel] [PULL 01/49] nbd: switch from g_slice allocator to malloc Paolo Bonzini
2015-10-16  8:49 ` [Qemu-devel] [PULL 02/49] scsi: " Paolo Bonzini
2015-10-16  8:49 ` [Qemu-devel] [PULL 03/49] megasas: fix megasas_get_sata_addr Paolo Bonzini
2015-10-16  8:49 ` [Qemu-devel] [PULL 04/49] configure: Require Python 2.6 Paolo Bonzini
2015-10-16  8:49 ` [Qemu-devel] [PULL 05/49] exec.c: Don't call cpu_reload_memory_map() from cpu_exec_init() Paolo Bonzini
2015-10-16  8:49 ` [Qemu-devel] [PULL 06/49] cpu-exec-common.c: Clarify comment about cpu_reload_memory_map()'s RCU operations Paolo Bonzini
2015-10-16  8:49 ` Paolo Bonzini [this message]
2015-10-16  8:49 ` [Qemu-devel] [PULL 08/49] checkpatch: allow open braces on typedef lines Paolo Bonzini
2015-10-16  8:49 ` [Qemu-devel] [PULL 09/49] linux-headers: update from kvm/next Paolo Bonzini
2015-10-16  8:49 ` [Qemu-devel] [PULL 10/49] target-i386/kvm: Hyper-V HV_X64_MSR_RESET support Paolo Bonzini
2015-10-16  8:49 ` [Qemu-devel] [PULL 11/49] target-i386/kvm: set Hyper-V features cpuid bit HV_X64_MSR_VP_INDEX_AVAILABLE Paolo Bonzini
2015-10-16  8:49 ` [Qemu-devel] [PULL 12/49] target-i386/kvm: Hyper-V HV_X64_MSR_VP_RUNTIME support Paolo Bonzini
2015-10-16  8:49 ` [Qemu-devel] [PULL 13/49] exec: remove non-TCG stuff from exec-all.h header Paolo Bonzini
2015-10-16  8:49 ` [Qemu-devel] [PULL 14/49] kvm-all: Align to qemu_real_host_page_size in kvm_set_phys_mem Paolo Bonzini
2015-10-16  8:49 ` [Qemu-devel] [PULL 15/49] checkpatch: port fix from kernel "## is not a valid modifier" Paolo Bonzini
2015-10-16  8:49 ` [Qemu-devel] [PULL 16/49] MAINTAINERS: add two devices to the e500 section Paolo Bonzini
2015-10-16  8:49 ` [Qemu-devel] [PULL 18/49] MAINTAINERS: Add more pxa2xx files and boards Paolo Bonzini
2015-10-16  8:49 ` [Qemu-devel] [PULL 19/49] MAINTAINERS: Add maintainer for ARM PrimeCell and integrated devices Paolo Bonzini
2015-10-16  8:49 ` [Qemu-devel] [PULL 20/49] MAINTAINERS: Add more devices to realview board Paolo Bonzini
2015-10-16  8:49 ` [Qemu-devel] [PULL 21/49] qemu-sockets: fix conversion of ipv4/ipv6 JSON to QemuOpts Paolo Bonzini
2015-10-16  8:49 ` [Qemu-devel] [PULL 22/49] README: fill out some useful quickstart information Paolo Bonzini
2015-10-16  8:49 ` [Qemu-devel] [PULL 23/49] qemu-char: cleanup qmp_chardev_add Paolo Bonzini
2015-10-16  8:49 ` [Qemu-devel] [PULL 24/49] qemu-char: cleanup HAVE_CHARDEV_* Paolo Bonzini
2015-10-16  8:49 ` [Qemu-devel] [PULL 25/49] qemu-char: add create to register_char_driver Paolo Bonzini
2015-10-16  8:49 ` [Qemu-devel] [PULL 26/49] qemu-char: convert file backend to data-driven creation Paolo Bonzini
2015-10-16  8:49 ` [Qemu-devel] [PULL 27/49] qemu-char: convert serial " Paolo Bonzini
2015-10-16  8:49 ` [Qemu-devel] [PULL 28/49] qemu-char: convert parallel " Paolo Bonzini
2015-10-16  8:49 ` [Qemu-devel] [PULL 29/49] qemu-char: convert pipe " Paolo Bonzini
2015-10-16  8:49 ` [Qemu-devel] [PULL 30/49] qemu-char: convert socket " Paolo Bonzini
2015-10-16  8:49 ` [Qemu-devel] [PULL 31/49] qemu-char: convert UDP " Paolo Bonzini
2015-10-16  8:49 ` [Qemu-devel] [PULL 32/49] qemu-char: convert pty " Paolo Bonzini
2015-10-16  8:49 ` [Qemu-devel] [PULL 33/49] qemu-char: convert null " Paolo Bonzini
2015-10-16  8:49 ` [Qemu-devel] [PULL 34/49] qemu-char: convert mux " Paolo Bonzini
2015-10-16  8:49 ` [Qemu-devel] [PULL 35/49] qemu-char: convert msmouse " Paolo Bonzini
2015-10-16  8:49 ` [Qemu-devel] [PULL 36/49] qemu-char: convert braille " Paolo Bonzini
2015-10-16  8:49 ` [Qemu-devel] [PULL 37/49] qemu-char: convert testdev " Paolo Bonzini
2015-10-16 12:23   ` Eric Blake
2015-10-16  8:50 ` [Qemu-devel] [PULL 38/49] qemu-char: convert stdio " Paolo Bonzini
2015-10-16  8:50 ` [Qemu-devel] [PULL 39/49] qemu-char: convert console " Paolo Bonzini
2015-10-16  8:50 ` [Qemu-devel] [PULL 40/49] qemu-char: convert spice " Paolo Bonzini
2015-10-16  8:50 ` [Qemu-devel] [PULL 41/49] qemu-char: convert vc " Paolo Bonzini
2015-10-16  8:50 ` [Qemu-devel] [PULL 42/49] qemu-char: convert ringbuf " Paolo Bonzini
2015-10-16  8:50 ` [Qemu-devel] [PULL 43/49] qemu-char: cleanup after completed conversion to cd->create Paolo Bonzini
2015-10-16  8:50 ` [Qemu-devel] [PULL 44/49] doc/rcu: fix g_free_rcu() usage example Paolo Bonzini
2015-10-16  8:50 ` [Qemu-devel] [PULL 45/49] kvm: Make KVM_CAP_SIGNAL_MSI globally available Paolo Bonzini
2015-10-16  8:50 ` [Qemu-devel] [PULL 46/49] hw/pci: Introduce pci_requester_id() Paolo Bonzini
2015-10-16  8:50 ` [Qemu-devel] [PULL 47/49] kvm: Pass PCI device pointer to MSI routing functions Paolo Bonzini
2015-10-16  8:50 ` [Qemu-devel] [PULL 48/49] kvm: Move x86-specific functions into target-i386/kvm.c Paolo Bonzini
2015-10-16  8:50 ` [Qemu-devel] [PULL 49/49] kvm: Allow the Hyper-V vendor ID to be specified Paolo Bonzini
2015-10-16 15:26 ` [Qemu-devel] [PULL 00/49] Misc patches for 2015-10-16 Paolo Bonzini
2015-10-18 16:55   ` Peter Maydell

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1444985411-17803-8-git-send-email-pbonzini@redhat.com \
    --to=pbonzini@redhat.com \
    --cc=peter.maydell@linaro.org \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).