[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [RFC v1 3/3] make address_space_map safe
From: |
Liu Ping Fan |
Subject: |
[Qemu-devel] [RFC v1 3/3] make address_space_map safe |
Date: |
Fri, 9 Nov 2012 11:14:30 +0800 |
From: Liu Ping Fan <address@hidden>
Signed-off-by: Liu Ping Fan <address@hidden>
---
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
[Qemu-devel] [RFC v1 3/3] make address_space_map safe,
Liu Ping Fan <=