Signed-off-by: Luiz Capitulino<lcapitul...@redhat.com>
---
cpu-all.h | 1 +
exec-obsolete.h | 1 +
exec.c | 25 +++++++++++++++++++++----
memory.c | 5 +++++
memory.h | 5 +++++
qemu-options.hx | 7 +++++++
vl.c | 3 +++
7 files changed, 43 insertions(+), 4 deletions(-)
diff --git a/cpu-all.h b/cpu-all.h
index 9dc249a..429c1c3 100644
--- a/cpu-all.h
+++ b/cpu-all.h
@@ -484,6 +484,7 @@ typedef struct RAMBlock {
} RAMBlock;
typedef struct RAMList {
+ bool merge_memory;
uint8_t *phys_dirty;
QLIST_HEAD(, RAMBlock) blocks;
} RAMList;
diff --git a/exec-obsolete.h b/exec-obsolete.h
index 792c831..71faf81 100644
--- a/exec-obsolete.h
+++ b/exec-obsolete.h
@@ -30,6 +30,7 @@ ram_addr_t qemu_ram_alloc_from_ptr(ram_addr_t size, void
*host,
ram_addr_t qemu_ram_alloc(ram_addr_t size, MemoryRegion *mr);
void qemu_ram_free(ram_addr_t addr);
void qemu_ram_free_from_ptr(ram_addr_t addr);
+void qemu_set_mem_merge(bool value);
struct MemoryRegion;
struct MemoryRegionSection;
diff --git a/exec.c b/exec.c
index 8244d54..c003789 100644
--- a/exec.c
+++ b/exec.c
@@ -112,7 +112,10 @@ static uint8_t *code_gen_ptr;
int phys_ram_fd;
static int in_migration;
-RAMList ram_list = { .blocks = QLIST_HEAD_INITIALIZER(ram_list.blocks) };
+RAMList ram_list = {
+ .merge_memory = true,
+ .blocks = QLIST_HEAD_INITIALIZER(ram_list.blocks)
+};
static MemoryRegion *system_memory;
static MemoryRegion *system_io;
@@ -2499,6 +2502,20 @@ void qemu_ram_set_idstr(ram_addr_t addr, const char
*name, DeviceState *dev)
}
}
+void qemu_set_mem_merge(bool value)
+{
+ ram_list.merge_memory = value;
+}
+
+static int madvise_mergeable(void *addr, size_t len)
+{
+ if (ram_list.merge_memory) {
+ return qemu_madvise(addr, len, QEMU_MADV_MERGEABLE);
+ }
+
+ return -1;
+}
+
ram_addr_t qemu_ram_alloc_from_ptr(ram_addr_t size, void *host,
MemoryRegion *mr)
{
@@ -2518,7 +2535,7 @@ ram_addr_t qemu_ram_alloc_from_ptr(ram_addr_t size, void
*host,
new_block->host = file_ram_alloc(new_block, size, mem_path);
if (!new_block->host) {
new_block->host = qemu_vmalloc(size);
- qemu_madvise(new_block->host, size, QEMU_MADV_MERGEABLE);
+ madvise_mergeable(new_block->host, size);
}
#else
fprintf(stderr, "-mem-path option unsupported\n");
@@ -2545,7 +2562,7 @@ ram_addr_t qemu_ram_alloc_from_ptr(ram_addr_t size, void
*host,
new_block->host = qemu_vmalloc(size);
}
#endif
- qemu_madvise(new_block->host, size, QEMU_MADV_MERGEABLE);
+ madvise_mergeable(new_block->host, size);
}
}
new_block->length = size;
@@ -2672,7 +2689,7 @@ void qemu_ram_remap(ram_addr_t addr, ram_addr_t length)
length, addr);
exit(1);
}
- qemu_madvise(vaddr, length, QEMU_MADV_MERGEABLE);
+ madvise_mergeable(vaddr, length);
}
return;
}
diff --git a/memory.c b/memory.c
index aab4a31..71789ab 100644
--- a/memory.c
+++ b/memory.c
@@ -1439,6 +1439,11 @@ void memory_global_dirty_log_stop(void)
MEMORY_LISTENER_CALL_GLOBAL(log_global_stop, Reverse);
}
+void memory_global_set_merge(bool value)
+{
+ qemu_set_mem_merge(value);
+}
+
static void listener_add_address_space(MemoryListener *listener,
AddressSpace *as)
{
diff --git a/memory.h b/memory.h
index 740c48e..ac224d4 100644
--- a/memory.h
+++ b/memory.h
@@ -746,6 +746,11 @@ void memory_global_dirty_log_start(void);
*/
void memory_global_dirty_log_stop(void);
+/**
+ * memory_global_set_merge: enable/disable memory merging done by the host
+ */
+void memory_global_set_merge(bool value);
+
void mtree_info(fprintf_function mon_printf, void *f);
#endif
diff --git a/qemu-options.hx b/qemu-options.hx
index 8b66264..324cc97 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -409,6 +409,13 @@ Preallocate memory when using -mem-path.
ETEXI
#endif
+DEF("disable-mem-merge", 0, QEMU_OPTION_disable_mem_merge,
+ "-disable-mem-merge disable memory merging.", QEMU_ARCH_ALL)
+STEXI
+@item -disable-mem-merge
+Disable memory merging. On Linux systems this disables KSM support.
+ETEXI
+
DEF("k", HAS_ARG, QEMU_OPTION_k,
"-k language use keyboard layout (for example 'fr' for French)\n",
QEMU_ARCH_ALL)
diff --git a/vl.c b/vl.c
index 1329c30..f81aadf 100644
--- a/vl.c
+++ b/vl.c
@@ -2676,6 +2676,9 @@ int main(int argc, char **argv, char **envp)
mem_prealloc = 1;
break;
#endif
+ case QEMU_OPTION_disable_mem_merge:
+ memory_global_set_merge(false);
+ break;
case QEMU_OPTION_d:
log_mask = optarg;
break;