void *kvm_create_phys_mem(kvm_context_t kvm, unsigned long phys_start, unsigned long len, int slot, int log, int writable) { void *ptr; // int r; int fd = kvm->vm_fd; // int prot = PROT_READ; BOOL ret; int retlen; struct winkvm_memory_region memory; struct winkvm_memmap maparea; fprintf(stderr, "called %s\n", __FUNCTION__); maparea.init.slot = kvm->current_mapping_slot; maparea.init.base_gfn = phys_start >> PAGE_SHIFT; maparea.init.npages = len >> PAGE_SHIFT; if (!SetMemmapArea(kvm, &maparea)) { fprintf(stderr, "Could not initialize Memmap Area: %m\n"); return NULL; } else { kvm->current_mapping_slot++; } /* struct kvm_memory_region memory = { .slot = slot, .memory_size = len, .guest_phys_addr = phys_start, .flags = log ? KVM_MEM_LOG_DIRTY_PAGES : 0, }; */ /* r = ioctl(fd, KVM_SET_MEMORY_REGION, &memory); */ /* if (r == -1) return 0; */ memory.vm_fd = fd; memory.kvm_memory_region.slot = slot; memory.kvm_memory_region.memory_size = len; memory.kvm_memory_region.guest_phys_addr = phys_start; memory.kvm_memory_region.flags = log ? KVM_MEM_LOG_DIRTY_PAGES : 0; fprintf(stderr, "%s\n" " VM_FD : %d\n" " MEMORY REGION (flag) : 0x%08x\n" " MEMORY REGION (memory_size) : %d [bytes]\n" " MEMORY REGION (slot) : %d\n" " MEMORY REGION (guest_phys_addr) : 0x%08lx\n", __FUNCTION__, memory.vm_fd, memory.kvm_memory_region.flags, memory.kvm_memory_region.memory_size, memory.kvm_memory_region.slot, memory.kvm_memory_region.guest_phys_addr); ret = DeviceIoControl( kvm->hnd, KVM_SET_MEMORY_REGION, &memory, sizeof(struct winkvm_memory_region), &memory, sizeof(struct winkvm_memory_region), &retlen, NULL); if (!ret) { return 0; } kvm_memory_region_save_params(kvm, &(memory.kvm_memory_region)); winkvm_mapping_region_save_params(kvm, &maparea); // if (writable) // prot |= PROT_WRITE; // ptr = mmap(0, len, prot, MAP_SHARED, fd, phys_start); ptr = WkVirtualAlloc(kvm, &maparea); if (ptr == NULL) return 0; fprintf(stderr, "Reserve memory: 0x%p\n", ptr); return ptr; }
int kvm_create(kvm_context_t kvm, unsigned long phys_mem_bytes, void **vm_mem) { unsigned long dosmem = 0xa0000; unsigned long exmem = 0xc0000; unsigned long pcimem = 0xf0000000; unsigned long memory = (phys_mem_bytes + PAGE_SIZE - 1) & PAGE_MASK; int fd = kvm->fd; int zfd; int r; struct kvm_userspace_memory_region low_memory = { .slot = 3, .memory_size = memory < dosmem ? memory : dosmem, .guest_phys_addr = 0, }; struct kvm_userspace_memory_region extended_memory = { .slot = 0, .memory_size = memory < exmem ? 0 : memory - exmem, .guest_phys_addr = exmem, }; struct kvm_userspace_memory_region above_4g_memory = { .slot = 4, .memory_size = memory < pcimem ? 0 : memory - pcimem, .guest_phys_addr = 0x100000000, }; if (memory >= pcimem) extended_memory.memory_size = pcimem - exmem; kvm->vcpu_fd[0] = -1; fd = ioctl(fd, KVM_CREATE_VM, 0); if (fd == -1) { fprintf(stderr, "kvm_create_vm: %m\n"); return -1; } kvm->vm_fd = fd; kvm->physical_memory = mmap(NULL, extended_memory.memory_size + exmem, 7, MAP_ANON|MAP_SHARED, -1, 0); /* 640K should be enough. */ low_memory.userspace_addr = kvm->physical_memory; r = ioctl(fd, KVM_SET_USER_MEMORY_REGION, &low_memory); if (r == -1) { fprintf(stderr, "kvm_create_memory_region: %m\n"); return -1; } if (extended_memory.memory_size) { extended_memory.userspace_addr = kvm->physical_memory + exmem; r = ioctl(fd, KVM_SET_USER_MEMORY_REGION, &extended_memory); if (r == -1) { fprintf(stderr, "kvm_create_memory_region: %m\n"); return -1; } } *vm_mem = kvm->physical_memory; /*if (above_4g_memory.memory_size) { above_4g_memory.userspace_addr = mmap(NULL, above_4g_memory.memory_size, 7, MAP_ANON|MAP_SHARED, -1, 0); r = ioctl(fd, KVM_SET_USER_MEMORY_REGION, &above_4g_memory); if (r == -1) { fprintf(stderr, "kvm_create_memory_region: %m\n"); return -1; } }*/ /*kvm_memory_region_save_params(kvm, &low_memory); kvm_memory_region_save_params(kvm, &extended_memory); kvm_memory_region_save_params(kvm, &above_4g_memory);*/ /**vm_mem = mmap(NULL, memory, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); if (*vm_mem == MAP_FAILED) { fprintf(stderr, "mmap: %m\n"); return -1; } kvm->physical_memory = *vm_mem;*/ /*zfd = open("/dev/zero", O_RDONLY); mmap(*vm_mem + 0xa8000, 0x8000, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED, zfd, 0); close(zfd);*/ //kvm->physical_memory = low_memory.userspace_addr; 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, NULL); if (r >= 0) kvm->irqchip_in_kernel = 1; else printf("Create kernel PIC irqchip failed\n"); } } r = kvm_create_vcpu(kvm, 0); if (r < 0) return r; return 0; } void *kvm_create_phys_mem(kvm_context_t kvm, unsigned long phys_start, unsigned long len, int slot, int log, int writable) { void *ptr; int r; int fd = kvm->vm_fd; int prot = PROT_READ; struct kvm_memory_region memory = { .slot = slot, .memory_size = len, .guest_phys_addr = phys_start, .flags = log ? KVM_MEM_LOG_DIRTY_PAGES : 0, }; r = ioctl(fd, KVM_SET_MEMORY_REGION, &memory); if (r == -1) return 0; kvm_memory_region_save_params(kvm, &memory); if (writable) prot |= PROT_WRITE; ptr = mmap(NULL, len, prot, MAP_SHARED, fd, phys_start); if (ptr == MAP_FAILED) return 0; return ptr; } /* destroy/free a whole slot. * phys_start, len and slot are the params passed to kvm_create_phys_mem() */ void kvm_destroy_phys_mem(kvm_context_t kvm, unsigned long phys_start, unsigned long len, int slot) { struct kvm_memory_region *mem; if (slot >= KVM_MAX_NUM_MEM_REGIONS) { fprintf(stderr, "BUG: %s: invalid parameters (slot=%d)\n", __FUNCTION__, slot); return; } mem = &kvm->mem_regions[slot]; if (phys_start != mem->guest_phys_addr) { fprintf(stderr, "WARNING: %s: phys_start is 0x%lx expecting 0x%llx\n", __FUNCTION__, phys_start, mem->guest_phys_addr); phys_start = mem->guest_phys_addr; } kvm_create_phys_mem(kvm, phys_start, 0, slot, 0, 0); } int kvm_create_memory_alias(kvm_context_t kvm, int slot, uint64_t phys_start, uint64_t len, uint64_t target_phys) { struct kvm_memory_alias alias = { .slot = slot, .flags = 0, .guest_phys_addr = phys_start, .memory_size = len, .target_phys_addr = target_phys, }; int fd = kvm->vm_fd; int r; r = ioctl(fd, KVM_SET_MEMORY_ALIAS, &alias); if (r == -1) return -errno; return 0; } int kvm_destroy_memory_alias(kvm_context_t kvm, int slot) { return kvm_create_memory_alias(kvm, slot, 0, 0, 0); } static int kvm_get_map(kvm_context_t kvm, int ioctl_num, int slot, void *buf) { int r; struct kvm_dirty_log log = { .slot = slot, }; log.dirty_bitmap = buf; r = ioctl(kvm->vm_fd, ioctl_num, &log); if (r == -1) return -errno; return 0; } int kvm_get_dirty_pages(kvm_context_t kvm, int slot, void *buf) { return kvm_get_map(kvm, KVM_GET_DIRTY_LOG, slot, buf); } int kvm_get_mem_map(kvm_context_t kvm, int slot, void *buf) { #ifdef KVM_GET_MEM_MAP return kvm_get_map(kvm, KVM_GET_MEM_MAP, slot, buf); #else /* not KVM_GET_MEM_MAP ==> fake it: all pages exist */ unsigned long i, n, m, npages; unsigned char v; if (slot >= KVM_MAX_NUM_MEM_REGIONS) { errno = -EINVAL; return -1; } npages = kvm->mem_regions[slot].memory_size / PAGE_SIZE; n = npages / 8; m = npages % 8; memset(buf, 0xff, n); /* all pages exist */ v = 0; for (i=0; i<=m; i++) /* last byte may not be "aligned" */ v |= 1<<(7-i); if (v) *(unsigned char*)(buf+n) = v; return 0; #endif /* KVM_GET_MEM_MAP */ } int kvm_set_irq_level(kvm_context_t kvm, int irq, int level) { struct kvm_irq_level event; int r; if (!kvm->irqchip_in_kernel) return 0; event.level = level; event.irq = irq; r = ioctl(kvm->vm_fd, KVM_IRQ_LINE, &event); if (r == -1) perror("kvm_set_irq_level"); return 1; } int kvm_get_irqchip(kvm_context_t kvm, struct kvm_irqchip *chip) { int r; if (!kvm->irqchip_in_kernel) return 0; r = ioctl(kvm->vm_fd, KVM_GET_IRQCHIP, chip); if (r == -1) { r = -errno; perror("kvm_get_irqchip\n"); } return r; } int kvm_set_irqchip(kvm_context_t kvm, struct kvm_irqchip *chip) { int r; if (!kvm->irqchip_in_kernel) return 0; r = ioctl(kvm->vm_fd, KVM_SET_IRQCHIP, chip); if (r == -1) { r = -errno; perror("kvm_set_irqchip\n"); } return r; } int kvm_get_lapic(kvm_context_t kvm, int vcpu, struct kvm_lapic_state *s) { int r; if (!kvm->irqchip_in_kernel) return 0; r = ioctl(kvm->vcpu_fd[vcpu], KVM_GET_LAPIC, s); if (r == -1) { r = -errno; perror("kvm_get_lapic"); } return r; }
int kvm_create(kvm_context_t kvm, unsigned long memory, void **vm_mem) { unsigned long dosmem = 0xa0000; unsigned long exmem = 0xc0000; HANDLE hnd = kvm->hnd; int fd, retlen, vcpufd; // int zfd; // int r; struct winkvm_memory_region low_memory; struct winkvm_memory_region extended_memory; struct winkvm_memmap maparea; struct winkvm_create_vcpu create_vcpu; BOOL ret; kvm_context = kvm; memset(&low_memory, 0, sizeof(struct winkvm_memory_region)); memset(&extended_memory, 0, sizeof(struct winkvm_memory_region)); /* for winkvm */ memset(&maparea, 0, sizeof(struct winkvm_memmap)); fprintf(stderr, "memory size: %d [mbytes]\n", memory / 1024 / 1024); kvm->current_mapping_slot = 0; maparea.init.slot = kvm->current_mapping_slot; maparea.init.base_gfn = 0 >> PAGE_SHIFT; maparea.init.npages = memory >> PAGE_SHIFT; if (!SetMemmapArea(kvm, &maparea)) { fprintf(stderr, "Could not initialize Memmap Area: %m\n"); return -1; } else { kvm->current_mapping_slot++; } /* end */ low_memory.kvm_memory_region.slot = 3; low_memory.kvm_memory_region.memory_size = memory < dosmem ? memory : dosmem; low_memory.kvm_memory_region.guest_phys_addr = 0; extended_memory.kvm_memory_region.slot = 0; extended_memory.kvm_memory_region.memory_size = memory < exmem ? 0 : memory - exmem; extended_memory.kvm_memory_region.guest_phys_addr = exmem; kvm->vcpu_fd[0] = -1; fprintf(stderr, "Create VM ... \n"); ret = DeviceIoControl( hnd, KVM_CREATE_VM, NULL, 0, &fd, sizeof(fd), &retlen, NULL); // fd = ioctl(fd, KVM_CREATE_VM, 0); if (!ret && fd == -1) { fprintf(stderr, "winkvm_create_vm: %m\n"); return -1; } kvm->vm_fd = fd; fprintf(stderr, " Done\n"); fprintf(stderr, "Set Memory Region ... \n"); low_memory.vm_fd = fd; extended_memory.vm_fd = fd; fprintf(stderr, " VM_FD : %d\n" " MEMORY REGION (flag) : 0x%08x\n" " MEMORY REGION (memory_size) : %d [bytes]\n" " MEMORY REGION (slot) : %d\n" " MEMORY REGION (guest_phys_addr) : 0x%08lx\n", low_memory.vm_fd, low_memory.kvm_memory_region.flags, low_memory.kvm_memory_region.memory_size, low_memory.kvm_memory_region.slot, low_memory.kvm_memory_region.guest_phys_addr); /* 640K should be enough. */ // r = ioctl(fd, KVM_SET_MEMORY_REGION, &low_memory); ret = DeviceIoControl( hnd, KVM_SET_MEMORY_REGION, &low_memory, sizeof(struct winkvm_memory_region), &low_memory, sizeof(struct winkvm_memory_region), &retlen, NULL); if (!ret) { fprintf(stderr, "kvm_create_memory_region: %m\n"); return -1; } printf(" Done\n"); if (extended_memory.kvm_memory_region.memory_size) { // r = ioctl(fd, KVM_SET_MEMORY_REGION, &extended_memory); fprintf(stderr, " VM_FD : %d\n" " MEMORY REGION (flag) : 0x%08x\n" " MEMORY REGION (memory_size) : %d [bytes]\n" " MEMORY REGION (slot) : %d\n" " MEMORY REGION (guest_phys_addr) : 0x%08lx\n", extended_memory.vm_fd, extended_memory.kvm_memory_region.flags, extended_memory.kvm_memory_region.memory_size, extended_memory.kvm_memory_region.slot, extended_memory.kvm_memory_region.guest_phys_addr); ret = DeviceIoControl( hnd, KVM_SET_MEMORY_REGION, &extended_memory, sizeof(struct winkvm_memory_region), &extended_memory, sizeof(struct winkvm_memory_region), &retlen, NULL); if (!ret) { fprintf(stderr, "kvm_create_memory_region: %m\n"); return -1; } fprintf(stderr, " Done\n"); } kvm_memory_region_save_params(kvm, &low_memory.kvm_memory_region); kvm_memory_region_save_params(kvm, &extended_memory.kvm_memory_region); /* *vm_mem = VirtualAlloc(NULL, memory, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); */ *vm_mem = WkVirtualAlloc(kvm, &maparea); if (*vm_mem == NULL) { fprintf(stderr, "VirtualAlloc error\n"); return -1; } kvm->physical_memory = *vm_mem; winkvm_mapping_region_save_params(kvm, &maparea); create_vcpu.vm_fd = fd; create_vcpu.vcpu_fd = 0; vcpufd = -1; fprintf(stderr, "Create VCPU ... \n"); ret = DeviceIoControl( hnd, KVM_CREATE_VCPU, &create_vcpu, sizeof(create_vcpu), &vcpufd, sizeof(vcpufd), &retlen, NULL); if (vcpufd == -1) { fprintf(stderr, " kvm_create_vcpu: %m\n"); return -1; } fprintf(stderr, " vcpu fd : %d\n", vcpufd); fprintf(stderr, " Done\n"); kvm->vcpu_fd[0] = vcpufd; return 0; }