hostmem: allow preallocation of any memory region

And allow preallocation of file-based memory even without -mem-prealloc.
Some care is necessary because -mem-prealloc does not allow disabling
preallocation for hostmem-file.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Hu Tao <hutao@cn.fujitsu.com>
Acked-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
This commit is contained in:
Paolo Bonzini 2014-06-10 19:15:23 +08:00 committed by Michael S. Tsirkin
parent 605d0a945d
commit a35ba7be4b
7 changed files with 75 additions and 0 deletions

View File

@ -9,7 +9,9 @@
* This work is licensed under the terms of the GNU GPL, version 2 or later. * This work is licensed under the terms of the GNU GPL, version 2 or later.
* See the COPYING file in the top-level directory. * See the COPYING file in the top-level directory.
*/ */
#include "qemu-common.h"
#include "sysemu/hostmem.h" #include "sysemu/hostmem.h"
#include "sysemu/sysemu.h"
#include "qom/object_interfaces.h" #include "qom/object_interfaces.h"
/* hostmem-file.c */ /* hostmem-file.c */
@ -46,6 +48,7 @@ file_backend_memory_alloc(HostMemoryBackend *backend, Error **errp)
error_setg(errp, "-mem-path not supported on this host"); error_setg(errp, "-mem-path not supported on this host");
#else #else
if (!memory_region_size(&backend->mr)) { if (!memory_region_size(&backend->mr)) {
backend->force_prealloc = mem_prealloc;
memory_region_init_ram_from_file(&backend->mr, OBJECT(backend), memory_region_init_ram_from_file(&backend->mr, OBJECT(backend),
object_get_canonical_path(OBJECT(backend)), object_get_canonical_path(OBJECT(backend)),
backend->size, backend->size,

View File

@ -105,6 +105,41 @@ static void host_memory_backend_set_dump(Object *obj, bool value, Error **errp)
} }
} }
static bool host_memory_backend_get_prealloc(Object *obj, Error **errp)
{
HostMemoryBackend *backend = MEMORY_BACKEND(obj);
return backend->prealloc || backend->force_prealloc;
}
static void host_memory_backend_set_prealloc(Object *obj, bool value,
Error **errp)
{
HostMemoryBackend *backend = MEMORY_BACKEND(obj);
if (backend->force_prealloc) {
if (value) {
error_setg(errp,
"remove -mem-prealloc to use the prealloc property");
return;
}
}
if (!memory_region_size(&backend->mr)) {
backend->prealloc = value;
return;
}
if (value && !backend->prealloc) {
int fd = memory_region_get_fd(&backend->mr);
void *ptr = memory_region_get_ram_ptr(&backend->mr);
uint64_t sz = memory_region_size(&backend->mr);
os_mem_prealloc(fd, ptr, sz);
backend->prealloc = true;
}
}
static void host_memory_backend_init(Object *obj) static void host_memory_backend_init(Object *obj)
{ {
HostMemoryBackend *backend = MEMORY_BACKEND(obj); HostMemoryBackend *backend = MEMORY_BACKEND(obj);
@ -113,6 +148,7 @@ static void host_memory_backend_init(Object *obj)
"mem-merge", true); "mem-merge", true);
backend->dump = qemu_opt_get_bool(qemu_get_machine_opts(), backend->dump = qemu_opt_get_bool(qemu_get_machine_opts(),
"dump-guest-core", true); "dump-guest-core", true);
backend->prealloc = mem_prealloc;
object_property_add_bool(obj, "merge", object_property_add_bool(obj, "merge",
host_memory_backend_get_merge, host_memory_backend_get_merge,
@ -120,6 +156,9 @@ static void host_memory_backend_init(Object *obj)
object_property_add_bool(obj, "dump", object_property_add_bool(obj, "dump",
host_memory_backend_get_dump, host_memory_backend_get_dump,
host_memory_backend_set_dump, NULL); host_memory_backend_set_dump, NULL);
object_property_add_bool(obj, "prealloc",
host_memory_backend_get_prealloc,
host_memory_backend_set_prealloc, NULL);
object_property_add(obj, "size", "int", object_property_add(obj, "size", "int",
host_memory_backend_get_size, host_memory_backend_get_size,
host_memory_backend_set_size, NULL, NULL, NULL); host_memory_backend_set_size, NULL, NULL, NULL);
@ -165,6 +204,9 @@ host_memory_backend_memory_complete(UserCreatable *uc, Error **errp)
if (!backend->dump) { if (!backend->dump) {
qemu_madvise(ptr, sz, QEMU_MADV_DONTDUMP); qemu_madvise(ptr, sz, QEMU_MADV_DONTDUMP);
} }
if (backend->prealloc) {
os_mem_prealloc(memory_region_get_fd(&backend->mr), ptr, sz);
}
} }
} }

