qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Liu Ping Fan <qemulist@gmail.com>
To: qemu-devel@nongnu.org
Cc: Vasilis Liaskovitis <vasilis.liaskovitis@profitbricks.com>,
	Stefan Hajnoczi <stefanha@gmail.com>, Avi Kivity <avi@redhat.com>,
	Anthony Liguori <anthony@codemonkey.ws>
Subject: [Qemu-devel] [RFC v1 3/3] make address_space_map safe
Date: Fri,  9 Nov 2012 11:14:30 +0800	[thread overview]
Message-ID: <1352430870-10129-4-git-send-email-qemulist@gmail.com> (raw)
In-Reply-To: <1352430870-10129-1-git-send-email-qemulist@gmail.com>

From: Liu Ping Fan <pingfank@linux.vnet.ibm.com>

Signed-off-by: Liu Ping Fan <pingfank@linux.vnet.ibm.com>
---
 cpu-common.h      |    8 ++++++--
 cputlb.c          |    4 ++--
 dma-helpers.c     |    4 +++-
 dma.h             |    5 ++++-
 exec.c            |   45 +++++++++++++++++++++++++++++++++++++--------
 memory.h          |    4 +++-
 target-i386/kvm.c |    4 ++--
 7 files changed, 57 insertions(+), 17 deletions(-)

diff --git a/cpu-common.h b/cpu-common.h
index 69c1d7a..f257dfc 100644
--- a/cpu-common.h
+++ b/cpu-common.h
@@ -45,8 +45,8 @@ void *qemu_ram_ptr_length(ram_addr_t addr, ram_addr_t *size);
 void *qemu_safe_ram_ptr(ram_addr_t addr);
 void qemu_put_ram_ptr(void *addr);
 /* This should not be used by devices.  */
-int qemu_ram_addr_from_host(void *ptr, ram_addr_t *ram_addr);
-ram_addr_t qemu_ram_addr_from_host_nofail(void *ptr);
+int qemu_ram_addr_from_host(void *ptr, ram_addr_t *ram_addr, bool unmap);
+ram_addr_t qemu_ram_addr_from_host_nofail(void *ptr, bool unmap);
 void qemu_ram_set_idstr(ram_addr_t addr, const char *name, DeviceState *dev);
 
 void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf,
@@ -64,6 +64,10 @@ static inline void cpu_physical_memory_write(target_phys_addr_t addr,
 {
     cpu_physical_memory_rw(addr, (void *)buf, len, 1);
 }
+void *cpu_physical_memory_map_safe(target_phys_addr_t addr,
+                              target_phys_addr_t *plen,
+                              int is_write,
+                              bool *safe);
 void *cpu_physical_memory_map(target_phys_addr_t addr,
                               target_phys_addr_t *plen,
                               int is_write);
diff --git a/cputlb.c b/cputlb.c
index 9027557..a78ba02 100644
--- a/cputlb.c
+++ b/cputlb.c
@@ -164,7 +164,7 @@ static inline void tlb_update_dirty(CPUTLBEntry *tlb_entry)
     if (tlb_is_dirty_ram(tlb_entry)) {
         p = (void *)(uintptr_t)((tlb_entry->addr_write & TARGET_PAGE_MASK)
             + tlb_entry->addend);
-        ram_addr = qemu_ram_addr_from_host_nofail(p);
+        ram_addr = qemu_ram_addr_from_host_nofail(p, false);
         if (!cpu_physical_memory_is_dirty(ram_addr)) {
             tlb_entry->addr_write |= TLB_NOTDIRTY;
         }
@@ -338,7 +338,7 @@ tb_page_addr_t get_page_addr_code(CPUArchState *env1, target_ulong addr)
 #endif
     }
     p = (void *)((uintptr_t)addr + env1->tlb_table[mmu_idx][page_index].addend);
-    return qemu_ram_addr_from_host_nofail(p);
+    return qemu_ram_addr_from_host_nofail(p, false);
 }
 
 #define MMUSUFFIX _cmmu
