* split kvm_create() into smaller pieces which can be individually called if needed. * add kvm_register_userspace_phys_mem() function. --- user/kvmctl.c | 61 +++++++++++++++++++++++++++++++++++++++++++++++++++++----- user/kvmctl.h | 8 +++++++ 2 files changed, 64 insertions(+), 5 deletions(-) Index: kvm-46/user/kvmctl.c =================================================================== --- kvm-46.orig/user/kvmctl.c +++ kvm-46/user/kvmctl.c @@ -427,12 +427,9 @@ int kvm_alloc_userspace_memory(kvm_conte return 0; } -int kvm_create(kvm_context_t kvm, unsigned long phys_mem_bytes, void **vm_mem) +int kvm_create_vm(kvm_context_t kvm) { - unsigned long memory = (phys_mem_bytes + PAGE_SIZE - 1) & PAGE_MASK; int fd = kvm->fd; - int zfd; - int r; kvm->vcpu_fd[0] = -1; @@ -442,6 +439,15 @@ int kvm_create(kvm_context_t kvm, unsign return -1; } kvm->vm_fd = fd; + return 0; +} + +int kvm_create_default_phys_mem(kvm_context_t kvm, unsigned long phys_mem_bytes, + void **vm_mem) +{ + unsigned long memory = (phys_mem_bytes + PAGE_SIZE - 1) & PAGE_MASK; + int zfd; + int r; r = ioctl(kvm->fd, KVM_CHECK_EXTENSION, KVM_CAP_USER_MEMORY); if (r > 0) @@ -457,18 +463,37 @@ int kvm_create(kvm_context_t kvm, unsign close(zfd); kvm->physical_memory = *vm_mem; + return 0; +} + +void kvm_create_irqchip(kvm_context_t kvm) +{ + int r; kvm->irqchip_in_kernel = 0; if (!kvm->no_irqchip_creation) { r = ioctl(kvm->fd, KVM_CHECK_EXTENSION, KVM_CAP_IRQCHIP); if (r > 0) { /* kernel irqchip supported */ - r = ioctl(fd, KVM_CREATE_IRQCHIP); + r = ioctl(kvm->vm_fd, KVM_CREATE_IRQCHIP); if (r >= 0) kvm->irqchip_in_kernel = 1; else printf("Create kernel PIC irqchip failed\n"); } } +} + +int kvm_create(kvm_context_t kvm, unsigned long phys_mem_bytes, void **vm_mem) +{ + int r; + + r = kvm_create_vm(kvm); + if (r < 0) + return r; + r = kvm_create_default_phys_mem(kvm, phys_mem_bytes, vm_mem); + if (r < 0) + return r; + kvm_create_irqchip(kvm); r = kvm_create_vcpu(kvm, 0); if (r < 0) return r; @@ -558,6 +583,32 @@ void *kvm_create_phys_mem(kvm_context_t log, writable); } +int kvm_register_userspace_phys_mem(kvm_context_t kvm, + unsigned long phys_start, void *userspace_addr, + unsigned long len, int slot, int log) +{ + struct kvm_userspace_memory_region memory = { + .slot = slot, + .memory_size = len, + .guest_phys_addr = phys_start, + .userspace_addr = (intptr_t)userspace_addr, + .flags = log ? KVM_MEM_LOG_DIRTY_PAGES : 0, + }; + int r; + + if (!kvm->physical_memory) + kvm->physical_memory = userspace_addr - phys_start; + + r = ioctl(kvm->vm_fd, KVM_SET_USER_MEMORY_REGION, &memory); + if (r == -1) { + fprintf(stderr, "create_userspace_phys_mem: %s", strerror(errno)); + return -1; + } + + kvm_userspace_memory_region_save_params(kvm, &memory); + return 0; +} + /* destroy/free a whole slot. * phys_start, len and slot are the params passed to kvm_create_phys_mem() */ Index: kvm-46/user/kvmctl.h =================================================================== --- kvm-46.orig/user/kvmctl.h +++ kvm-46/user/kvmctl.h @@ -137,6 +137,11 @@ int kvm_get_shadow_pages(kvm_context_t k int kvm_create(kvm_context_t kvm, unsigned long phys_mem_bytes, void **phys_mem); +int kvm_create_vm(kvm_context_t kvm); +int kvm_create_default_phys_mem(kvm_context_t kvm, unsigned long phys_mem_bytes, + void **vm_mem); +void kvm_create_irqchip(kvm_context_t kvm); + /*! * \brief Create a new virtual cpu * @@ -404,6 +409,9 @@ void *kvm_create_phys_mem(kvm_context_t, unsigned long len, int slot, int log, int writable); void kvm_destroy_phys_mem(kvm_context_t, unsigned long phys_start, unsigned long len, int slot); +int kvm_register_userspace_phys_mem(kvm_context_t kvm, + unsigned long phys_start, void *userspace_addr, + unsigned long len, int slot, int log); int kvm_get_dirty_pages(kvm_context_t, int slot, void *buf);