X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=exec.c;h=95c4356c65a006e1f992e193bd19c45c9f593255;hb=30c367ed446b6ea53245589a5cf373578ac075d7;hp=482dd801df238c7b63823c560fd964e11a73e55d;hpb=0628c18267bbe8d44f0faf3e71acf0ae31bea7fd;p=qemu.git diff --git a/exec.c b/exec.c index 482dd801d..95c4356c6 100644 --- a/exec.c +++ b/exec.c @@ -129,7 +129,6 @@ static PhysPageMap next_map; static void io_mem_init(void); static void memory_map_init(void); -static void *qemu_safe_ram_ptr(ram_addr_t addr); static MemoryRegion io_mem_watch; #endif @@ -410,8 +409,10 @@ static void breakpoint_invalidate(CPUState *cpu, target_ulong pc) #else static void breakpoint_invalidate(CPUState *cpu, target_ulong pc) { - tb_invalidate_phys_addr(cpu_get_phys_page_debug(cpu, pc) | - (pc & ~TARGET_PAGE_MASK)); + hwaddr phys = cpu_get_phys_page_debug(cpu, pc); + if (phys != -1) { + tb_invalidate_phys_addr(phys | (pc & ~TARGET_PAGE_MASK)); + } } #endif #endif /* TARGET_HAS_ICE */ @@ -625,55 +626,40 @@ void cpu_abort(CPUArchState *env, const char *fmt, ...) abort(); } -CPUArchState *cpu_copy(CPUArchState *env) +#if !defined(CONFIG_USER_ONLY) +static RAMBlock *qemu_get_ram_block(ram_addr_t addr) { - CPUArchState *new_env = cpu_init(env->cpu_model_str); -#if defined(TARGET_HAS_ICE) - CPUBreakpoint *bp; - CPUWatchpoint *wp; -#endif - - /* Reset non arch specific state */ - cpu_reset(ENV_GET_CPU(new_env)); - - /* Copy arch specific state into the new CPU */ - memcpy(new_env, env, sizeof(CPUArchState)); + RAMBlock *block; - /* Clone all break/watchpoints. - Note: Once we support ptrace with hw-debug register access, make sure - BP_CPU break/watchpoints are handled correctly on clone. */ - QTAILQ_INIT(&env->breakpoints); - QTAILQ_INIT(&env->watchpoints); -#if defined(TARGET_HAS_ICE) - QTAILQ_FOREACH(bp, &env->breakpoints, entry) { - cpu_breakpoint_insert(new_env, bp->pc, bp->flags, NULL); + /* The list is protected by the iothread lock here. */ + block = ram_list.mru_block; + if (block && addr - block->offset < block->length) { + goto found; } - QTAILQ_FOREACH(wp, &env->watchpoints, entry) { - cpu_watchpoint_insert(new_env, wp->vaddr, (~wp->len_mask) + 1, - wp->flags, NULL); + QTAILQ_FOREACH(block, &ram_list.blocks, next) { + if (addr - block->offset < block->length) { + goto found; + } } -#endif - return new_env; + fprintf(stderr, "Bad ram offset %" PRIx64 "\n", (uint64_t)addr); + abort(); + +found: + ram_list.mru_block = block; + return block; } -#if !defined(CONFIG_USER_ONLY) static void tlb_reset_dirty_range_all(ram_addr_t start, ram_addr_t end, uintptr_t length) { - uintptr_t start1; + RAMBlock *block; + ram_addr_t start1; - /* we modify the TLB cache so that the dirty bit will be set again - when accessing the range */ - start1 = (uintptr_t)qemu_safe_ram_ptr(start); - /* Check that we don't span multiple blocks - this breaks the - address comparisons below. */ - if ((uintptr_t)qemu_safe_ram_ptr(end - 1) - start1 - != (end - 1) - start) { - abort(); - } + block = qemu_get_ram_block(start); + assert(block == qemu_get_ram_block(end - 1)); + start1 = (uintptr_t)block->host + (start - block->offset); cpu_tlb_reset_dirty_all(start1, length); - } /* Note: start and end must be within the same ram block. */ @@ -749,6 +735,18 @@ static int subpage_register (subpage_t *mmio, uint32_t start, uint32_t end, uint16_t section); static subpage_t *subpage_init(AddressSpace *as, hwaddr base); +static void *(*phys_mem_alloc)(size_t size) = qemu_anon_ram_alloc; + +/* + * Set a custom physical guest memory alloator. + * Accelerators with unusual needs may need this. Hopefully, we can + * get rid of it eventually. + */ +void phys_mem_set_alloc(void *(*alloc)(size_t)) +{ + phys_mem_alloc = alloc; +} + static uint16_t phys_section_add(MemoryRegionSection *section) { /* The physical section number is ORed with a page-aligned @@ -880,7 +878,7 @@ void qemu_mutex_unlock_ramlist(void) qemu_mutex_unlock(&ram_list.mutex); } -#if defined(__linux__) && !defined(TARGET_S390X) +#ifdef __linux__ #include @@ -983,6 +981,14 @@ static void *file_ram_alloc(RAMBlock *block, block->fd = fd; return area; } +#else +static void *file_ram_alloc(RAMBlock *block, + ram_addr_t memory, + const char *path) +{ + fprintf(stderr, "-mem-path not supported on this host\n"); + exit(1); +} #endif static ram_addr_t find_ram_offset(ram_addr_t size) @@ -1099,6 +1105,7 @@ ram_addr_t qemu_ram_alloc_from_ptr(ram_addr_t size, void *host, size = TARGET_PAGE_ALIGN(size); new_block = g_malloc0(sizeof(*new_block)); + new_block->fd = -1; /* This assumes the iothread lock is taken here too. */ qemu_mutex_lock_ramlist(); @@ -1115,19 +1122,24 @@ ram_addr_t qemu_ram_alloc_from_ptr(ram_addr_t size, void *host, xen_ram_alloc(new_block->offset, size, mr); } else { if (mem_path) { -#if defined (__linux__) && !defined(TARGET_S390X) + if (phys_mem_alloc != qemu_anon_ram_alloc) { + /* + * file_ram_alloc() needs to allocate just like + * phys_mem_alloc, but we haven't bothered to provide + * a hook there. + */ + fprintf(stderr, + "-mem-path not supported with this accelerator\n"); + exit(1); + } new_block->host = file_ram_alloc(new_block, size, mem_path); -#else - fprintf(stderr, "-mem-path option unsupported\n"); - exit(1); -#endif } if (!new_block->host) { - if (kvm_enabled()) { - /* some s390/kvm configurations have special constraints */ - new_block->host = kvm_ram_alloc(size); - } else { - new_block->host = qemu_anon_ram_alloc(size); + new_block->host = phys_mem_alloc(size); + if (!new_block->host) { + fprintf(stderr, "Cannot set up guest memory '%s': %s\n", + new_block->mr->name, strerror(errno)); + exit(1); } memory_try_enable_merging(new_block->host, size); } @@ -1158,6 +1170,7 @@ ram_addr_t qemu_ram_alloc_from_ptr(ram_addr_t size, void *host, qemu_ram_setup_dump(new_block->host, size); qemu_madvise(new_block->host, size, QEMU_MADV_HUGEPAGE); + qemu_madvise(new_block->host, size, QEMU_MADV_DONTFORK); if (kvm_enabled()) kvm_setup_guest_memory(new_block->host, size); @@ -1203,16 +1216,10 @@ void qemu_ram_free(ram_addr_t addr) ; } else if (xen_enabled()) { xen_invalidate_map_cache_entry(block->host); - } else if (mem_path) { -#if defined (__linux__) && !defined(TARGET_S390X) - if (block->fd) { - munmap(block->host, block->length); - close(block->fd); - } else { - qemu_anon_ram_free(block->host, block->length); - } -#else - abort(); +#ifndef _WIN32 + } else if (block->fd >= 0) { + munmap(block->host, block->length); + close(block->fd); #endif } else { qemu_anon_ram_free(block->host, block->length); @@ -1244,35 +1251,26 @@ void qemu_ram_remap(ram_addr_t addr, ram_addr_t length) } else { flags = MAP_FIXED; munmap(vaddr, length); - if (mem_path) { -#if defined(__linux__) && !defined(TARGET_S390X) - if (block->fd) { + if (block->fd >= 0) { #ifdef MAP_POPULATE - flags |= mem_prealloc ? MAP_POPULATE | MAP_SHARED : - MAP_PRIVATE; + flags |= mem_prealloc ? MAP_POPULATE | MAP_SHARED : + MAP_PRIVATE; #else - flags |= MAP_PRIVATE; -#endif - area = mmap(vaddr, length, PROT_READ | PROT_WRITE, - flags, block->fd, offset); - } else { - flags |= MAP_PRIVATE | MAP_ANONYMOUS; - area = mmap(vaddr, length, PROT_READ | PROT_WRITE, - flags, -1, 0); - } -#else - abort(); + flags |= MAP_PRIVATE; #endif + area = mmap(vaddr, length, PROT_READ | PROT_WRITE, + flags, block->fd, offset); } else { -#if defined(TARGET_S390X) && defined(CONFIG_KVM) - flags |= MAP_SHARED | MAP_ANONYMOUS; - area = mmap(vaddr, length, PROT_EXEC|PROT_READ|PROT_WRITE, - flags, -1, 0); -#else + /* + * Remap needs to match alloc. Accelerators that + * set phys_mem_alloc never remap. If they did, + * we'd need a remap hook here. + */ + assert(phys_mem_alloc == qemu_anon_ram_alloc); + flags |= MAP_PRIVATE | MAP_ANONYMOUS; area = mmap(vaddr, length, PROT_READ | PROT_WRITE, flags, -1, 0); -#endif } if (area != vaddr) { fprintf(stderr, "Could not remap addr: " @@ -1289,29 +1287,6 @@ void qemu_ram_remap(ram_addr_t addr, ram_addr_t length) } #endif /* !_WIN32 */ -static RAMBlock *qemu_get_ram_block(ram_addr_t addr) -{ - RAMBlock *block; - - /* The list is protected by the iothread lock here. */ - block = ram_list.mru_block; - if (block && addr - block->offset < block->length) { - goto found; - } - QTAILQ_FOREACH(block, &ram_list.blocks, next) { - if (addr - block->offset < block->length) { - goto found; - } - } - - fprintf(stderr, "Bad ram offset %" PRIx64 "\n", (uint64_t)addr); - abort(); - -found: - ram_list.mru_block = block; - return block; -} - /* Return a host pointer to ram allocated with qemu_ram_alloc. 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, @@ -1339,40 +1314,6 @@ void *qemu_get_ram_ptr(ram_addr_t addr) return block->host + (addr - block->offset); } -/* Return a host pointer to ram allocated with qemu_ram_alloc. Same as - * qemu_get_ram_ptr but do not touch ram_list.mru_block. - * - * ??? Is this still necessary? - */ -static void *qemu_safe_ram_ptr(ram_addr_t addr) -{ - RAMBlock *block; - - /* The list is protected by the iothread lock here. */ - QTAILQ_FOREACH(block, &ram_list.blocks, next) { - if (addr - block->offset < block->length) { - if (xen_enabled()) { - /* We need to check if the requested address is in the RAM - * because we don't want to map the entire memory in QEMU. - * In that case just map until the end of the page. - */ - if (block->offset == 0) { - return xen_map_cache(addr, 0, 0); - } else if (block->host == NULL) { - block->host = - xen_map_cache(block->offset, block->length, 1); - } - } - return block->host + (addr - block->offset); - } - } - - fprintf(stderr, "Bad ram offset %" PRIx64 "\n", (uint64_t)addr); - abort(); - - return NULL; -} - /* Return a host pointer to guest's ram. Similar to qemu_get_ram_ptr * but takes a size argument */ static void *qemu_ram_ptr_length(ram_addr_t addr, hwaddr *size) @@ -1561,7 +1502,7 @@ static uint64_t subpage_read(void *opaque, hwaddr addr, uint8_t buf[4]; #if defined(DEBUG_SUBPAGE) - printf("%s: subpage %p len %d addr " TARGET_FMT_plx "\n", __func__, + printf("%s: subpage %p len %u addr " TARGET_FMT_plx "\n", __func__, subpage, len, addr); #endif address_space_read(subpage->as, addr + subpage->base, buf, len); @@ -1584,7 +1525,7 @@ static void subpage_write(void *opaque, hwaddr addr, uint8_t buf[4]; #if defined(DEBUG_SUBPAGE) - printf("%s: subpage %p len %d addr " TARGET_FMT_plx + printf("%s: subpage %p len %u addr " TARGET_FMT_plx " value %"PRIx64"\n", __func__, subpage, len, addr, value); #endif @@ -1605,16 +1546,16 @@ static void subpage_write(void *opaque, hwaddr addr, } static bool subpage_accepts(void *opaque, hwaddr addr, - unsigned size, bool is_write) + unsigned len, bool is_write) { subpage_t *subpage = opaque; #if defined(DEBUG_SUBPAGE) - printf("%s: subpage %p %c len %d addr " TARGET_FMT_plx "\n", + printf("%s: subpage %p %c len %u addr " TARGET_FMT_plx "\n", __func__, subpage, is_write ? 'w' : 'r', len, addr); #endif return address_space_access_valid(subpage->as, addr + subpage->base, - size, is_write); + len, is_write); } static const MemoryRegionOps subpage_ops = { @@ -1634,8 +1575,8 @@ static int subpage_register (subpage_t *mmio, uint32_t start, uint32_t end, idx = SUBPAGE_IDX(start); eidx = SUBPAGE_IDX(end); #if defined(DEBUG_SUBPAGE) - printf("%s: %p start %08x end %08x idx %08x eidx %08x mem %ld\n", __func__, - mmio, start, end, idx, eidx, memory); + printf("%s: %p start %08x end %08x idx %08x eidx %08x section %d\n", + __func__, mmio, start, end, idx, eidx, section); #endif for (; idx <= eidx; idx++) { mmio->sub_section[idx] = section; @@ -1656,8 +1597,8 @@ static subpage_t *subpage_init(AddressSpace *as, hwaddr base) "subpage", TARGET_PAGE_SIZE); mmio->iomem.subpage = true; #if defined(DEBUG_SUBPAGE) - printf("%s: %p base " TARGET_FMT_plx " len %08x %d\n", __func__, - mmio, base, TARGET_PAGE_SIZE, subpage_memory); + printf("%s: %p base " TARGET_FMT_plx " len %08x\n", __func__, + mmio, base, TARGET_PAGE_SIZE); #endif subpage_register(mmio, 0, TARGET_PAGE_SIZE-1, PHYS_SECTION_UNASSIGNED); @@ -2160,7 +2101,9 @@ void *address_space_map(AddressSpace *as, if (bounce.buffer) { return NULL; } - bounce.buffer = qemu_memalign(TARGET_PAGE_SIZE, TARGET_PAGE_SIZE); + /* Avoid unbounded allocations */ + l = MIN(l, TARGET_PAGE_SIZE); + bounce.buffer = qemu_memalign(TARGET_PAGE_SIZE, l); bounce.addr = addr; bounce.len = l;