diff --git a/dma-helpers.c b/dma-helpers.c
index 3f09dcb..6f6e3b7 100644
--- a/dma-helpers.c
+++ b/dma-helpers.c
@@ -394,6 +394,7 @@ void *iommu_dma_memory_map(DMAContext *dma, dma_addr_t addr, dma_addr_t *len,
     int err;
     target_phys_addr_t paddr, plen;
     void *buf;
+    bool safe;
 
     if (dma->map) {
         return dma->map(dma, addr, len, dir);
@@ -414,7 +415,8 @@ void *iommu_dma_memory_map(DMAContext *dma, dma_addr_t addr, dma_addr_t *len,
         *len = plen;
     }
 
-    buf = address_space_map(dma->as, paddr, &plen, dir == DMA_DIRECTION_FROM_DEVICE);
+    buf = address_space_map(dma->as, paddr, &plen,
+                        dir == DMA_DIRECTION_FROM_DEVICE, &safe);
     *len = plen;
 
     return buf;
diff --git a/dma.h b/dma.h
index 1bd6f4a..9d67dab 100644
--- a/dma.h
+++ b/dma.h
@@ -176,11 +176,14 @@ static inline void *dma_memory_map(DMAContext *dma,
                                    dma_addr_t addr, dma_addr_t *len,
                                    DMADirection dir)
 {
+    bool safe;
+
     if (!dma_has_iommu(dma)) {
         target_phys_addr_t xlen = *len;
         void *p;
 
-        p = address_space_map(dma->as, addr, &xlen, dir == DMA_DIRECTION_FROM_DEVICE);
+        p = address_space_map(dma->as, addr, &xlen,
+                        dir == DMA_DIRECTION_FROM_DEVICE, &safe);
         *len = xlen;
         return p;
     } else {
diff --git a/exec.c b/exec.c
index e5f1c0f..e9bd695 100644
--- a/exec.c
+++ b/exec.c
@@ -2847,7 +2847,14 @@ void qemu_put_ram_ptr(void *addr)
     trace_qemu_put_ram_ptr(addr);
 }
 
-int qemu_ram_addr_from_host(void *ptr, ram_addr_t *ram_addr)
+static void memory_region_unref(MemoryRegion *mr)
+{
+    if (mr->ops && mr->ops->unref) {
+        mr->ops->unref(mr);
+    }
+}
+
+int qemu_ram_addr_from_host(void *ptr, ram_addr_t *ram_addr, bool unmap)
 {
     RAMBlock *block;
     uint8_t *host = ptr;
@@ -2866,6 +2873,9 @@ int qemu_ram_addr_from_host(void *ptr, ram_addr_t *ram_addr)
         if (host - block->host < block->length) {
             *ram_addr = block->offset + (host - block->host);
             qemu_mutex_unlock(&ram_list.lock);
+            if (unmap) {
+                memory_region_unref(block->mr);
+            }
             return 0;
         }
     }
@@ -2876,11 +2886,11 @@ int qemu_ram_addr_from_host(void *ptr, ram_addr_t *ram_addr)
 
 /* Some of the softmmu routines need to translate from a host pointer
    (typically a TLB entry) back to a ram offset.  */
-ram_addr_t qemu_ram_addr_from_host_nofail(void *ptr)
+ram_addr_t qemu_ram_addr_from_host_nofail(void *ptr, bool unmap)
 {
     ram_addr_t ram_addr;
 
-    if (qemu_ram_addr_from_host(ptr, &ram_addr)) {
+    if (qemu_ram_addr_from_host(ptr, &ram_addr, unmap)) {
         fprintf(stderr, "Bad ram pointer %p\n", ptr);
         abort();
     }
@@ -3762,7 +3772,8 @@ static void cpu_notify_map_clients(void)
 void *address_space_map(AddressSpace *as,
                         target_phys_addr_t addr,
                         target_phys_addr_t *plen,
-                        bool is_write)
+                        bool is_write,
+                        bool *safe)
 {
     target_phys_addr_t len = *plen;
     target_phys_addr_t todo = 0;
@@ -3778,7 +3789,8 @@ void *address_space_map(AddressSpace *as,
         l = (page + TARGET_PAGE_SIZE) - addr;
         if (l > len)
             l = len;
-        address_space_section_lookup_ref(as, page >> TARGET_PAGE_BITS, &mr_obj);
+        *safe = address_space_section_lookup_ref(as, page >> TARGET_PAGE_BITS,
+                &mr_obj);
         section = &mr_obj;
 
         if (!(memory_region_is_ram(section->mr) && !section->readonly)) {
@@ -3805,7 +3817,10 @@ void *address_space_map(AddressSpace *as,
         len -= l;
         addr += l;
         todo += l;
-        memory_region_section_unref(&mr_obj);
+        /* len <= 0,release when unmapped */
+        if (len > 0) {
+            memory_region_section_unref(&mr_obj);
+        }
     }
     rlen = todo;
     ret = qemu_ram_ptr_length(raddr, &rlen);
@@ -3822,7 +3837,8 @@ void address_space_unmap(AddressSpace *as, void *buffer, target_phys_addr_t len,
 {
     if (buffer != bounce.buffer) {
         if (is_write) {
-            ram_addr_t addr1 = qemu_ram_addr_from_host_nofail(buffer);
+            /* Will release RAM refcnt */
+            ram_addr_t addr1 = qemu_ram_addr_from_host_nofail(buffer, true);
             while (access_len) {
                 unsigned l;
                 l = TARGET_PAGE_SIZE;
@@ -3847,11 +3863,24 @@ void address_space_unmap(AddressSpace *as, void *buffer, target_phys_addr_t len,
     cpu_notify_map_clients();
 }
 
+void *cpu_physical_memory_map_safe(target_phys_addr_t addr,
+                              target_phys_addr_t *plen,
+                              int is_write,
+                              bool *safe)
+{
+
+    return address_space_map(&address_space_memory, addr, plen, is_write,
+           safe);
+}
+
 void *cpu_physical_memory_map(target_phys_addr_t addr,
                               target_phys_addr_t *plen,
                               int is_write)
 {
-    return address_space_map(&address_space_memory, addr, plen, is_write);
+    bool safe;
+
+    return address_space_map(&address_space_memory, addr, plen, is_write,
+           &safe);
 }
 
 void cpu_physical_memory_unmap(void *buffer, target_phys_addr_t len,
diff --git a/memory.h b/memory.h
index 704d014..c9d8a04 100644
--- a/memory.h
+++ b/memory.h
@@ -863,9 +863,11 @@ void address_space_read(AddressSpace *as, target_phys_addr_t addr, uint8_t *buf,
  * @addr: address within that address space
  * @plen: pointer to length of buffer; updated on return
  * @is_write: indicates the transfer direction
+ * @safe: indicates the mapped addr can be safely across big lock or not
  */
 void *address_space_map(AddressSpace *as, target_phys_addr_t addr,
-                        target_phys_addr_t *plen, bool is_write);
+                        target_phys_addr_t *plen, bool is_write,
+                        bool *safe);
 
 /* address_space_unmap: Unmaps a memory region previously mapped by address_space_map()
  *
diff --git a/target-i386/kvm.c b/target-i386/kvm.c
index 5b18383..40f40c4 100644
--- a/target-i386/kvm.c
+++ b/target-i386/kvm.c
@@ -261,7 +261,7 @@ int kvm_arch_on_sigbus_vcpu(CPUX86State *env, int code, void *addr)
 
     if ((env->mcg_cap & MCG_SER_P) && addr
         && (code == BUS_MCEERR_AR || code == BUS_MCEERR_AO)) {
-        if (qemu_ram_addr_from_host(addr, &ram_addr) ||
+        if (qemu_ram_addr_from_host(addr, &ram_addr, false) ||
             !kvm_physical_memory_addr_from_host(env->kvm_state, addr, &paddr)) {
             fprintf(stderr, "Hardware memory error for memory used by "
                     "QEMU itself instead of guest system!\n");
@@ -293,7 +293,7 @@ int kvm_arch_on_sigbus(int code, void *addr)
         target_phys_addr_t paddr;
 
         /* Hope we are lucky for AO MCE */
-        if (qemu_ram_addr_from_host(addr, &ram_addr) ||
+        if (qemu_ram_addr_from_host(addr, &ram_addr, false) ||
             !kvm_physical_memory_addr_from_host(first_cpu->kvm_state, addr,
                                                 &paddr)) {
             fprintf(stderr, "Hardware memory error for memory used by "
-- 
1.7.4.4

  parent reply	other threads:[~2012-11-09  3:14 UTC|newest]

Thread overview: 12+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-11-09  3:14 [Qemu-devel] [RFC v1 0/3] make address_space_map() safe without biglock's protection Liu Ping Fan
2012-11-09  3:14 ` [Qemu-devel] [RFC v1 1/3] bouce buffer has fine grain lock Liu Ping Fan
2012-11-10  1:49   ` Paolo Bonzini
2012-11-12  6:23     ` liu ping fan
2012-11-12  8:53       ` Paolo Bonzini
2012-11-09  3:14 ` [Qemu-devel] [RFC v1 2/3] ramlist: apply fine grain lock for ram_list Liu Ping Fan
2012-11-10  1:54   ` Paolo Bonzini
2012-11-12  6:22     ` liu ping fan
2012-11-12  8:48       ` Paolo Bonzini
2012-11-13  6:07         ` liu ping fan
2012-11-09  3:14 ` Liu Ping Fan [this message]
     [not found]   ` <20130213121214.GC4576@dhcp-192-168-178-175.profitbricks.localdomain>
2013-03-07  1:59     ` [Qemu-devel] [RFC v1 3/3] make address_space_map safe liu ping fan

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=1352430870-10129-4-git-send-email-qemulist@gmail.com \
    --to=qemulist@gmail.com \
    --cc=anthony@codemonkey.ws \
    --cc=avi@redhat.com \
    --cc=qemu-devel@nongnu.org \
    --cc=stefanha@gmail.com \
    --cc=vasilis.liaskovitis@profitbricks.com \
    /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).