Skip to content

Commit

Permalink
mem: add share parameter to memory-backend-ram
Browse files Browse the repository at this point in the history
Currently only file backed memory backend can
be created with a "share" flag in order to allow
sharing guest RAM with other processes in the host.

Add the "share" flag also to RAM Memory Backend
in order to allow remapping parts of the guest RAM
to different host virtual addresses. This is needed
by the RDMA devices in order to remap non-contiguous
QEMU virtual addresses to a contiguous virtual address range.

Moved the "share" flag to the Host Memory base class,
modified phys_mem_alloc to include the new parameter
and a new interface memory_region_init_ram_shared_nomigrate.

There are no functional changes if the new flag is not used.

Reviewed-by: Eduardo Habkost <[email protected]>
Signed-off-by: Marcel Apfelbaum <[email protected]>
  • Loading branch information
marcel-apf committed Feb 19, 2018
1 parent e5ecc28 commit 06329cc
Show file tree
Hide file tree
Showing 14 changed files with 94 additions and 50 deletions.
25 changes: 1 addition & 24 deletions backends/hostmem-file.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ typedef struct HostMemoryBackendFile HostMemoryBackendFile;
struct HostMemoryBackendFile {
HostMemoryBackend parent_obj;

bool share;
bool discard_data;
char *mem_path;
uint64_t align;
Expand Down Expand Up @@ -59,7 +58,7 @@ file_backend_memory_alloc(HostMemoryBackend *backend, Error **errp)
path = object_get_canonical_path(OBJECT(backend));
memory_region_init_ram_from_file(&backend->mr, OBJECT(backend),
path,
backend->size, fb->align, fb->share,
backend->size, fb->align, backend->share,
fb->mem_path, errp);
g_free(path);
}
Expand All @@ -86,25 +85,6 @@ 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 (host_memory_backend_mr_inited(backend)) {
error_setg(errp, "cannot change property value");
return;
}
fb->share = value;
}

static bool file_memory_backend_get_discard_data(Object *o, Error **errp)
{
return MEMORY_BACKEND_FILE(o)->discard_data;
Expand Down Expand Up @@ -171,9 +151,6 @@ file_backend_class_init(ObjectClass *oc, void *data)
bc->alloc = file_backend_memory_alloc;
oc->unparent = file_backend_unparent;

object_class_property_add_bool(oc, "share",
file_memory_backend_get_share, file_memory_backend_set_share,
&error_abort);
object_class_property_add_bool(oc, "discard-data",
file_memory_backend_get_discard_data, file_memory_backend_set_discard_data,
&error_abort);
Expand Down
4 changes: 2 additions & 2 deletions backends/hostmem-ram.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@ ram_backend_memory_alloc(HostMemoryBackend *backend, Error **errp)
}

path = object_get_canonical_path_component(OBJECT(backend));
memory_region_init_ram_nomigrate(&backend->mr, OBJECT(backend), path,
backend->size, errp);
memory_region_init_ram_shared_nomigrate(&backend->mr, OBJECT(backend), path,
backend->size, backend->share, errp);
g_free(path);
}

Expand Down
21 changes: 21 additions & 0 deletions backends/hostmem.c
Original file line number Diff line number Diff line change
Expand Up @@ -368,6 +368,24 @@ static void set_id(Object *o, const char *str, Error **errp)
backend->id = g_strdup(str);
}

static bool host_memory_backend_get_share(Object *o, Error **errp)
{
HostMemoryBackend *backend = MEMORY_BACKEND(o);

return backend->share;
}

static void host_memory_backend_set_share(Object *o, bool value, Error **errp)
{
HostMemoryBackend *backend = MEMORY_BACKEND(o);

if (host_memory_backend_mr_inited(backend)) {
error_setg(errp, "cannot change property value");
return;
}
backend->share = value;
}

static void
host_memory_backend_class_init(ObjectClass *oc, void *data)
{
Expand Down Expand Up @@ -398,6 +416,9 @@ host_memory_backend_class_init(ObjectClass *oc, void *data)
host_memory_backend_get_policy,
host_memory_backend_set_policy, &error_abort);
object_class_property_add_str(oc, "id", get_id, set_id, &error_abort);
object_class_property_add_bool(oc, "share",
host_memory_backend_get_share, host_memory_backend_set_share,
&error_abort);
}