7
exec.c
View File

@ -1448,6 +1448,13 @@ void qemu_ram_remap(ram_addr_t addr, ram_addr_t length)
} }
#endif /* !_WIN32 */ #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. /* Return a host pointer to ram allocated with qemu_ram_alloc.
With the exception of the softmmu code in this file, this should 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, only be used for local memory (e.g. video ram) that the device owns,

View File

@ -533,6 +533,16 @@ bool memory_region_is_logging(MemoryRegion *mr);
*/ */
bool memory_region_is_rom(MemoryRegion *mr); bool memory_region_is_rom(MemoryRegion *mr);
/**
* memory_region_get_fd: Get a file descriptor backing a RAM memory region.
*
* Returns a file descriptor backing a file-based RAM memory region,
* or -1 if the region is not a file-based RAM memory region.
*
* @mr: the RAM or alias memory region being queried.
*/
int memory_region_get_fd(MemoryRegion *mr);
/** /**
* memory_region_get_ram_ptr: Get a pointer into a RAM memory region. * memory_region_get_ram_ptr: Get a pointer into a RAM memory region.
* *

View File

@ -27,6 +27,7 @@ ram_addr_t qemu_ram_alloc_from_file(ram_addr_t size, MemoryRegion *mr,
ram_addr_t qemu_ram_alloc_from_ptr(ram_addr_t size, void *host, ram_addr_t qemu_ram_alloc_from_ptr(ram_addr_t size, void *host,
MemoryRegion *mr); MemoryRegion *mr);
ram_addr_t qemu_ram_alloc(ram_addr_t size, MemoryRegion *mr); ram_addr_t qemu_ram_alloc(ram_addr_t size, MemoryRegion *mr);
int qemu_get_ram_fd(ram_addr_t addr);
void *qemu_get_ram_ptr(ram_addr_t addr); void *qemu_get_ram_ptr(ram_addr_t addr);
void qemu_ram_free(ram_addr_t addr); void qemu_ram_free(ram_addr_t addr);
void qemu_ram_free_from_ptr(ram_addr_t addr); void qemu_ram_free_from_ptr(ram_addr_t addr);

View File

@ -53,6 +53,7 @@ struct HostMemoryBackend {
/* protected */ /* protected */
uint64_t size; uint64_t size;
bool merge, dump; bool merge, dump;
bool prealloc, force_prealloc;
MemoryRegion mr; MemoryRegion mr;
}; };

View File

@ -1271,6 +1271,17 @@ void memory_region_reset_dirty(MemoryRegion *mr, hwaddr addr,
cpu_physical_memory_reset_dirty(mr->ram_addr + addr, size, client); cpu_physical_memory_reset_dirty(mr->ram_addr + addr, size, client);
} }
int memory_region_get_fd(MemoryRegion *mr)
{
if (mr->alias) {
return memory_region_get_fd(mr->alias);
}
assert(mr->terminates);
return qemu_get_ram_fd(mr->ram_addr & TARGET_PAGE_MASK);
}
void *memory_region_get_ram_ptr(MemoryRegion *mr) void *memory_region_get_ram_ptr(MemoryRegion *mr)
{ {
if (mr->alias) { if (mr->alias) {