@@ -25,7 +25,7 @@ struct kvm {
struct interrupt_table interrupt_table;
};
-struct kvm *kvm__init(const char *kvm_dev, unsigned long ram_size);
+struct kvm *kvm__init(const char *kvm_dev, unsigned long ram_size, bool use_backing);
void kvm__init_ram(struct kvm *self);
void kvm__delete(struct kvm *self);
bool kvm__load_kernel(struct kvm *kvm, const char *kernel_filename,
@@ -69,6 +69,7 @@ static const char *host_ip_addr;
static const char *guest_mac;
static const char *script;
static bool single_step;
+static bool use_backing;
static bool readonly_image;
extern bool ioport_debug;
extern int active_console;
@@ -84,6 +85,8 @@ static const struct option options[] = {
OPT_GROUP("Basic options:"),
OPT_INTEGER('\0', "cpus", &nrcpus, "Number of CPUs"),
OPT_U64('m', "mem", &ram_size, "Virtual machine memory size in MiB."),
+ OPT_BOOLEAN('\0', "use-backing", &use_backing,
+ "Use a backing file for virtual RAM"),
OPT_STRING('i', "image", &image_filename, "image", "Disk image"),
OPT_BOOLEAN('\0', "readonly", &readonly_image,
"Don't write changes back to disk image"),
@@ -366,7 +369,7 @@ int kvm_cmd_run(int argc, const char **argv, const char *prefix)
term_init();
- kvm = kvm__init(kvm_dev, ram_size);
+ kvm = kvm__init(kvm_dev, ram_size, use_backing);
memset(real_cmdline, 0, sizeof(real_cmdline));
strcpy(real_cmdline, "notsc nolapic noacpi pci=conf1 console=ttyS0 ");
@@ -170,11 +170,12 @@ void kvm__init_ram(struct kvm *self)
die_perror("KVM_SET_USER_MEMORY_REGION ioctl");
}
-struct kvm *kvm__init(const char *kvm_dev, unsigned long ram_size)
+struct kvm *kvm__init(const char *kvm_dev, unsigned long ram_size, bool use_backing)
{
struct kvm_pit_config pit_config = { .flags = 0, };
struct kvm *self;
int ret;
+ int backfd;
if (!kvm__cpu_supports_vm())
die("Your CPU does not support hardware virtualization");
@@ -214,7 +215,23 @@ struct kvm *kvm__init(const char *kvm_dev, unsigned long ram_size)
self->ram_size = ram_size;
- self->ram_start = mmap(NULL, ram_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE, -1, 0);
+ if (use_backing) {
+ char tmp_template[] = "/tmp/kvm_ram.XXXXXX";
+
+ backfd = mkstemp(tmp_template);
+ if (backfd < 0)
+ die("Failed creating RAM backing file");
+
+ unlink(tmp_template);
+
+ if (ftruncate(backfd, ram_size) < 0)
+ die("Failed resizing RAM backing file");
+
+ self->ram_start = mmap(NULL, ram_size, PROT_READ | PROT_WRITE, MAP_SHARED, backfd, 0);
+ } else {
+ self->ram_start = mmap(NULL, ram_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE, -1, 0);
+ }
+
if (self->ram_start == MAP_FAILED)
die("out of memory");
Using mmap to allocate the RAM enables us to allocate large blocks of memory for the guest, allowing to boot guests with a large RAM. Since if we try KVM_SET_USER_MEMORY_REGION with a large memory block KVM used to Oops (now it just fails), we had to move the actual ioctl to after we KVM_CREATE_VCPU. Signed-off-by: Sasha Levin <levinsasha928@gmail.com> --- tools/kvm/include/kvm/kvm.h | 2 +- tools/kvm/kvm-run.c | 5 ++++- tools/kvm/kvm.c | 21 +++++++++++++++++++-- 3 files changed, 24 insertions(+), 4 deletions(-)