diff options
Diffstat (limited to 'exec.c')
| -rw-r--r-- | exec.c | 211 |
1 files changed, 104 insertions, 107 deletions
@@ -70,6 +70,12 @@ AddressSpace address_space_memory; MemoryRegion io_mem_rom, io_mem_notdirty; static MemoryRegion io_mem_unassigned; +/* RAM is pre-allocated and passed into qemu_ram_alloc_from_ptr */ +#define RAM_PREALLOC (1 << 0) + +/* RAM is mmap-ed with MAP_SHARED */ +#define RAM_SHARED (1 << 1) + #endif struct CPUTailQ cpus = QTAILQ_HEAD_INITIALIZER(cpus); @@ -1011,16 +1017,10 @@ static long gethugepagesize(const char *path) return fs.f_bsize; } -static sigjmp_buf sigjump; - -static void sigbus_handler(int signal) -{ - siglongjmp(sigjump, 1); -} - static void *file_ram_alloc(RAMBlock *block, ram_addr_t memory, - const char *path) + const char *path, + Error **errp) { char *filename; char *sanitized_name; @@ -1039,7 +1039,8 @@ static void *file_ram_alloc(RAMBlock *block, } if (kvm_enabled() && !kvm_has_sync_mmu()) { - fprintf(stderr, "host lacks kvm mmu notifiers, -mem-path unsupported\n"); + error_setg(errp, + "host lacks kvm mmu notifiers, -mem-path unsupported"); goto error; } @@ -1056,7 +1057,8 @@ static void *file_ram_alloc(RAMBlock *block, fd = mkstemp(filename); if (fd < 0) { - perror("unable to create backing store for hugepages"); + error_setg_errno(errp, errno, + "unable to create backing store for hugepages"); g_free(filename); goto error; } @@ -1071,53 +1073,22 @@ static void *file_ram_alloc(RAMBlock *block, * If anything goes wrong with it under other filesystems, * mmap will fail. */ - if (ftruncate(fd, memory)) + if (ftruncate(fd, memory)) { perror("ftruncate"); + } - area = mmap(0, memory, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0); + area = mmap(0, memory, PROT_READ | PROT_WRITE, + (block->flags & RAM_SHARED ? MAP_SHARED : MAP_PRIVATE), + fd, 0); if (area == MAP_FAILED) { - perror("file_ram_alloc: can't mmap RAM pages"); + error_setg_errno(errp, errno, + "unable to map backing store for hugepages"); close(fd); goto error; } if (mem_prealloc) { - int ret, i; - struct sigaction act, oldact; - sigset_t set, oldset; - - memset(&act, 0, sizeof(act)); - act.sa_handler = &sigbus_handler; - act.sa_flags = 0; - - ret = sigaction(SIGBUS, &act, &oldact); - if (ret) { - perror("file_ram_alloc: failed to install signal handler"); - exit(1); - } - - /* unblock SIGBUS */ - sigemptyset(&set); - sigaddset(&set, SIGBUS); - pthread_sigmask(SIG_UNBLOCK, &set, &oldset); - - if (sigsetjmp(sigjump, 1)) { - fprintf(stderr, "file_ram_alloc: failed to preallocate pages\n"); - exit(1); - } - - /* MAP_POPULATE silently ignores failures */ - for (i = 0; i < (memory/hpagesize); i++) { - memset(area + (hpagesize*i), 0, 1); - } - - ret = sigaction(SIGBUS, &oldact, NULL); - if (ret) { - perror("file_ram_alloc: failed to reinstall signal handler"); - exit(1); - } - - pthread_sigmask(SIG_SETMASK, &oldset, NULL); + os_mem_prealloc(fd, area, memory); } block->fd = fd; @@ -1129,14 +1100,6 @@ error: } return NULL; } -#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) @@ -1262,56 +1225,30 @@ static int memory_try_enable_merging(void *addr, size_t len) return qemu_madvise(addr, len, QEMU_MADV_MERGEABLE); } -ram_addr_t qemu_ram_alloc_from_ptr(ram_addr_t size, void *host, - MemoryRegion *mr) +static ram_addr_t ram_block_add(RAMBlock *new_block) { - RAMBlock *block, *new_block; + RAMBlock *block; ram_addr_t old_ram_size, new_ram_size; old_ram_size = last_ram_offset() >> TARGET_PAGE_BITS; - 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(); - new_block->mr = mr; - new_block->offset = find_ram_offset(size); - if (host) { - new_block->host = host; - new_block->flags |= RAM_PREALLOC_MASK; - } else if (xen_enabled()) { - if (mem_path) { - fprintf(stderr, "-mem-path not supported with Xen\n"); - exit(1); - } - xen_ram_alloc(new_block->offset, size, mr); - } else { - if (mem_path) { - 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); - } - if (!new_block->host) { - new_block->host = phys_mem_alloc(size); + new_block->offset = find_ram_offset(new_block->length); + + if (!new_block->host) { + if (xen_enabled()) { + xen_ram_alloc(new_block->offset, new_block->length, new_block->mr); + } else { + new_block->host = phys_mem_alloc(new_block->length); 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); + memory_try_enable_merging(new_block->host, new_block->length); } } - new_block->length = size; /* Keep the list sorted from biggest to smallest block. */ QTAILQ_FOREACH(block, &ram_list.blocks, next) { @@ -1339,18 +1276,75 @@ ram_addr_t qemu_ram_alloc_from_ptr(ram_addr_t size, void *host, old_ram_size, new_ram_size); } } - cpu_physical_memory_set_dirty_range(new_block->offset, size); + cpu_physical_memory_set_dirty_range(new_block->offset, new_block->length); - 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); + qemu_ram_setup_dump(new_block->host, new_block->length); + qemu_madvise(new_block->host, new_block->length, QEMU_MADV_HUGEPAGE); + qemu_madvise(new_block->host, new_block->length, QEMU_MADV_DONTFORK); - if (kvm_enabled()) - kvm_setup_guest_memory(new_block->host, size); + if (kvm_enabled()) { + kvm_setup_guest_memory(new_block->host, new_block->length); + } return new_block->offset; } +#ifdef __linux__ +ram_addr_t qemu_ram_alloc_from_file(ram_addr_t size, MemoryRegion *mr, + bool share, const char *mem_path, + Error **errp) +{ + RAMBlock *new_block; + + if (xen_enabled()) { + error_setg(errp, "-mem-path not supported with Xen"); + return -1; + } + + 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. + */ + error_setg(errp, + "-mem-path not supported with this accelerator"); + return -1; + } + + size = TARGET_PAGE_ALIGN(size); + new_block = g_malloc0(sizeof(*new_block)); + new_block->mr = mr; + new_block->length = size; + new_block->flags = share ? RAM_SHARED : 0; + new_block->host = file_ram_alloc(new_block, size, + mem_path, errp); + if (!new_block->host) { + g_free(new_block); + return -1; + } + + return ram_block_add(new_block); +} +#endif + +ram_addr_t qemu_ram_alloc_from_ptr(ram_addr_t size, void *host, + MemoryRegion *mr) +{ + RAMBlock *new_block; + + size = TARGET_PAGE_ALIGN(size); + new_block = g_malloc0(sizeof(*new_block)); + new_block->mr = mr; + new_block->length = size; + new_block->fd = -1; + new_block->host = host; + if (host) { + new_block->flags |= RAM_PREALLOC; + } + return ram_block_add(new_block); +} + ram_addr_t qemu_ram_alloc(ram_addr_t size, MemoryRegion *mr) { return qemu_ram_alloc_from_ptr(size, NULL, mr); @@ -1385,7 +1379,7 @@ void qemu_ram_free(ram_addr_t addr) QTAILQ_REMOVE(&ram_list.blocks, block, next); ram_list.mru_block = NULL; ram_list.version++; - if (block->flags & RAM_PREALLOC_MASK) { + if (block->flags & RAM_PREALLOC) { ; } else if (xen_enabled()) { xen_invalidate_map_cache_entry(block->host); @@ -1417,7 +1411,7 @@ void qemu_ram_remap(ram_addr_t addr, ram_addr_t length) offset = addr - block->offset; if (offset < block->length) { vaddr = block->host + offset; - if (block->flags & RAM_PREALLOC_MASK) { + if (block->flags & RAM_PREALLOC) { ; } else if (xen_enabled()) { abort(); @@ -1425,12 +1419,8 @@ void qemu_ram_remap(ram_addr_t addr, ram_addr_t length) flags = MAP_FIXED; munmap(vaddr, length); if (block->fd >= 0) { -#ifdef MAP_POPULATE - flags |= mem_prealloc ? MAP_POPULATE | MAP_SHARED : - MAP_PRIVATE; -#else - flags |= MAP_PRIVATE; -#endif + flags |= (block->flags & RAM_SHARED ? + MAP_SHARED : MAP_PRIVATE); area = mmap(vaddr, length, PROT_READ | PROT_WRITE, flags, block->fd, offset); } else { @@ -1460,6 +1450,13 @@ void qemu_ram_remap(ram_addr_t addr, ram_addr_t length) } #endif /* !_WIN32 */ +int qemu_get_ram_fd(ram_addr_t addr) +{ + RAMBlock *block = qemu_get_ram_block(addr); + + return block->fd; +} + /* 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, |
