kvm tools: Use mmap to allocate guest RAM

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>
Signed-off-by: Pekka Enberg <penberg@kernel.org>
This commit is contained in:
Sasha Levin
2015-06-01 16:39:42 +01:00
committed by Will Deacon
parent a51948cef1
commit 839051d949
3 changed files with 25 additions and 16 deletions
+1
View File
@@ -26,6 +26,7 @@ struct kvm {
};
struct kvm *kvm__init(const char *kvm_dev, unsigned long ram_size);
void kvm__init_ram(struct kvm *self);
void kvm__delete(struct kvm *self);
bool kvm__load_kernel(struct kvm *kvm, const char *kernel_filename,
const char *initrd_filename, const char *kernel_cmdline);
+4
View File
@@ -437,7 +437,11 @@ int kvm_cmd_run(int argc, const char **argv, const char *prefix)
if (single_step)
kvm_cpu__enable_singlestep(kvm_cpus[i]);
}
kvm__init_ram(kvm);
for (i = 0; i < nrcpus; i++) {
if (pthread_create(&kvm_cpus[i]->thread, NULL, kvm_cpu_thread, kvm_cpus[i]) != 0)
die("unable to create KVM VCPU thread");
}
+20 -16
View File
@@ -107,7 +107,7 @@ void kvm__delete(struct kvm *self)
{
kvm__stop_timer(self);
free(self->ram_start);
munmap(self->ram_start, self->ram_size);
free(self);
}
@@ -153,12 +153,27 @@ static bool kvm__cpu_supports_vm(void)
return regs.ecx & (1 << feature);
}
struct kvm *kvm__init(const char *kvm_dev, unsigned long ram_size)
void kvm__init_ram(struct kvm *self)
{
struct kvm_userspace_memory_region mem;
int ret;
mem = (struct kvm_userspace_memory_region) {
.slot = 0,
.guest_phys_addr = 0x0UL,
.memory_size = self->ram_size,
.userspace_addr = (unsigned long) self->ram_start,
};
ret = ioctl(self->vm_fd, KVM_SET_USER_MEMORY_REGION, &mem);
if (ret < 0)
die_perror("KVM_SET_USER_MEMORY_REGION ioctl");
}
struct kvm *kvm__init(const char *kvm_dev, unsigned long ram_size)
{
struct kvm_pit_config pit_config = { .flags = 0, };
struct kvm *self;
long page_size;
int ret;
if (!kvm__cpu_supports_vm())
@@ -199,21 +214,10 @@ struct kvm *kvm__init(const char *kvm_dev, unsigned long ram_size)
self->ram_size = ram_size;
page_size = sysconf(_SC_PAGESIZE);
if (posix_memalign(&self->ram_start, page_size, self->ram_size) != 0)
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");
mem = (struct kvm_userspace_memory_region) {
.slot = 0,
.guest_phys_addr = 0x0UL,
.memory_size = self->ram_size,
.userspace_addr = (unsigned long) self->ram_start,
};
ret = ioctl(self->vm_fd, KVM_SET_USER_MEMORY_REGION, &mem);
if (ret < 0)
die_perror("KVM_SET_USER_MEMORY_REGION ioctl");
ret = ioctl(self->vm_fd, KVM_CREATE_IRQCHIP);
if (ret < 0)
die_perror("KVM_CREATE_IRQCHIP ioctl");