static void host_memory_backend_finalize(Object *o)
Expand Down
26 changes: 15 additions & 11 deletions exec.c
Original file line number Diff line number Diff line change
Expand Up @@ -1285,15 +1285,15 @@ static int subpage_register (subpage_t *mmio, uint32_t start, uint32_t end,
uint16_t section);
static subpage_t *subpage_init(FlatView *fv, hwaddr base);

static void *(*phys_mem_alloc)(size_t size, uint64_t *align) =
static void *(*phys_mem_alloc)(size_t size, uint64_t *align, bool shared) =
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, uint64_t *align))
void phys_mem_set_alloc(void *(*alloc)(size_t, uint64_t *align, bool shared))
{
phys_mem_alloc = alloc;
}
Expand Down Expand Up @@ -1921,7 +1921,7 @@ static void dirty_memory_extend(ram_addr_t old_ram_size,
}
}

static void ram_block_add(RAMBlock *new_block, Error **errp)
static void ram_block_add(RAMBlock *new_block, Error **errp, bool shared)
{
RAMBlock *block;
RAMBlock *last_block = NULL;
Expand All @@ -1944,7 +1944,7 @@ static void ram_block_add(RAMBlock *new_block, Error **errp)
}
} else {
new_block->host = phys_mem_alloc(new_block->max_length,
&new_block->mr->align);
&new_block->mr->align, shared);
if (!new_block->host) {
error_setg_errno(errp, errno,
"cannot set up guest memory '%s'",
Expand Down Expand Up @@ -2049,7 +2049,7 @@ RAMBlock *qemu_ram_alloc_from_fd(ram_addr_t size, MemoryRegion *mr,
return NULL;
}

ram_block_add(new_block, &local_err);
ram_block_add(new_block, &local_err, share);
if (local_err) {
g_free(new_block);
error_propagate(errp, local_err);
Expand Down Expand Up @@ -2091,7 +2091,7 @@ RAMBlock *qemu_ram_alloc_internal(ram_addr_t size, ram_addr_t max_size,
void (*resized)(const char*,
uint64_t length,
void *host),
void *host, bool resizeable,
void *host, bool resizeable, bool share,
MemoryRegion *mr, Error **errp)
{
RAMBlock *new_block;
Expand All @@ -2114,7 +2114,7 @@ RAMBlock *qemu_ram_alloc_internal(ram_addr_t size, ram_addr_t max_size,
if (resizeable) {
new_block->flags |= RAM_RESIZEABLE;
}
ram_block_add(new_block, &local_err);
ram_block_add(new_block, &local_err, share);
if (local_err) {
g_free(new_block);
error_propagate(errp, local_err);
Expand All @@ -2126,12 +2126,15 @@ RAMBlock *qemu_ram_alloc_internal(ram_addr_t size, ram_addr_t max_size,
RAMBlock *qemu_ram_alloc_from_ptr(ram_addr_t size, void *host,
MemoryRegion *mr, Error **errp)
{
return qemu_ram_alloc_internal(size, size, NULL, host, false, mr, errp);
return qemu_ram_alloc_internal(size, size, NULL, host, false,
false, mr, errp);
}

RAMBlock *qemu_ram_alloc(ram_addr_t size, MemoryRegion *mr, Error **errp)
RAMBlock *qemu_ram_alloc(ram_addr_t size, bool share,
MemoryRegion *mr, Error **errp)
{
return qemu_ram_alloc_internal(size, size, NULL, NULL, false, mr, errp);
return qemu_ram_alloc_internal(size, size, NULL, NULL, false,
share, mr, errp);
}

RAMBlock *qemu_ram_alloc_resizeable(ram_addr_t size, ram_addr_t maxsz,
Expand All @@ -2140,7 +2143,8 @@ RAMBlock *qemu_ram_alloc_resizeable(ram_addr_t size, ram_addr_t maxsz,
void *host),
MemoryRegion *mr, Error **errp)
{
return qemu_ram_alloc_internal(size, maxsz, resized, NULL, true, mr, errp);
return qemu_ram_alloc_internal(size, maxsz, resized, NULL, true,
false, mr, errp);
}

static void reclaim_ramblock(RAMBlock *block)
Expand Down
23 changes: 23 additions & 0 deletions include/exec/memory.h
Original file line number Diff line number Diff line change
Expand Up @@ -435,6 +435,29 @@ void memory_region_init_ram_nomigrate(MemoryRegion *mr,
uint64_t size,
Error **errp);

/**
* memory_region_init_ram_shared_nomigrate: Initialize RAM memory region.
* Accesses into the region will
* modify memory directly.
*
* @mr: the #MemoryRegion to be initialized.
* @owner: the object that tracks the region's reference count
* @name: Region name, becomes part of RAMBlock name used in migration stream
* must be unique within any device
* @size: size of the region.
* @share: allow remapping RAM to different addresses
* @errp: pointer to Error*, to store an error if it happens.
*
* Note that this function is similar to memory_region_init_ram_nomigrate.
* The only difference is part of the RAM region can be remapped.
*/
void memory_region_init_ram_shared_nomigrate(MemoryRegion *mr,
struct Object *owner,
const char *name,
uint64_t size,
bool share,
Error **errp);

/**
* memory_region_init_resizeable_ram: Initialize memory region with resizeable
* RAM. Accesses into the region will
Expand Down
3 changes: 2 additions & 1 deletion include/exec/ram_addr.h
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,8 @@ RAMBlock *qemu_ram_alloc_from_fd(ram_addr_t size, MemoryRegion *mr,
Error **errp);
RAMBlock *qemu_ram_alloc_from_ptr(ram_addr_t size, void *host,
MemoryRegion *mr, Error **errp);
RAMBlock *qemu_ram_alloc(ram_addr_t size, MemoryRegion *mr, Error **errp);
RAMBlock *qemu_ram_alloc(ram_addr_t size, bool share, MemoryRegion *mr,
Error **errp);
RAMBlock *qemu_ram_alloc_resizeable(ram_addr_t size, ram_addr_t max_size,
void (*resized)(const char*,
uint64_t length,
Expand Down
2 changes: 1 addition & 1 deletion include/qemu/osdep.h
Original file line number Diff line number Diff line change
Expand Up @@ -255,7 +255,7 @@ extern int daemon(int, int);
int qemu_daemon(int nochdir, int noclose);
void *qemu_try_memalign(size_t alignment, size_t size);
void *qemu_memalign(size_t alignment, size_t size);
void *qemu_anon_ram_alloc(size_t size, uint64_t *align);
void *qemu_anon_ram_alloc(size_t size, uint64_t *align, bool shared);
void qemu_vfree(void *ptr);
void qemu_anon_ram_free(void *ptr, size_t size);

Expand Down
2 changes: 1 addition & 1 deletion include/sysemu/hostmem.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ struct HostMemoryBackend {
char *id;
uint64_t size;
bool merge, dump;
bool prealloc, force_prealloc, is_mapped;
bool prealloc, force_prealloc, is_mapped, share;
DECLARE_BITMAP(host_nodes, MAX_NODES + 1);
HostMemPolicy policy;

Expand Down
2 changes: 1 addition & 1 deletion include/sysemu/kvm.h
Original file line number Diff line number Diff line change
Expand Up @@ -248,7 +248,7 @@ int kvm_on_sigbus(int code, void *addr);

/* interface with exec.c */

void phys_mem_set_alloc(void *(*alloc)(size_t, uint64_t *align));
void phys_mem_set_alloc(void *(*alloc)(size_t, uint64_t *align, bool shared));

/* internal API */

Expand Down
16 changes: 13 additions & 3 deletions memory.c
Original file line number Diff line number Diff line change
Expand Up @@ -1538,12 +1538,22 @@ void memory_region_init_ram_nomigrate(MemoryRegion *mr,
const char *name,
uint64_t size,
Error **errp)
{
memory_region_init_ram_shared_nomigrate(mr, owner, name, size, false, errp);
}

void memory_region_init_ram_shared_nomigrate(MemoryRegion *mr,
Object *owner,
const char *name,
uint64_t size,
bool share,
Error **errp)
{
memory_region_init(mr, owner, name, size);
mr->ram = true;
mr->terminates = true;
mr->destructor = memory_region_destructor_ram;
mr->ram_block = qemu_ram_alloc(size, mr, errp);
mr->ram_block = qemu_ram_alloc(size, share, mr, errp);
mr->dirty_log_mask = tcg_enabled() ? (1 << DIRTY_MEMORY_CODE) : 0;
}

Expand Down Expand Up @@ -1654,7 +1664,7 @@ void memory_region_init_rom_nomigrate(MemoryRegion *mr,
mr->readonly = true;
mr->terminates = true;
mr->destructor = memory_region_destructor_ram;
mr->ram_block = qemu_ram_alloc(size, mr, errp);
mr->ram_block = qemu_ram_alloc(size, false, mr, errp);
mr->dirty_log_mask = tcg_enabled() ? (1 << DIRTY_MEMORY_CODE) : 0;
}

Expand All @@ -1673,7 +1683,7 @@ void memory_region_init_rom_device_nomigrate(MemoryRegion *mr,
mr->terminates = true;
mr->rom_device = true;
mr->destructor = memory_region_destructor_ram;
mr->ram_block = qemu_ram_alloc(size, mr, errp);
mr->ram_block = qemu_ram_alloc(size, false, mr, errp);
}

void memory_region_init_iommu(void *_iommu_mr,
Expand Down
10 changes: 9 additions & 1 deletion qemu-options.hx
Original file line number Diff line number Diff line change
Expand Up @@ -3975,6 +3975,14 @@ The @option{share} boolean option determines whether the memory
region is marked as private to QEMU, or shared. The latter allows
a co-operating external process to access the QEMU memory region.

The @option{share} is also required for pvrdma devices due to
limitations in the RDMA API provided by Linux.

Setting share=on might affect the ability to configure NUMA
bindings for the memory backend under some circumstances, see
Documentation/vm/numa_memory_policy.txt on the Linux kernel
source tree for additional details.

Setting the @option{discard-data} boolean option to @var{on}
indicates that file contents can be destroyed when QEMU exits,
to avoid unnecessarily flushing data to the backing file. Note
Expand Down Expand Up @@ -4017,7 +4025,7 @@ requires an alignment different than the default one used by QEMU, eg
the device DAX /dev/dax0.0 requires 2M alignment rather than 4K. In
such cases, users can specify the required alignment via this option.

@item -object memory-backend-ram,id=@var{id},merge=@var{on|off},dump=@var{on|off},prealloc=@var{on|off},size=@var{size},host-nodes=@var{host-nodes},policy=@var{default|preferred|bind|interleave}
@item -object memory-backend-ram,id=@var{id},merge=@var{on|off},dump=@var{on|off},share=@var{on|off},prealloc=@var{on|off},size=@var{size},host-nodes=@var{host-nodes},policy=@var{default|preferred|bind|interleave}

Creates a memory backend object, which can be used to back the guest RAM.
Memory backend objects offer more control than the @option{-m} option that is
Expand Down
4 changes: 2 additions & 2 deletions target/s390x/kvm.c
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ static int cap_gs;

static int active_cmma;

static void *legacy_s390_alloc(size_t size, uint64_t *align);
static void *legacy_s390_alloc(size_t size, uint64_t *align, bool shared);

static int kvm_s390_query_mem_limit(uint64_t *memory_limit)
{
Expand Down Expand Up @@ -752,7 +752,7 @@ int kvm_s390_mem_op(S390CPU *cpu, vaddr addr, uint8_t ar, void *hostbuf,
* to grow. We also have to use MAP parameters that avoid
* read-only mapping of guest pages.
*/
static void *legacy_s390_alloc(size_t size, uint64_t *align)
static void *legacy_s390_alloc(size_t size, uint64_t *align, bool shared)
{
void *mem;

Expand Down
4 changes: 2 additions & 2 deletions util/oslib-posix.c
Original file line number Diff line number Diff line change
Expand Up @@ -127,10 +127,10 @@ void *qemu_memalign(size_t alignment, size_t size)
}

/* alloc shared memory pages */
void *qemu_anon_ram_alloc(size_t size, uint64_t *alignment)
void *qemu_anon_ram_alloc(size_t size, uint64_t *alignment, bool shared)
{
size_t align = QEMU_VMALLOC_ALIGN;
void *ptr = qemu_ram_mmap(-1, size, align, false);
void *ptr = qemu_ram_mmap(-1, size, align, shared);

if (ptr == MAP_FAILED) {
return NULL;
Expand Down
2 changes: 1 addition & 1 deletion util/oslib-win32.c
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ void *qemu_memalign(size_t alignment, size_t size)
return qemu_oom_check(qemu_try_memalign(alignment, size));
}

void *qemu_anon_ram_alloc(size_t size, uint64_t *align)
void *qemu_anon_ram_alloc(size_t size, uint64_t *align, bool shared)
{
void *ptr;

Expand Down

0 comments on commit 06329cc

Please sign in to comment.