diff --git a/cpu-all.h b/cpu-all.h index f2f8aac886..6094e446ca 100644 --- a/cpu-all.h +++ b/cpu-all.h @@ -908,6 +908,9 @@ ram_addr_t qemu_ram_alloc(ram_addr_t); void qemu_ram_free(ram_addr_t addr); /* This should only be used for ram local to a device. */ void *qemu_get_ram_ptr(ram_addr_t addr); +/* This should not be used by devices. */ +ram_addr_t qemu_ram_addr_from_host(void *ptr); + int cpu_register_io_memory(int io_index, CPUReadMemoryFunc **mem_read, CPUWriteMemoryFunc **mem_write, diff --git a/exec-all.h b/exec-all.h index 33ccb7b445..0afaae86d1 100644 --- a/exec-all.h +++ b/exec-all.h @@ -316,6 +316,7 @@ static inline target_ulong get_phys_addr_code(CPUState *env1, target_ulong addr) static inline target_ulong get_phys_addr_code(CPUState *env1, target_ulong addr) { int mmu_idx, page_index, pd; + void *p; page_index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1); mmu_idx = cpu_mmu_index(env1); @@ -331,7 +332,9 @@ static inline target_ulong get_phys_addr_code(CPUState *env1, target_ulong addr) cpu_abort(env1, "Trying to execute code outside RAM or ROM at 0x" TARGET_FMT_lx "\n", addr); #endif } - return addr + env1->tlb_table[mmu_idx][page_index].addend - (unsigned long)phys_ram_base; + p = (void *)(unsigned long)addr + + env1->tlb_table[mmu_idx][page_index].addend; + return qemu_ram_addr_from_host(p); } /* Deterministic execution requires that IO only be performed on the last diff --git a/exec.c b/exec.c index 9671199a19..eda3bf3fa3 100644 --- a/exec.c +++ b/exec.c @@ -1835,6 +1835,7 @@ static inline void tlb_reset_dirty_range(CPUTLBEntry *tlb_entry, } } +/* Note: start and end must be within the same ram block. */ void cpu_physical_memory_reset_dirty(ram_addr_t start, ram_addr_t end, int dirty_flags) { @@ -1869,7 +1870,14 @@ void cpu_physical_memory_reset_dirty(ram_addr_t start, ram_addr_t end, /* we modify the TLB cache so that the dirty bit will be set again when accessing the range */ - start1 = start + (unsigned long)phys_ram_base; + start1 = (unsigned long)qemu_get_ram_ptr(start); + /* Chek that we don't span multiple blocks - this breaks the + address comparisons below. */ + if ((unsigned long)qemu_get_ram_ptr(end - 1) - start1 + != (end - 1) - start) { + abort(); + } + for(env = first_cpu; env != NULL; env = env->next_cpu) { for(i = 0; i < CPU_TLB_SIZE; i++) tlb_reset_dirty_range(&env->tlb_table[0][i], start1, length); @@ -1910,10 +1918,12 @@ void cpu_physical_sync_dirty_bitmap(target_phys_addr_t start_addr, target_phys_a static inline void tlb_update_dirty(CPUTLBEntry *tlb_entry) { ram_addr_t ram_addr; + void *p; if ((tlb_entry->addr_write & ~TARGET_PAGE_MASK) == IO_MEM_RAM) { - ram_addr = (tlb_entry->addr_write & TARGET_PAGE_MASK) + - tlb_entry->addend - (unsigned long)phys_ram_base; + p = (void *)(unsigned long)((tlb_entry->addr_write & TARGET_PAGE_MASK) + + tlb_entry->addend); + ram_addr = qemu_ram_addr_from_host(p); if (!cpu_physical_memory_is_dirty(ram_addr)) { tlb_entry->addr_write |= TLB_NOTDIRTY; } @@ -2005,7 +2015,7 @@ int tlb_set_page_exec(CPUState *env, target_ulong vaddr, /* IO memory case (romd handled later) */ address |= TLB_MMIO; } - addend = (unsigned long)phys_ram_base + (pd & TARGET_PAGE_MASK); + addend = (unsigned long)qemu_get_ram_ptr(pd & TARGET_PAGE_MASK); if ((pd & ~TARGET_PAGE_MASK) <= IO_MEM_ROM) { /* Normal RAM. */ iotlb = pd & TARGET_PAGE_MASK; @@ -2428,13 +2438,25 @@ void qemu_ram_free(ram_addr_t addr) } /* Return a host pointer to ram allocated with qemu_ram_alloc. - This may only be used if you actually allocated the ram, and - aready know how but the ram block is. */ + With the exception of the softmmu code in this file, this should + only be used for local memory (e.g. video ram) that the device owns, + and knows it isn't going to access beyond the end of the block. + + It should not be used for general purpose DMA. + Use cpu_physical_memory_map/cpu_physical_memory_rw instead. + */ void *qemu_get_ram_ptr(ram_addr_t addr) { return phys_ram_base + 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(void *ptr) +{ + return (uint8_t *)ptr - phys_ram_base; +} + static uint32_t unassigned_mem_readb(void *opaque, target_phys_addr_t addr) { #ifdef DEBUG_UNASSIGNED @@ -2521,7 +2543,7 @@ static void notdirty_mem_writeb(void *opaque, target_phys_addr_t ram_addr, dirty_flags = phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS]; #endif } - stb_p(phys_ram_base + ram_addr, val); + stb_p(qemu_get_ram_ptr(ram_addr), val); #ifdef USE_KQEMU if (cpu_single_env->kqemu_enabled && (dirty_flags & KQEMU_MODIFY_PAGE_MASK) != KQEMU_MODIFY_PAGE_MASK) @@ -2546,7 +2568,7 @@ static void notdirty_mem_writew(void *opaque, target_phys_addr_t ram_addr, dirty_flags = phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS]; #endif } - stw_p(phys_ram_base + ram_addr, val); + stw_p(qemu_get_ram_ptr(ram_addr), val); #ifdef USE_KQEMU if (cpu_single_env->kqemu_enabled && (dirty_flags & KQEMU_MODIFY_PAGE_MASK) != KQEMU_MODIFY_PAGE_MASK) @@ -2571,7 +2593,7 @@ static void notdirty_mem_writel(void *opaque, target_phys_addr_t ram_addr, dirty_flags = phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS]; #endif } - stl_p(phys_ram_base + ram_addr, val); + stl_p(qemu_get_ram_ptr(ram_addr), val); #ifdef USE_KQEMU if (cpu_single_env->kqemu_enabled && (dirty_flags & KQEMU_MODIFY_PAGE_MASK) != KQEMU_MODIFY_PAGE_MASK) @@ -3030,7 +3052,7 @@ void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf, unsigned long addr1; addr1 = (pd & TARGET_PAGE_MASK) + (addr & ~TARGET_PAGE_MASK); /* RAM case */ - ptr = phys_ram_base + addr1; + ptr = qemu_get_ram_ptr(addr1); memcpy(ptr, buf, l); if (!cpu_physical_memory_is_dirty(addr1)) { /* invalidate code */ @@ -3066,7 +3088,7 @@ void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf, } } else { /* RAM case */ - ptr = phys_ram_base + (pd & TARGET_PAGE_MASK) + + ptr = qemu_get_ram_ptr(pd & TARGET_PAGE_MASK) + (addr & ~TARGET_PAGE_MASK); memcpy(buf, ptr, l); } @@ -3107,7 +3129,7 @@ void cpu_physical_memory_write_rom(target_phys_addr_t addr, unsigned long addr1; addr1 = (pd & TARGET_PAGE_MASK) + (addr & ~TARGET_PAGE_MASK); /* ROM/RAM case */ - ptr = phys_ram_base + addr1; + ptr = qemu_get_ram_ptr(addr1); memcpy(ptr, buf, l); } len -= l; @@ -3207,7 +3229,7 @@ void *cpu_physical_memory_map(target_phys_addr_t addr, ptr = bounce.buffer; } else { addr1 = (pd & TARGET_PAGE_MASK) + (addr & ~TARGET_PAGE_MASK); - ptr = phys_ram_base + addr1; + ptr = qemu_get_ram_ptr(addr1); } if (!done) { ret = ptr; @@ -3232,7 +3254,7 @@ void cpu_physical_memory_unmap(void *buffer, target_phys_addr_t len, { if (buffer != bounce.buffer) { if (is_write) { - unsigned long addr1 = (uint8_t *)buffer - phys_ram_base; + ram_addr_t addr1 = qemu_ram_addr_from_host(buffer); while (access_len) { unsigned l; l = TARGET_PAGE_SIZE; @@ -3284,7 +3306,7 @@ uint32_t ldl_phys(target_phys_addr_t addr) val = io_mem_read[io_index][2](io_mem_opaque[io_index], addr); } else { /* RAM case */ - ptr = phys_ram_base + (pd & TARGET_PAGE_MASK) + + ptr = qemu_get_ram_ptr(pd & TARGET_PAGE_MASK) + (addr & ~TARGET_PAGE_MASK); val = ldl_p(ptr); } @@ -3322,7 +3344,7 @@ uint64_t ldq_phys(target_phys_addr_t addr) #endif } else { /* RAM case */ - ptr = phys_ram_base + (pd & TARGET_PAGE_MASK) + + ptr = qemu_get_ram_ptr(pd & TARGET_PAGE_MASK) + (addr & ~TARGET_PAGE_MASK); val = ldq_p(ptr); } @@ -3369,7 +3391,7 @@ void stl_phys_notdirty(target_phys_addr_t addr, uint32_t val) io_mem_write[io_index][2](io_mem_opaque[io_index], addr, val); } else { unsigned long addr1 = (pd & TARGET_PAGE_MASK) + (addr & ~TARGET_PAGE_MASK); - ptr = phys_ram_base + addr1; + ptr = qemu_get_ram_ptr(addr1); stl_p(ptr, val); if (unlikely(in_migration)) { @@ -3410,7 +3432,7 @@ void stq_phys_notdirty(target_phys_addr_t addr, uint64_t val) io_mem_write[io_index][2](io_mem_opaque[io_index], addr + 4, val >> 32); #endif } else { - ptr = phys_ram_base + (pd & TARGET_PAGE_MASK) + + ptr = qemu_get_ram_ptr(pd & TARGET_PAGE_MASK) + (addr & ~TARGET_PAGE_MASK); stq_p(ptr, val); } @@ -3440,7 +3462,7 @@ void stl_phys(target_phys_addr_t addr, uint32_t val) unsigned long addr1; addr1 = (pd & TARGET_PAGE_MASK) + (addr & ~TARGET_PAGE_MASK); /* RAM case */ - ptr = phys_ram_base + addr1; + ptr = qemu_get_ram_ptr(addr1); stl_p(ptr, val); if (!cpu_physical_memory_is_dirty(addr1)) { /* invalidate code */ diff --git a/kvm-all.c b/kvm-all.c index 3cfc7b5d8b..7198b32697 100644 --- a/kvm-all.c +++ b/kvm-all.c @@ -101,7 +101,7 @@ static int kvm_set_user_memory_region(KVMState *s, KVMSlot *slot) mem.slot = slot->slot; mem.guest_phys_addr = slot->start_addr; mem.memory_size = slot->memory_size; - mem.userspace_addr = (unsigned long)phys_ram_base + slot->phys_offset; + mem.userspace_addr = (unsigned long)qemu_get_ram_ptr(slot->phys_offset); mem.flags = slot->flags; return kvm_vm_ioctl(s, KVM_SET_USER_MEMORY_REGION, &mem); @@ -329,7 +329,7 @@ int kvm_init(int smp_cpus) /* initially, KVM allocated its own memory and we had to jump through * hooks to make phys_ram_base point to this. Modern versions of KVM - * just use a user allocated buffer so we can use phys_ram_base + * just use a user allocated buffer so we can use regular pages * unmodified. Make sure we have a sufficiently modern version of KVM. */ ret = kvm_ioctl(s, KVM_CHECK_EXTENSION, KVM_CAP_USER_MEMORY); diff --git a/vl.c b/vl.c index ddbcc6c2a6..cd974be497 100644 --- a/vl.c +++ b/vl.c @@ -3097,7 +3097,7 @@ static int ram_load_v1(QEMUFile *f, void *opaque) if (qemu_get_be32(f) != phys_ram_size) return -EINVAL; for(i = 0; i < phys_ram_size; i+= TARGET_PAGE_SIZE) { - ret = ram_get_page(f, phys_ram_base + i, TARGET_PAGE_SIZE); + ret = ram_get_page(f, qemu_get_ram_ptr(i), TARGET_PAGE_SIZE); if (ret) return ret; } @@ -3184,20 +3184,20 @@ static int ram_save_block(QEMUFile *f) while (addr < phys_ram_size) { if (cpu_physical_memory_get_dirty(current_addr, MIGRATION_DIRTY_FLAG)) { - uint8_t ch; + uint8_t *p; cpu_physical_memory_reset_dirty(current_addr, current_addr + TARGET_PAGE_SIZE, MIGRATION_DIRTY_FLAG); - ch = *(phys_ram_base + current_addr); + p = qemu_get_ram_ptr(current_addr); - if (is_dup_page(phys_ram_base + current_addr, ch)) { + if (is_dup_page(p, *p)) { qemu_put_be64(f, current_addr | RAM_SAVE_FLAG_COMPRESS); - qemu_put_byte(f, ch); + qemu_put_byte(f, *p); } else { qemu_put_be64(f, current_addr | RAM_SAVE_FLAG_PAGE); - qemu_put_buffer(f, phys_ram_base + current_addr, TARGET_PAGE_SIZE); + qemu_put_buffer(f, p, TARGET_PAGE_SIZE); } found = 1; @@ -3278,7 +3278,8 @@ static int ram_load_dead(QEMUFile *f, void *opaque) goto error; } if (buf[0] == 0) { - if (ram_decompress_buf(s, phys_ram_base + i, BDRV_HASH_BLOCK_SIZE) < 0) { + if (ram_decompress_buf(s, qemu_get_ram_ptr(i), + BDRV_HASH_BLOCK_SIZE) < 0) { fprintf(stderr, "Error while reading ram block address=0x%08" PRIx64, (uint64_t)i); goto error; } @@ -3328,9 +3329,9 @@ static int ram_load(QEMUFile *f, void *opaque, int version_id) if (flags & RAM_SAVE_FLAG_COMPRESS) { uint8_t ch = qemu_get_byte(f); - memset(phys_ram_base + addr, ch, TARGET_PAGE_SIZE); + memset(qemu_get_ram_ptr(addr), ch, TARGET_PAGE_SIZE); } else if (flags & RAM_SAVE_FLAG_PAGE) - qemu_get_buffer(f, phys_ram_base + addr, TARGET_PAGE_SIZE); + qemu_get_buffer(f, qemu_get_ram_ptr(addr), TARGET_PAGE_SIZE); } while (!(flags & RAM_SAVE_FLAG_EOS)); return 0;