From: Liu Ping Fan <pingf...@linux.vnet.ibm.com> Signed-off-by: Liu Ping Fan <pingf...@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