|
@@ -1808,6 +1808,7 @@ static void ram_block_add(RAMBlock *new_block, Error **errp)
|
|
const bool shared = qemu_ram_is_shared(new_block);
|
|
const bool shared = qemu_ram_is_shared(new_block);
|
|
RAMBlock *block;
|
|
RAMBlock *block;
|
|
RAMBlock *last_block = NULL;
|
|
RAMBlock *last_block = NULL;
|
|
|
|
+ bool free_on_error = false;
|
|
ram_addr_t old_ram_size, new_ram_size;
|
|
ram_addr_t old_ram_size, new_ram_size;
|
|
Error *err = NULL;
|
|
Error *err = NULL;
|
|
|
|
|
|
@@ -1837,6 +1838,19 @@ static void ram_block_add(RAMBlock *new_block, Error **errp)
|
|
return;
|
|
return;
|
|
}
|
|
}
|
|
memory_try_enable_merging(new_block->host, new_block->max_length);
|
|
memory_try_enable_merging(new_block->host, new_block->max_length);
|
|
|
|
+ free_on_error = true;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (new_block->flags & RAM_GUEST_MEMFD) {
|
|
|
|
+ assert(kvm_enabled());
|
|
|
|
+ assert(new_block->guest_memfd < 0);
|
|
|
|
+
|
|
|
|
+ new_block->guest_memfd = kvm_create_guest_memfd(new_block->max_length,
|
|
|
|
+ 0, errp);
|
|
|
|
+ if (new_block->guest_memfd < 0) {
|
|
|
|
+ qemu_mutex_unlock_ramlist();
|
|
|
|
+ goto out_free;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
@@ -1888,6 +1902,13 @@ static void ram_block_add(RAMBlock *new_block, Error **errp)
|
|
ram_block_notify_add(new_block->host, new_block->used_length,
|
|
ram_block_notify_add(new_block->host, new_block->used_length,
|
|
new_block->max_length);
|
|
new_block->max_length);
|
|
}
|
|
}
|
|
|
|
+ return;
|
|
|
|
+
|
|
|
|
+out_free:
|
|
|
|
+ if (free_on_error) {
|
|
|
|
+ qemu_anon_ram_free(new_block->host, new_block->max_length);
|
|
|
|
+ new_block->host = NULL;
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
|
|
#ifdef CONFIG_POSIX
|
|
#ifdef CONFIG_POSIX
|
|
@@ -1902,7 +1923,7 @@ RAMBlock *qemu_ram_alloc_from_fd(ram_addr_t size, MemoryRegion *mr,
|
|
/* Just support these ram flags by now. */
|
|
/* Just support these ram flags by now. */
|
|
assert((ram_flags & ~(RAM_SHARED | RAM_PMEM | RAM_NORESERVE |
|
|
assert((ram_flags & ~(RAM_SHARED | RAM_PMEM | RAM_NORESERVE |
|
|
RAM_PROTECTED | RAM_NAMED_FILE | RAM_READONLY |
|
|
RAM_PROTECTED | RAM_NAMED_FILE | RAM_READONLY |
|
|
- RAM_READONLY_FD)) == 0);
|
|
|
|
|
|
+ RAM_READONLY_FD | RAM_GUEST_MEMFD)) == 0);
|
|
|
|
|
|
if (xen_enabled()) {
|
|
if (xen_enabled()) {
|
|
error_setg(errp, "-mem-path not supported with Xen");
|
|
error_setg(errp, "-mem-path not supported with Xen");
|
|
@@ -1939,6 +1960,7 @@ RAMBlock *qemu_ram_alloc_from_fd(ram_addr_t size, MemoryRegion *mr,
|
|
new_block->used_length = size;
|
|
new_block->used_length = size;
|
|
new_block->max_length = size;
|
|
new_block->max_length = size;
|
|
new_block->flags = ram_flags;
|
|
new_block->flags = ram_flags;
|
|
|
|
+ new_block->guest_memfd = -1;
|
|
new_block->host = file_ram_alloc(new_block, size, fd, !file_size, offset,
|
|
new_block->host = file_ram_alloc(new_block, size, fd, !file_size, offset,
|
|
errp);
|
|
errp);
|
|
if (!new_block->host) {
|
|
if (!new_block->host) {
|
|
@@ -2018,7 +2040,7 @@ RAMBlock *qemu_ram_alloc_internal(ram_addr_t size, ram_addr_t max_size,
|
|
int align;
|
|
int align;
|
|
|
|
|
|
assert((ram_flags & ~(RAM_SHARED | RAM_RESIZEABLE | RAM_PREALLOC |
|
|
assert((ram_flags & ~(RAM_SHARED | RAM_RESIZEABLE | RAM_PREALLOC |
|
|
- RAM_NORESERVE)) == 0);
|
|
|
|
|
|
+ RAM_NORESERVE | RAM_GUEST_MEMFD)) == 0);
|
|
assert(!host ^ (ram_flags & RAM_PREALLOC));
|
|
assert(!host ^ (ram_flags & RAM_PREALLOC));
|
|
|
|
|
|
align = qemu_real_host_page_size();
|
|
align = qemu_real_host_page_size();
|
|
@@ -2033,6 +2055,7 @@ RAMBlock *qemu_ram_alloc_internal(ram_addr_t size, ram_addr_t max_size,
|
|
new_block->max_length = max_size;
|
|
new_block->max_length = max_size;
|
|
assert(max_size >= size);
|
|
assert(max_size >= size);
|
|
new_block->fd = -1;
|
|
new_block->fd = -1;
|
|
|
|
+ new_block->guest_memfd = -1;
|
|
new_block->page_size = qemu_real_host_page_size();
|
|
new_block->page_size = qemu_real_host_page_size();
|
|
new_block->host = host;
|
|
new_block->host = host;
|
|
new_block->flags = ram_flags;
|
|
new_block->flags = ram_flags;
|
|
@@ -2055,7 +2078,7 @@ RAMBlock *qemu_ram_alloc_from_ptr(ram_addr_t size, void *host,
|
|
RAMBlock *qemu_ram_alloc(ram_addr_t size, uint32_t ram_flags,
|
|
RAMBlock *qemu_ram_alloc(ram_addr_t size, uint32_t ram_flags,
|
|
MemoryRegion *mr, Error **errp)
|
|
MemoryRegion *mr, Error **errp)
|
|
{
|
|
{
|
|
- assert((ram_flags & ~(RAM_SHARED | RAM_NORESERVE)) == 0);
|
|
|
|
|
|
+ assert((ram_flags & ~(RAM_SHARED | RAM_NORESERVE | RAM_GUEST_MEMFD)) == 0);
|
|
return qemu_ram_alloc_internal(size, size, NULL, NULL, ram_flags, mr, errp);
|
|
return qemu_ram_alloc_internal(size, size, NULL, NULL, ram_flags, mr, errp);
|
|
}
|
|
}
|
|
|
|
|
|
@@ -2083,6 +2106,11 @@ static void reclaim_ramblock(RAMBlock *block)
|
|
} else {
|
|
} else {
|
|
qemu_anon_ram_free(block->host, block->max_length);
|
|
qemu_anon_ram_free(block->host, block->max_length);
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+ if (block->guest_memfd >= 0) {
|
|
|
|
+ close(block->guest_memfd);
|
|
|
|
+ }
|
|
|
|
+
|
|
g_free(block);
|
|
g_free(block);
|
|
}
|
|
}
|
|
|
|
|