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:
parent
605d0a945d
commit
a35ba7be4b
@ -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,
|
||||||
|
@ -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
7
exec.c
@ -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,
|
||||||
|
@ -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.
|
||||||
*
|
*
|
||||||
|
@ -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);
|
||||||
|
@ -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;
|
||||||
};
|
};
|
||||||
|
11
memory.c
11
memory.c
@ -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) {
|
||||||
|
Loading…
Reference in New Issue
Block a user