diff --git a/backends/hostmem-file.c b/backends/hostmem-file.c index 92659c119d..51799943f1 100644 --- a/backends/hostmem-file.c +++ b/backends/hostmem-file.c @@ -28,6 +28,8 @@ typedef struct HostMemoryBackendFile HostMemoryBackendFile; struct HostMemoryBackendFile { HostMemoryBackend parent_obj; + + bool share; char *mem_path; }; @@ -51,7 +53,7 @@ file_backend_memory_alloc(HostMemoryBackend *backend, Error **errp) backend->force_prealloc = mem_prealloc; memory_region_init_ram_from_file(&backend->mr, OBJECT(backend), object_get_canonical_path(OBJECT(backend)), - backend->size, + backend->size, fb->share, fb->mem_path, errp); } #endif @@ -87,9 +89,31 @@ static void set_mem_path(Object *o, const char *str, Error **errp) fb->mem_path = g_strdup(str); } +static bool file_memory_backend_get_share(Object *o, Error **errp) +{ + HostMemoryBackendFile *fb = MEMORY_BACKEND_FILE(o); + + return fb->share; +} + +static void file_memory_backend_set_share(Object *o, bool value, Error **errp) +{ + HostMemoryBackend *backend = MEMORY_BACKEND(o); + HostMemoryBackendFile *fb = MEMORY_BACKEND_FILE(o); + + if (memory_region_size(&backend->mr)) { + error_setg(errp, "cannot change property value"); + return; + } + fb->share = value; +} + static void file_backend_instance_init(Object *o) { + object_property_add_bool(o, "share", + file_memory_backend_get_share, + file_memory_backend_set_share, NULL); object_property_add_str(o, "mem-path", get_mem_path, set_mem_path, NULL); } diff --git a/exec.c b/exec.c index a27923a258..1ca7baca0b 100644 --- a/exec.c +++ b/exec.c @@ -73,6 +73,9 @@ 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); @@ -1074,7 +1077,9 @@ static void *file_ram_alloc(RAMBlock *block, 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) { error_setg_errno(errp, errno, "unable to map backing store for hugepages"); @@ -1286,7 +1291,7 @@ static ram_addr_t ram_block_add(RAMBlock *new_block) #ifdef __linux__ ram_addr_t qemu_ram_alloc_from_file(ram_addr_t size, MemoryRegion *mr, - const char *mem_path, + bool share, const char *mem_path, Error **errp) { RAMBlock *new_block; @@ -1311,6 +1316,7 @@ ram_addr_t qemu_ram_alloc_from_file(ram_addr_t size, MemoryRegion *mr, 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) { @@ -1413,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 { diff --git a/include/exec/memory.h b/include/exec/memory.h index 1cf5981b2e..3d778d70f0 100644 --- a/include/exec/memory.h +++ b/include/exec/memory.h @@ -321,6 +321,7 @@ void memory_region_init_ram(MemoryRegion *mr, * @owner: the object that tracks the region's reference count * @name: the name of the region. * @size: size of the region. + * @share: %true if memory must be mmaped with the MAP_SHARED flag * @path: the path in which to allocate the RAM. * @errp: pointer to Error*, to store an error if it happens. */ @@ -328,6 +329,7 @@ void memory_region_init_ram_from_file(MemoryRegion *mr, struct Object *owner, const char *name, uint64_t size, + bool share, const char *path, Error **errp); #endif diff --git a/include/exec/ram_addr.h b/include/exec/ram_addr.h index fcc7ef0180..55ca67681f 100644 --- a/include/exec/ram_addr.h +++ b/include/exec/ram_addr.h @@ -23,7 +23,8 @@ #include "hw/xen/xen.h" ram_addr_t qemu_ram_alloc_from_file(ram_addr_t size, MemoryRegion *mr, - const char *mem_path, Error **errp); + bool share, const char *mem_path, + Error **errp); ram_addr_t qemu_ram_alloc_from_ptr(ram_addr_t size, void *host, MemoryRegion *mr); ram_addr_t qemu_ram_alloc(ram_addr_t size, MemoryRegion *mr); diff --git a/memory.c b/memory.c index e7f1160f4e..b91a60a921 100644 --- a/memory.c +++ b/memory.c @@ -1038,6 +1038,7 @@ void memory_region_init_ram_from_file(MemoryRegion *mr, struct Object *owner, const char *name, uint64_t size, + bool share, const char *path, Error **errp) { @@ -1045,7 +1046,7 @@ void memory_region_init_ram_from_file(MemoryRegion *mr, mr->ram = true; mr->terminates = true; mr->destructor = memory_region_destructor_ram; - mr->ram_addr = qemu_ram_alloc_from_file(size, mr, path, errp); + mr->ram_addr = qemu_ram_alloc_from_file(size, mr, share, path, errp); } #endif diff --git a/numa.c b/numa.c index 8af9c916ac..711f6825cb 100644 --- a/numa.c +++ b/numa.c @@ -231,7 +231,7 @@ static void allocate_system_memory_nonnuma(MemoryRegion *mr, Object *owner, if (mem_path) { #ifdef __linux__ Error *err = NULL; - memory_region_init_ram_from_file(mr, owner, name, ram_size, + memory_region_init_ram_from_file(mr, owner, name, ram_size, false, mem_path, &err); /* Legacy behavior: if allocation failed, fall back to