|
@@ -16,8 +16,6 @@
|
|
|
#include <sys/stat.h>
|
|
|
#include <linux/kernel.h>
|
|
|
|
|
|
-#define KVM_DEV_PATH "/dev/kvm"
|
|
|
-
|
|
|
#define KVM_UTIL_PGS_PER_HUGEPG 512
|
|
|
#define KVM_UTIL_MIN_PADDR 0x2000
|
|
|
|
|
@@ -30,7 +28,8 @@ static void *align(void *x, size_t size)
|
|
|
return (void *) (((size_t) x + mask) & ~mask);
|
|
|
}
|
|
|
|
|
|
-/* Capability
|
|
|
+/*
|
|
|
+ * Capability
|
|
|
*
|
|
|
* Input Args:
|
|
|
* cap - Capability
|
|
@@ -92,13 +91,13 @@ static void vm_open(struct kvm_vm *vm, int perm)
|
|
|
if (vm->kvm_fd < 0)
|
|
|
exit(KSFT_SKIP);
|
|
|
|
|
|
- /* Create VM. */
|
|
|
vm->fd = ioctl(vm->kvm_fd, KVM_CREATE_VM, NULL);
|
|
|
TEST_ASSERT(vm->fd >= 0, "KVM_CREATE_VM ioctl failed, "
|
|
|
"rc: %i errno: %i", vm->fd, errno);
|
|
|
}
|
|
|
|
|
|
-/* VM Create
|
|
|
+/*
|
|
|
+ * VM Create
|
|
|
*
|
|
|
* Input Args:
|
|
|
* mode - VM Mode (e.g. VM_MODE_FLAT48PG)
|
|
@@ -121,7 +120,6 @@ struct kvm_vm *vm_create(enum vm_guest_mode mode, uint64_t phy_pages, int perm)
|
|
|
struct kvm_vm *vm;
|
|
|
int kvm_fd;
|
|
|
|
|
|
- /* Allocate memory. */
|
|
|
vm = calloc(1, sizeof(*vm));
|
|
|
TEST_ASSERT(vm != NULL, "Insufficent Memory");
|
|
|
|
|
@@ -160,7 +158,8 @@ struct kvm_vm *vm_create(enum vm_guest_mode mode, uint64_t phy_pages, int perm)
|
|
|
return vm;
|
|
|
}
|
|
|
|
|
|
-/* VM Restart
|
|
|
+/*
|
|
|
+ * VM Restart
|
|
|
*
|
|
|
* Input Args:
|
|
|
* vm - VM that has been released before
|
|
@@ -187,7 +186,8 @@ void kvm_vm_restart(struct kvm_vm *vmp, int perm)
|
|
|
" rc: %i errno: %i\n"
|
|
|
" slot: %u flags: 0x%x\n"
|
|
|
" guest_phys_addr: 0x%lx size: 0x%lx",
|
|
|
- ret, errno, region->region.slot, region->region.flags,
|
|
|
+ ret, errno, region->region.slot,
|
|
|
+ region->region.flags,
|
|
|
region->region.guest_phys_addr,
|
|
|
region->region.memory_size);
|
|
|
}
|
|
@@ -203,7 +203,8 @@ void kvm_vm_get_dirty_log(struct kvm_vm *vm, int slot, void *log)
|
|
|
strerror(-ret));
|
|
|
}
|
|
|
|
|
|
-/* Userspace Memory Region Find
|
|
|
+/*
|
|
|
+ * Userspace Memory Region Find
|
|
|
*
|
|
|
* Input Args:
|
|
|
* vm - Virtual Machine
|
|
@@ -221,8 +222,8 @@ void kvm_vm_get_dirty_log(struct kvm_vm *vm, int slot, void *log)
|
|
|
* of the regions is returned. Null is returned only when no overlapping
|
|
|
* region exists.
|
|
|
*/
|
|
|
-static struct userspace_mem_region *userspace_mem_region_find(
|
|
|
- struct kvm_vm *vm, uint64_t start, uint64_t end)
|
|
|
+static struct userspace_mem_region *
|
|
|
+userspace_mem_region_find(struct kvm_vm *vm, uint64_t start, uint64_t end)
|
|
|
{
|
|
|
struct userspace_mem_region *region;
|
|
|
|
|
@@ -238,7 +239,8 @@ static struct userspace_mem_region *userspace_mem_region_find(
|
|
|
return NULL;
|
|
|
}
|
|
|
|
|
|
-/* KVM Userspace Memory Region Find
|
|
|
+/*
|
|
|
+ * KVM Userspace Memory Region Find
|
|
|
*
|
|
|
* Input Args:
|
|
|
* vm - Virtual Machine
|
|
@@ -266,7 +268,8 @@ kvm_userspace_memory_region_find(struct kvm_vm *vm, uint64_t start,
|
|
|
return ®ion->region;
|
|
|
}
|
|
|
|
|
|
-/* VCPU Find
|
|
|
+/*
|
|
|
+ * VCPU Find
|
|
|
*
|
|
|
* Input Args:
|
|
|
* vm - Virtual Machine
|
|
@@ -281,8 +284,7 @@ kvm_userspace_memory_region_find(struct kvm_vm *vm, uint64_t start,
|
|
|
* returns a pointer to it. Returns NULL if the VM doesn't contain a VCPU
|
|
|
* for the specified vcpuid.
|
|
|
*/
|
|
|
-struct vcpu *vcpu_find(struct kvm_vm *vm,
|
|
|
- uint32_t vcpuid)
|
|
|
+struct vcpu *vcpu_find(struct kvm_vm *vm, uint32_t vcpuid)
|
|
|
{
|
|
|
struct vcpu *vcpup;
|
|
|
|
|
@@ -294,7 +296,8 @@ struct vcpu *vcpu_find(struct kvm_vm *vm,
|
|
|
return NULL;
|
|
|
}
|
|
|
|
|
|
-/* VM VCPU Remove
|
|
|
+/*
|
|
|
+ * VM VCPU Remove
|
|
|
*
|
|
|
* Input Args:
|
|
|
* vm - Virtual Machine
|
|
@@ -331,11 +334,9 @@ void kvm_vm_release(struct kvm_vm *vmp)
|
|
|
{
|
|
|
int ret;
|
|
|
|
|
|
- /* Free VCPUs. */
|
|
|
while (vmp->vcpu_head)
|
|
|
vm_vcpu_rm(vmp, vmp->vcpu_head->id);
|
|
|
|
|
|
- /* Close file descriptor for the VM. */
|
|
|
ret = close(vmp->fd);
|
|
|
TEST_ASSERT(ret == 0, "Close of vm fd failed,\n"
|
|
|
" vmp->fd: %i rc: %i errno: %i", vmp->fd, ret, errno);
|
|
@@ -345,7 +346,8 @@ void kvm_vm_release(struct kvm_vm *vmp)
|
|
|
" vmp->kvm_fd: %i rc: %i errno: %i", vmp->kvm_fd, ret, errno);
|
|
|
}
|
|
|
|
|
|
-/* Destroys and frees the VM pointed to by vmp.
|
|
|
+/*
|
|
|
+ * Destroys and frees the VM pointed to by vmp.
|
|
|
*/
|
|
|
void kvm_vm_free(struct kvm_vm *vmp)
|
|
|
{
|
|
@@ -384,7 +386,8 @@ void kvm_vm_free(struct kvm_vm *vmp)
|
|
|
free(vmp);
|
|
|
}
|
|
|
|
|
|
-/* Memory Compare, host virtual to guest virtual
|
|
|
+/*
|
|
|
+ * Memory Compare, host virtual to guest virtual
|
|
|
*
|
|
|
* Input Args:
|
|
|
* hva - Starting host virtual address
|
|
@@ -406,23 +409,25 @@ void kvm_vm_free(struct kvm_vm *vmp)
|
|
|
* a length of len, to the guest bytes starting at the guest virtual
|
|
|
* address given by gva.
|
|
|
*/
|
|
|
-int kvm_memcmp_hva_gva(void *hva,
|
|
|
- struct kvm_vm *vm, vm_vaddr_t gva, size_t len)
|
|
|
+int kvm_memcmp_hva_gva(void *hva, struct kvm_vm *vm, vm_vaddr_t gva, size_t len)
|
|
|
{
|
|
|
size_t amt;
|
|
|
|
|
|
- /* Compare a batch of bytes until either a match is found
|
|
|
+ /*
|
|
|
+ * Compare a batch of bytes until either a match is found
|
|
|
* or all the bytes have been compared.
|
|
|
*/
|
|
|
for (uintptr_t offset = 0; offset < len; offset += amt) {
|
|
|
uintptr_t ptr1 = (uintptr_t)hva + offset;
|
|
|
|
|
|
- /* Determine host address for guest virtual address
|
|
|
+ /*
|
|
|
+ * Determine host address for guest virtual address
|
|
|
* at offset.
|
|
|
*/
|
|
|
uintptr_t ptr2 = (uintptr_t)addr_gva2hva(vm, gva + offset);
|
|
|
|
|
|
- /* Determine amount to compare on this pass.
|
|
|
+ /*
|
|
|
+ * Determine amount to compare on this pass.
|
|
|
* Don't allow the comparsion to cross a page boundary.
|
|
|
*/
|
|
|
amt = len - offset;
|
|
@@ -434,7 +439,8 @@ int kvm_memcmp_hva_gva(void *hva,
|
|
|
assert((ptr1 >> vm->page_shift) == ((ptr1 + amt - 1) >> vm->page_shift));
|
|
|
assert((ptr2 >> vm->page_shift) == ((ptr2 + amt - 1) >> vm->page_shift));
|
|
|
|
|
|
- /* Perform the comparison. If there is a difference
|
|
|
+ /*
|
|
|
+ * Perform the comparison. If there is a difference
|
|
|
* return that result to the caller, otherwise need
|
|
|
* to continue on looking for a mismatch.
|
|
|
*/
|
|
@@ -443,109 +449,15 @@ int kvm_memcmp_hva_gva(void *hva,
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
- /* No mismatch found. Let the caller know the two memory
|
|
|
+ /*
|
|
|
+ * No mismatch found. Let the caller know the two memory
|
|
|
* areas are equal.
|
|
|
*/
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
-/* Allocate an instance of struct kvm_cpuid2
|
|
|
- *
|
|
|
- * Input Args: None
|
|
|
- *
|
|
|
- * Output Args: None
|
|
|
- *
|
|
|
- * Return: A pointer to the allocated struct. The caller is responsible
|
|
|
- * for freeing this struct.
|
|
|
- *
|
|
|
- * Since kvm_cpuid2 uses a 0-length array to allow a the size of the
|
|
|
- * array to be decided at allocation time, allocation is slightly
|
|
|
- * complicated. This function uses a reasonable default length for
|
|
|
- * the array and performs the appropriate allocation.
|
|
|
- */
|
|
|
-static struct kvm_cpuid2 *allocate_kvm_cpuid2(void)
|
|
|
-{
|
|
|
- struct kvm_cpuid2 *cpuid;
|
|
|
- int nent = 100;
|
|
|
- size_t size;
|
|
|
-
|
|
|
- size = sizeof(*cpuid);
|
|
|
- size += nent * sizeof(struct kvm_cpuid_entry2);
|
|
|
- cpuid = malloc(size);
|
|
|
- if (!cpuid) {
|
|
|
- perror("malloc");
|
|
|
- abort();
|
|
|
- }
|
|
|
-
|
|
|
- cpuid->nent = nent;
|
|
|
-
|
|
|
- return cpuid;
|
|
|
-}
|
|
|
-
|
|
|
-/* KVM Supported CPUID Get
|
|
|
- *
|
|
|
- * Input Args: None
|
|
|
- *
|
|
|
- * Output Args:
|
|
|
- *
|
|
|
- * Return: The supported KVM CPUID
|
|
|
- *
|
|
|
- * Get the guest CPUID supported by KVM.
|
|
|
- */
|
|
|
-struct kvm_cpuid2 *kvm_get_supported_cpuid(void)
|
|
|
-{
|
|
|
- static struct kvm_cpuid2 *cpuid;
|
|
|
- int ret;
|
|
|
- int kvm_fd;
|
|
|
-
|
|
|
- if (cpuid)
|
|
|
- return cpuid;
|
|
|
-
|
|
|
- cpuid = allocate_kvm_cpuid2();
|
|
|
- kvm_fd = open(KVM_DEV_PATH, O_RDONLY);
|
|
|
- if (kvm_fd < 0)
|
|
|
- exit(KSFT_SKIP);
|
|
|
-
|
|
|
- ret = ioctl(kvm_fd, KVM_GET_SUPPORTED_CPUID, cpuid);
|
|
|
- TEST_ASSERT(ret == 0, "KVM_GET_SUPPORTED_CPUID failed %d %d\n",
|
|
|
- ret, errno);
|
|
|
-
|
|
|
- close(kvm_fd);
|
|
|
- return cpuid;
|
|
|
-}
|
|
|
-
|
|
|
-/* Locate a cpuid entry.
|
|
|
- *
|
|
|
- * Input Args:
|
|
|
- * cpuid: The cpuid.
|
|
|
- * function: The function of the cpuid entry to find.
|
|
|
- *
|
|
|
- * Output Args: None
|
|
|
- *
|
|
|
- * Return: A pointer to the cpuid entry. Never returns NULL.
|
|
|
- */
|
|
|
-struct kvm_cpuid_entry2 *
|
|
|
-kvm_get_supported_cpuid_index(uint32_t function, uint32_t index)
|
|
|
-{
|
|
|
- struct kvm_cpuid2 *cpuid;
|
|
|
- struct kvm_cpuid_entry2 *entry = NULL;
|
|
|
- int i;
|
|
|
-
|
|
|
- cpuid = kvm_get_supported_cpuid();
|
|
|
- for (i = 0; i < cpuid->nent; i++) {
|
|
|
- if (cpuid->entries[i].function == function &&
|
|
|
- cpuid->entries[i].index == index) {
|
|
|
- entry = &cpuid->entries[i];
|
|
|
- break;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- TEST_ASSERT(entry, "Guest CPUID entry not found: (EAX=%x, ECX=%x).",
|
|
|
- function, index);
|
|
|
- return entry;
|
|
|
-}
|
|
|
-
|
|
|
-/* VM Userspace Memory Region Add
|
|
|
+/*
|
|
|
+ * VM Userspace Memory Region Add
|
|
|
*
|
|
|
* Input Args:
|
|
|
* vm - Virtual Machine
|
|
@@ -587,7 +499,8 @@ void vm_userspace_mem_region_add(struct kvm_vm *vm,
|
|
|
" vm->max_gfn: 0x%lx vm->page_size: 0x%x",
|
|
|
guest_paddr, npages, vm->max_gfn, vm->page_size);
|
|
|
|
|
|
- /* Confirm a mem region with an overlapping address doesn't
|
|
|
+ /*
|
|
|
+ * Confirm a mem region with an overlapping address doesn't
|
|
|
* already exist.
|
|
|
*/
|
|
|
region = (struct userspace_mem_region *) userspace_mem_region_find(
|
|
@@ -678,7 +591,8 @@ void vm_userspace_mem_region_add(struct kvm_vm *vm,
|
|
|
vm->userspace_mem_region_head = region;
|
|
|
}
|
|
|
|
|
|
-/* Memslot to region
|
|
|
+/*
|
|
|
+ * Memslot to region
|
|
|
*
|
|
|
* Input Args:
|
|
|
* vm - Virtual Machine
|
|
@@ -692,8 +606,8 @@ void vm_userspace_mem_region_add(struct kvm_vm *vm,
|
|
|
* on error (e.g. currently no memory region using memslot as a KVM
|
|
|
* memory slot ID).
|
|
|
*/
|
|
|
-static struct userspace_mem_region *memslot2region(struct kvm_vm *vm,
|
|
|
- uint32_t memslot)
|
|
|
+static struct userspace_mem_region *
|
|
|
+memslot2region(struct kvm_vm *vm, uint32_t memslot)
|
|
|
{
|
|
|
struct userspace_mem_region *region;
|
|
|
|
|
@@ -713,7 +627,8 @@ static struct userspace_mem_region *memslot2region(struct kvm_vm *vm,
|
|
|
return region;
|
|
|
}
|
|
|
|
|
|
-/* VM Memory Region Flags Set
|
|
|
+/*
|
|
|
+ * VM Memory Region Flags Set
|
|
|
*
|
|
|
* Input Args:
|
|
|
* vm - Virtual Machine
|
|
@@ -731,7 +646,6 @@ void vm_mem_region_set_flags(struct kvm_vm *vm, uint32_t slot, uint32_t flags)
|
|
|
int ret;
|
|
|
struct userspace_mem_region *region;
|
|
|
|
|
|
- /* Locate memory region. */
|
|
|
region = memslot2region(vm, slot);
|
|
|
|
|
|
region->region.flags = flags;
|
|
@@ -743,7 +657,8 @@ void vm_mem_region_set_flags(struct kvm_vm *vm, uint32_t slot, uint32_t flags)
|
|
|
ret, errno, slot, flags);
|
|
|
}
|
|
|
|
|
|
-/* VCPU mmap Size
|
|
|
+/*
|
|
|
+ * VCPU mmap Size
|
|
|
*
|
|
|
* Input Args: None
|
|
|
*
|
|
@@ -773,7 +688,8 @@ static int vcpu_mmap_sz(void)
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
-/* VM VCPU Add
|
|
|
+/*
|
|
|
+ * VM VCPU Add
|
|
|
*
|
|
|
* Input Args:
|
|
|
* vm - Virtual Machine
|
|
@@ -786,7 +702,8 @@ static int vcpu_mmap_sz(void)
|
|
|
* Creates and adds to the VM specified by vm and virtual CPU with
|
|
|
* the ID given by vcpuid.
|
|
|
*/
|
|
|
-void vm_vcpu_add(struct kvm_vm *vm, uint32_t vcpuid, int pgd_memslot, int gdt_memslot)
|
|
|
+void vm_vcpu_add(struct kvm_vm *vm, uint32_t vcpuid, int pgd_memslot,
|
|
|
+ int gdt_memslot)
|
|
|
{
|
|
|
struct vcpu *vcpu;
|
|
|
|
|
@@ -824,7 +741,8 @@ void vm_vcpu_add(struct kvm_vm *vm, uint32_t vcpuid, int pgd_memslot, int gdt_me
|
|
|
vcpu_setup(vm, vcpuid, pgd_memslot, gdt_memslot);
|
|
|
}
|
|
|
|
|
|
-/* VM Virtual Address Unused Gap
|
|
|
+/*
|
|
|
+ * VM Virtual Address Unused Gap
|
|
|
*
|
|
|
* Input Args:
|
|
|
* vm - Virtual Machine
|
|
@@ -844,14 +762,14 @@ void vm_vcpu_add(struct kvm_vm *vm, uint32_t vcpuid, int pgd_memslot, int gdt_me
|
|
|
* sz unallocated bytes >= vaddr_min is available.
|
|
|
*/
|
|
|
static vm_vaddr_t vm_vaddr_unused_gap(struct kvm_vm *vm, size_t sz,
|
|
|
- vm_vaddr_t vaddr_min)
|
|
|
+ vm_vaddr_t vaddr_min)
|
|
|
{
|
|
|
uint64_t pages = (sz + vm->page_size - 1) >> vm->page_shift;
|
|
|
|
|
|
/* Determine lowest permitted virtual page index. */
|
|
|
uint64_t pgidx_start = (vaddr_min + vm->page_size - 1) >> vm->page_shift;
|
|
|
if ((pgidx_start * vm->page_size) < vaddr_min)
|
|
|
- goto no_va_found;
|
|
|
+ goto no_va_found;
|
|
|
|
|
|
/* Loop over section with enough valid virtual page indexes. */
|
|
|
if (!sparsebit_is_set_num(vm->vpages_valid,
|
|
@@ -910,7 +828,8 @@ va_found:
|
|
|
return pgidx_start * vm->page_size;
|
|
|
}
|
|
|
|
|
|
-/* VM Virtual Address Allocate
|
|
|
+/*
|
|
|
+ * VM Virtual Address Allocate
|
|
|
*
|
|
|
* Input Args:
|
|
|
* vm - Virtual Machine
|
|
@@ -931,13 +850,14 @@ va_found:
|
|
|
* a page.
|
|
|
*/
|
|
|
vm_vaddr_t vm_vaddr_alloc(struct kvm_vm *vm, size_t sz, vm_vaddr_t vaddr_min,
|
|
|
- uint32_t data_memslot, uint32_t pgd_memslot)
|
|
|
+ uint32_t data_memslot, uint32_t pgd_memslot)
|
|
|
{
|
|
|
uint64_t pages = (sz >> vm->page_shift) + ((sz % vm->page_size) != 0);
|
|
|
|
|
|
virt_pgd_alloc(vm, pgd_memslot);
|
|
|
|
|
|
- /* Find an unused range of virtual page addresses of at least
|
|
|
+ /*
|
|
|
+ * Find an unused range of virtual page addresses of at least
|
|
|
* pages in length.
|
|
|
*/
|
|
|
vm_vaddr_t vaddr_start = vm_vaddr_unused_gap(vm, sz, vaddr_min);
|
|
@@ -991,7 +911,8 @@ void virt_map(struct kvm_vm *vm, uint64_t vaddr, uint64_t paddr,
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-/* Address VM Physical to Host Virtual
|
|
|
+/*
|
|
|
+ * Address VM Physical to Host Virtual
|
|
|
*
|
|
|
* Input Args:
|
|
|
* vm - Virtual Machine
|
|
@@ -1023,7 +944,8 @@ void *addr_gpa2hva(struct kvm_vm *vm, vm_paddr_t gpa)
|
|
|
return NULL;
|
|
|
}
|
|
|
|
|
|
-/* Address Host Virtual to VM Physical
|
|
|
+/*
|
|
|
+ * Address Host Virtual to VM Physical
|
|
|
*
|
|
|
* Input Args:
|
|
|
* vm - Virtual Machine
|
|
@@ -1057,7 +979,8 @@ vm_paddr_t addr_hva2gpa(struct kvm_vm *vm, void *hva)
|
|
|
return -1;
|
|
|
}
|
|
|
|
|
|
-/* VM Create IRQ Chip
|
|
|
+/*
|
|
|
+ * VM Create IRQ Chip
|
|
|
*
|
|
|
* Input Args:
|
|
|
* vm - Virtual Machine
|
|
@@ -1079,7 +1002,8 @@ void vm_create_irqchip(struct kvm_vm *vm)
|
|
|
vm->has_irqchip = true;
|
|
|
}
|
|
|
|
|
|
-/* VM VCPU State
|
|
|
+/*
|
|
|
+ * VM VCPU State
|
|
|
*
|
|
|
* Input Args:
|
|
|
* vm - Virtual Machine
|
|
@@ -1101,7 +1025,8 @@ struct kvm_run *vcpu_state(struct kvm_vm *vm, uint32_t vcpuid)
|
|
|
return vcpu->state;
|
|
|
}
|
|
|
|
|
|
-/* VM VCPU Run
|
|
|
+/*
|
|
|
+ * VM VCPU Run
|
|
|
*
|
|
|
* Input Args:
|
|
|
* vm - Virtual Machine
|
|
@@ -1127,13 +1052,14 @@ int _vcpu_run(struct kvm_vm *vm, uint32_t vcpuid)
|
|
|
int rc;
|
|
|
|
|
|
TEST_ASSERT(vcpu != NULL, "vcpu not found, vcpuid: %u", vcpuid);
|
|
|
- do {
|
|
|
+ do {
|
|
|
rc = ioctl(vcpu->fd, KVM_RUN, NULL);
|
|
|
} while (rc == -1 && errno == EINTR);
|
|
|
return rc;
|
|
|
}
|
|
|
|
|
|
-/* VM VCPU Set MP State
|
|
|
+/*
|
|
|
+ * VM VCPU Set MP State
|
|
|
*
|
|
|
* Input Args:
|
|
|
* vm - Virtual Machine
|
|
@@ -1148,7 +1074,7 @@ int _vcpu_run(struct kvm_vm *vm, uint32_t vcpuid)
|
|
|
* by mp_state.
|
|
|
*/
|
|
|
void vcpu_set_mp_state(struct kvm_vm *vm, uint32_t vcpuid,
|
|
|
- struct kvm_mp_state *mp_state)
|
|
|
+ struct kvm_mp_state *mp_state)
|
|
|
{
|
|
|
struct vcpu *vcpu = vcpu_find(vm, vcpuid);
|
|
|
int ret;
|
|
@@ -1160,7 +1086,8 @@ void vcpu_set_mp_state(struct kvm_vm *vm, uint32_t vcpuid,
|
|
|
"rc: %i errno: %i", ret, errno);
|
|
|
}
|
|
|
|
|
|
-/* VM VCPU Regs Get
|
|
|
+/*
|
|
|
+ * VM VCPU Regs Get
|
|
|
*
|
|
|
* Input Args:
|
|
|
* vm - Virtual Machine
|
|
@@ -1174,21 +1101,20 @@ void vcpu_set_mp_state(struct kvm_vm *vm, uint32_t vcpuid,
|
|
|
* Obtains the current register state for the VCPU specified by vcpuid
|
|
|
* and stores it at the location given by regs.
|
|
|
*/
|
|
|
-void vcpu_regs_get(struct kvm_vm *vm,
|
|
|
- uint32_t vcpuid, struct kvm_regs *regs)
|
|
|
+void vcpu_regs_get(struct kvm_vm *vm, uint32_t vcpuid, struct kvm_regs *regs)
|
|
|
{
|
|
|
struct vcpu *vcpu = vcpu_find(vm, vcpuid);
|
|
|
int ret;
|
|
|
|
|
|
TEST_ASSERT(vcpu != NULL, "vcpu not found, vcpuid: %u", vcpuid);
|
|
|
|
|
|
- /* Get the regs. */
|
|
|
ret = ioctl(vcpu->fd, KVM_GET_REGS, regs);
|
|
|
TEST_ASSERT(ret == 0, "KVM_GET_REGS failed, rc: %i errno: %i",
|
|
|
ret, errno);
|
|
|
}
|
|
|
|
|
|
-/* VM VCPU Regs Set
|
|
|
+/*
|
|
|
+ * VM VCPU Regs Set
|
|
|
*
|
|
|
* Input Args:
|
|
|
* vm - Virtual Machine
|
|
@@ -1202,165 +1128,46 @@ void vcpu_regs_get(struct kvm_vm *vm,
|
|
|
* Sets the regs of the VCPU specified by vcpuid to the values
|
|
|
* given by regs.
|
|
|
*/
|
|
|
-void vcpu_regs_set(struct kvm_vm *vm,
|
|
|
- uint32_t vcpuid, struct kvm_regs *regs)
|
|
|
+void vcpu_regs_set(struct kvm_vm *vm, uint32_t vcpuid, struct kvm_regs *regs)
|
|
|
{
|
|
|
struct vcpu *vcpu = vcpu_find(vm, vcpuid);
|
|
|
int ret;
|
|
|
|
|
|
TEST_ASSERT(vcpu != NULL, "vcpu not found, vcpuid: %u", vcpuid);
|
|
|
|
|
|
- /* Set the regs. */
|
|
|
ret = ioctl(vcpu->fd, KVM_SET_REGS, regs);
|
|
|
TEST_ASSERT(ret == 0, "KVM_SET_REGS failed, rc: %i errno: %i",
|
|
|
ret, errno);
|
|
|
}
|
|
|
|
|
|
void vcpu_events_get(struct kvm_vm *vm, uint32_t vcpuid,
|
|
|
- struct kvm_vcpu_events *events)
|
|
|
+ struct kvm_vcpu_events *events)
|
|
|
{
|
|
|
struct vcpu *vcpu = vcpu_find(vm, vcpuid);
|
|
|
int ret;
|
|
|
|
|
|
TEST_ASSERT(vcpu != NULL, "vcpu not found, vcpuid: %u", vcpuid);
|
|
|
|
|
|
- /* Get the regs. */
|
|
|
ret = ioctl(vcpu->fd, KVM_GET_VCPU_EVENTS, events);
|
|
|
TEST_ASSERT(ret == 0, "KVM_GET_VCPU_EVENTS, failed, rc: %i errno: %i",
|
|
|
ret, errno);
|
|
|
}
|
|
|
|
|
|
void vcpu_events_set(struct kvm_vm *vm, uint32_t vcpuid,
|
|
|
- struct kvm_vcpu_events *events)
|
|
|
+ struct kvm_vcpu_events *events)
|
|
|
{
|
|
|
struct vcpu *vcpu = vcpu_find(vm, vcpuid);
|
|
|
int ret;
|
|
|
|
|
|
TEST_ASSERT(vcpu != NULL, "vcpu not found, vcpuid: %u", vcpuid);
|
|
|
|
|
|
- /* Set the regs. */
|
|
|
ret = ioctl(vcpu->fd, KVM_SET_VCPU_EVENTS, events);
|
|
|
TEST_ASSERT(ret == 0, "KVM_SET_VCPU_EVENTS, failed, rc: %i errno: %i",
|
|
|
ret, errno);
|
|
|
}
|
|
|
|
|
|
-/* VCPU Get MSR
|
|
|
- *
|
|
|
- * Input Args:
|
|
|
- * vm - Virtual Machine
|
|
|
- * vcpuid - VCPU ID
|
|
|
- * msr_index - Index of MSR
|
|
|
- *
|
|
|
- * Output Args: None
|
|
|
- *
|
|
|
- * Return: On success, value of the MSR. On failure a TEST_ASSERT is produced.
|
|
|
- *
|
|
|
- * Get value of MSR for VCPU.
|
|
|
- */
|
|
|
-uint64_t vcpu_get_msr(struct kvm_vm *vm, uint32_t vcpuid, uint64_t msr_index)
|
|
|
-{
|
|
|
- struct vcpu *vcpu = vcpu_find(vm, vcpuid);
|
|
|
- struct {
|
|
|
- struct kvm_msrs header;
|
|
|
- struct kvm_msr_entry entry;
|
|
|
- } buffer = {};
|
|
|
- int r;
|
|
|
-
|
|
|
- TEST_ASSERT(vcpu != NULL, "vcpu not found, vcpuid: %u", vcpuid);
|
|
|
- buffer.header.nmsrs = 1;
|
|
|
- buffer.entry.index = msr_index;
|
|
|
- r = ioctl(vcpu->fd, KVM_GET_MSRS, &buffer.header);
|
|
|
- TEST_ASSERT(r == 1, "KVM_GET_MSRS IOCTL failed,\n"
|
|
|
- " rc: %i errno: %i", r, errno);
|
|
|
-
|
|
|
- return buffer.entry.data;
|
|
|
-}
|
|
|
-
|
|
|
-/* VCPU Set MSR
|
|
|
- *
|
|
|
- * Input Args:
|
|
|
- * vm - Virtual Machine
|
|
|
- * vcpuid - VCPU ID
|
|
|
- * msr_index - Index of MSR
|
|
|
- * msr_value - New value of MSR
|
|
|
- *
|
|
|
- * Output Args: None
|
|
|
- *
|
|
|
- * Return: On success, nothing. On failure a TEST_ASSERT is produced.
|
|
|
- *
|
|
|
- * Set value of MSR for VCPU.
|
|
|
- */
|
|
|
-void vcpu_set_msr(struct kvm_vm *vm, uint32_t vcpuid, uint64_t msr_index,
|
|
|
- uint64_t msr_value)
|
|
|
-{
|
|
|
- struct vcpu *vcpu = vcpu_find(vm, vcpuid);
|
|
|
- struct {
|
|
|
- struct kvm_msrs header;
|
|
|
- struct kvm_msr_entry entry;
|
|
|
- } buffer = {};
|
|
|
- int r;
|
|
|
-
|
|
|
- TEST_ASSERT(vcpu != NULL, "vcpu not found, vcpuid: %u", vcpuid);
|
|
|
- memset(&buffer, 0, sizeof(buffer));
|
|
|
- buffer.header.nmsrs = 1;
|
|
|
- buffer.entry.index = msr_index;
|
|
|
- buffer.entry.data = msr_value;
|
|
|
- r = ioctl(vcpu->fd, KVM_SET_MSRS, &buffer.header);
|
|
|
- TEST_ASSERT(r == 1, "KVM_SET_MSRS IOCTL failed,\n"
|
|
|
- " rc: %i errno: %i", r, errno);
|
|
|
-}
|
|
|
-
|
|
|
-/* VM VCPU Args Set
|
|
|
- *
|
|
|
- * Input Args:
|
|
|
- * vm - Virtual Machine
|
|
|
- * vcpuid - VCPU ID
|
|
|
- * num - number of arguments
|
|
|
- * ... - arguments, each of type uint64_t
|
|
|
- *
|
|
|
- * Output Args: None
|
|
|
- *
|
|
|
- * Return: None
|
|
|
- *
|
|
|
- * Sets the first num function input arguments to the values
|
|
|
- * given as variable args. Each of the variable args is expected to
|
|
|
- * be of type uint64_t.
|
|
|
- */
|
|
|
-void vcpu_args_set(struct kvm_vm *vm, uint32_t vcpuid, unsigned int num, ...)
|
|
|
-{
|
|
|
- va_list ap;
|
|
|
- struct kvm_regs regs;
|
|
|
-
|
|
|
- TEST_ASSERT(num >= 1 && num <= 6, "Unsupported number of args,\n"
|
|
|
- " num: %u\n",
|
|
|
- num);
|
|
|
-
|
|
|
- va_start(ap, num);
|
|
|
- vcpu_regs_get(vm, vcpuid, ®s);
|
|
|
-
|
|
|
- if (num >= 1)
|
|
|
- regs.rdi = va_arg(ap, uint64_t);
|
|
|
-
|
|
|
- if (num >= 2)
|
|
|
- regs.rsi = va_arg(ap, uint64_t);
|
|
|
-
|
|
|
- if (num >= 3)
|
|
|
- regs.rdx = va_arg(ap, uint64_t);
|
|
|
-
|
|
|
- if (num >= 4)
|
|
|
- regs.rcx = va_arg(ap, uint64_t);
|
|
|
-
|
|
|
- if (num >= 5)
|
|
|
- regs.r8 = va_arg(ap, uint64_t);
|
|
|
-
|
|
|
- if (num >= 6)
|
|
|
- regs.r9 = va_arg(ap, uint64_t);
|
|
|
-
|
|
|
- vcpu_regs_set(vm, vcpuid, ®s);
|
|
|
- va_end(ap);
|
|
|
-}
|
|
|
-
|
|
|
-/* VM VCPU System Regs Get
|
|
|
+/*
|
|
|
+ * VM VCPU System Regs Get
|
|
|
*
|
|
|
* Input Args:
|
|
|
* vm - Virtual Machine
|
|
@@ -1374,22 +1181,20 @@ void vcpu_args_set(struct kvm_vm *vm, uint32_t vcpuid, unsigned int num, ...)
|
|
|
* Obtains the current system register state for the VCPU specified by
|
|
|
* vcpuid and stores it at the location given by sregs.
|
|
|
*/
|
|
|
-void vcpu_sregs_get(struct kvm_vm *vm,
|
|
|
- uint32_t vcpuid, struct kvm_sregs *sregs)
|
|
|
+void vcpu_sregs_get(struct kvm_vm *vm, uint32_t vcpuid, struct kvm_sregs *sregs)
|
|
|
{
|
|
|
struct vcpu *vcpu = vcpu_find(vm, vcpuid);
|
|
|
int ret;
|
|
|
|
|
|
TEST_ASSERT(vcpu != NULL, "vcpu not found, vcpuid: %u", vcpuid);
|
|
|
|
|
|
- /* Get the regs. */
|
|
|
- /* Get the regs. */
|
|
|
ret = ioctl(vcpu->fd, KVM_GET_SREGS, sregs);
|
|
|
TEST_ASSERT(ret == 0, "KVM_GET_SREGS failed, rc: %i errno: %i",
|
|
|
ret, errno);
|
|
|
}
|
|
|
|
|
|
-/* VM VCPU System Regs Set
|
|
|
+/*
|
|
|
+ * VM VCPU System Regs Set
|
|
|
*
|
|
|
* Input Args:
|
|
|
* vm - Virtual Machine
|
|
@@ -1403,27 +1208,25 @@ void vcpu_sregs_get(struct kvm_vm *vm,
|
|
|
* Sets the system regs of the VCPU specified by vcpuid to the values
|
|
|
* given by sregs.
|
|
|
*/
|
|
|
-void vcpu_sregs_set(struct kvm_vm *vm,
|
|
|
- uint32_t vcpuid, struct kvm_sregs *sregs)
|
|
|
+void vcpu_sregs_set(struct kvm_vm *vm, uint32_t vcpuid, struct kvm_sregs *sregs)
|
|
|
{
|
|
|
int ret = _vcpu_sregs_set(vm, vcpuid, sregs);
|
|
|
TEST_ASSERT(ret == 0, "KVM_RUN IOCTL failed, "
|
|
|
"rc: %i errno: %i", ret, errno);
|
|
|
}
|
|
|
|
|
|
-int _vcpu_sregs_set(struct kvm_vm *vm,
|
|
|
- uint32_t vcpuid, struct kvm_sregs *sregs)
|
|
|
+int _vcpu_sregs_set(struct kvm_vm *vm, uint32_t vcpuid, struct kvm_sregs *sregs)
|
|
|
{
|
|
|
struct vcpu *vcpu = vcpu_find(vm, vcpuid);
|
|
|
int ret;
|
|
|
|
|
|
TEST_ASSERT(vcpu != NULL, "vcpu not found, vcpuid: %u", vcpuid);
|
|
|
|
|
|
- /* Get the regs. */
|
|
|
return ioctl(vcpu->fd, KVM_SET_SREGS, sregs);
|
|
|
}
|
|
|
|
|
|
-/* VCPU Ioctl
|
|
|
+/*
|
|
|
+ * VCPU Ioctl
|
|
|
*
|
|
|
* Input Args:
|
|
|
* vm - Virtual Machine
|
|
@@ -1435,8 +1238,8 @@ int _vcpu_sregs_set(struct kvm_vm *vm,
|
|
|
*
|
|
|
* Issues an arbitrary ioctl on a VCPU fd.
|
|
|
*/
|
|
|
-void vcpu_ioctl(struct kvm_vm *vm,
|
|
|
- uint32_t vcpuid, unsigned long cmd, void *arg)
|
|
|
+void vcpu_ioctl(struct kvm_vm *vm, uint32_t vcpuid,
|
|
|
+ unsigned long cmd, void *arg)
|
|
|
{
|
|
|
struct vcpu *vcpu = vcpu_find(vm, vcpuid);
|
|
|
int ret;
|
|
@@ -1448,7 +1251,8 @@ void vcpu_ioctl(struct kvm_vm *vm,
|
|
|
cmd, ret, errno, strerror(errno));
|
|
|
}
|
|
|
|
|
|
-/* VM Ioctl
|
|
|
+/*
|
|
|
+ * VM Ioctl
|
|
|
*
|
|
|
* Input Args:
|
|
|
* vm - Virtual Machine
|
|
@@ -1468,7 +1272,8 @@ void vm_ioctl(struct kvm_vm *vm, unsigned long cmd, void *arg)
|
|
|
cmd, ret, errno, strerror(errno));
|
|
|
}
|
|
|
|
|
|
-/* VM Dump
|
|
|
+/*
|
|
|
+ * VM Dump
|
|
|
*
|
|
|
* Input Args:
|
|
|
* vm - Virtual Machine
|
|
@@ -1515,38 +1320,6 @@ void vm_dump(FILE *stream, struct kvm_vm *vm, uint8_t indent)
|
|
|
vcpu_dump(stream, vm, vcpu->id, indent + 2);
|
|
|
}
|
|
|
|
|
|
-/* VM VCPU Dump
|
|
|
- *
|
|
|
- * Input Args:
|
|
|
- * vm - Virtual Machine
|
|
|
- * vcpuid - VCPU ID
|
|
|
- * indent - Left margin indent amount
|
|
|
- *
|
|
|
- * Output Args:
|
|
|
- * stream - Output FILE stream
|
|
|
- *
|
|
|
- * Return: None
|
|
|
- *
|
|
|
- * Dumps the current state of the VCPU specified by vcpuid, within the VM
|
|
|
- * given by vm, to the FILE stream given by stream.
|
|
|
- */
|
|
|
-void vcpu_dump(FILE *stream, struct kvm_vm *vm,
|
|
|
- uint32_t vcpuid, uint8_t indent)
|
|
|
-{
|
|
|
- struct kvm_regs regs;
|
|
|
- struct kvm_sregs sregs;
|
|
|
-
|
|
|
- fprintf(stream, "%*scpuid: %u\n", indent, "", vcpuid);
|
|
|
-
|
|
|
- fprintf(stream, "%*sregs:\n", indent + 2, "");
|
|
|
- vcpu_regs_get(vm, vcpuid, ®s);
|
|
|
- regs_dump(stream, ®s, indent + 4);
|
|
|
-
|
|
|
- fprintf(stream, "%*ssregs:\n", indent + 2, "");
|
|
|
- vcpu_sregs_get(vm, vcpuid, &sregs);
|
|
|
- sregs_dump(stream, &sregs, indent + 4);
|
|
|
-}
|
|
|
-
|
|
|
/* Known KVM exit reasons */
|
|
|
static struct exit_reason {
|
|
|
unsigned int reason;
|
|
@@ -1577,7 +1350,8 @@ static struct exit_reason {
|
|
|
#endif
|
|
|
};
|
|
|
|
|
|
-/* Exit Reason String
|
|
|
+/*
|
|
|
+ * Exit Reason String
|
|
|
*
|
|
|
* Input Args:
|
|
|
* exit_reason - Exit reason
|
|
@@ -1603,7 +1377,8 @@ const char *exit_reason_str(unsigned int exit_reason)
|
|
|
return "Unknown";
|
|
|
}
|
|
|
|
|
|
-/* Physical Page Allocate
|
|
|
+/*
|
|
|
+ * Physical Page Allocate
|
|
|
*
|
|
|
* Input Args:
|
|
|
* vm - Virtual Machine
|
|
@@ -1620,8 +1395,8 @@ const char *exit_reason_str(unsigned int exit_reason)
|
|
|
* and its address is returned. A TEST_ASSERT failure occurs if no
|
|
|
* page is available at or above paddr_min.
|
|
|
*/
|
|
|
-vm_paddr_t vm_phy_page_alloc(struct kvm_vm *vm,
|
|
|
- vm_paddr_t paddr_min, uint32_t memslot)
|
|
|
+vm_paddr_t vm_phy_page_alloc(struct kvm_vm *vm, vm_paddr_t paddr_min,
|
|
|
+ uint32_t memslot)
|
|
|
{
|
|
|
struct userspace_mem_region *region;
|
|
|
sparsebit_idx_t pg;
|
|
@@ -1631,17 +1406,15 @@ vm_paddr_t vm_phy_page_alloc(struct kvm_vm *vm,
|
|
|
" paddr_min: 0x%lx page_size: 0x%x",
|
|
|
paddr_min, vm->page_size);
|
|
|
|
|
|
- /* Locate memory region. */
|
|
|
region = memslot2region(vm, memslot);
|
|
|
-
|
|
|
- /* Locate next available physical page at or above paddr_min. */
|
|
|
pg = paddr_min >> vm->page_shift;
|
|
|
|
|
|
+ /* Locate next available physical page at or above paddr_min. */
|
|
|
if (!sparsebit_is_set(region->unused_phy_pages, pg)) {
|
|
|
pg = sparsebit_next_set(region->unused_phy_pages, pg);
|
|
|
if (pg == 0) {
|
|
|
fprintf(stderr, "No guest physical page available, "
|
|
|
- "paddr_min: 0x%lx page_size: 0x%x memslot: %u",
|
|
|
+ "paddr_min: 0x%lx page_size: 0x%x memslot: %u\n",
|
|
|
paddr_min, vm->page_size, memslot);
|
|
|
fputs("---- vm dump ----\n", stderr);
|
|
|
vm_dump(stderr, vm, 2);
|
|
@@ -1655,7 +1428,8 @@ vm_paddr_t vm_phy_page_alloc(struct kvm_vm *vm,
|
|
|
return pg * vm->page_size;
|
|
|
}
|
|
|
|
|
|
-/* Address Guest Virtual to Host Virtual
|
|
|
+/*
|
|
|
+ * Address Guest Virtual to Host Virtual
|
|
|
*
|
|
|
* Input Args:
|
|
|
* vm - Virtual Machine
|