Commit eabe7881 authored by Andrew Jones's avatar Andrew Jones Committed by Paolo Bonzini
Browse files

kvm: selftests: tidy up kvm_util



Tidy up kvm-util code: code/comment formatting, remove unused code,
and move x86 specific code out. We also move vcpu_dump() out of
common code, because not all arches (AArch64) have KVM_GET_REGS.

Signed-off-by: default avatarAndrew Jones <drjones@redhat.com>
Signed-off-by: default avatarPaolo Bonzini <pbonzini@redhat.com>
parent eea192bf
Loading
Loading
Loading
Loading
+26 −54
Original line number Diff line number Diff line
@@ -17,12 +17,6 @@

#include "sparsebit.h"

/*
 * Memslots can't cover the gfn starting at this gpa otherwise vCPUs can't be
 * created. Only applies to VMs using EPT.
 */
#define KVM_DEFAULT_IDENTITY_MAP_ADDRESS 0xfffbc000ul


/* Callers of kvm_util only have an incomplete/opaque description of the
 * structure kvm_util is using to maintain the state of a VM.
@@ -58,15 +52,15 @@ void kvm_vm_restart(struct kvm_vm *vmp, int perm);
void kvm_vm_release(struct kvm_vm *vmp);
void kvm_vm_get_dirty_log(struct kvm_vm *vm, int slot, void *log);

int kvm_memcmp_hva_gva(void *hva,
	struct kvm_vm *vm, const vm_vaddr_t gva, size_t len);
int kvm_memcmp_hva_gva(void *hva, struct kvm_vm *vm, const vm_vaddr_t gva,
		       size_t len);

void kvm_vm_elf_load(struct kvm_vm *vm, const char *filename,
		     uint32_t data_memslot, uint32_t pgd_memslot);

void vm_dump(FILE *stream, struct kvm_vm *vm, uint8_t indent);
void vcpu_dump(FILE *stream, struct kvm_vm *vm,
	uint32_t vcpuid, uint8_t indent);
void vcpu_dump(FILE *stream, struct kvm_vm *vm, uint32_t vcpuid,
	       uint8_t indent);

void vm_create_irqchip(struct kvm_vm *vm);

@@ -75,11 +69,12 @@ void vm_userspace_mem_region_add(struct kvm_vm *vm,
	uint64_t guest_paddr, uint32_t slot, uint64_t npages,
	uint32_t flags);

void vcpu_ioctl(struct kvm_vm *vm,
	uint32_t vcpuid, unsigned long ioctl, void *arg);
void vcpu_ioctl(struct kvm_vm *vm, uint32_t vcpuid, unsigned long ioctl,
		void *arg);
void vm_ioctl(struct kvm_vm *vm, unsigned long ioctl, void *arg);
void vm_mem_region_set_flags(struct kvm_vm *vm, uint32_t slot, uint32_t flags);
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);
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);
void virt_map(struct kvm_vm *vm, uint64_t vaddr, uint64_t paddr,
@@ -94,55 +89,32 @@ void vcpu_run(struct kvm_vm *vm, uint32_t vcpuid);
int _vcpu_run(struct kvm_vm *vm, uint32_t vcpuid);
void vcpu_set_mp_state(struct kvm_vm *vm, uint32_t vcpuid,
		       struct kvm_mp_state *mp_state);
void vcpu_regs_get(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);
void vcpu_regs_get(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);
void vcpu_args_set(struct kvm_vm *vm, uint32_t vcpuid, unsigned int num, ...);
void vcpu_sregs_get(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 _vcpu_sregs_set(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);
void 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);
void vcpu_events_get(struct kvm_vm *vm, uint32_t vcpuid,
		     struct kvm_vcpu_events *events);
void vcpu_events_set(struct kvm_vm *vm, uint32_t vcpuid,
		     struct kvm_vcpu_events *events);
uint64_t vcpu_get_msr(struct kvm_vm *vm, uint32_t vcpuid, uint64_t msr_index);
void vcpu_set_msr(struct kvm_vm *vm, uint32_t vcpuid, uint64_t msr_index,
	uint64_t msr_value);

const char *exit_reason_str(unsigned int exit_reason);

void virt_pgd_alloc(struct kvm_vm *vm, uint32_t pgd_memslot);
void virt_pg_map(struct kvm_vm *vm, uint64_t vaddr, uint64_t paddr,
		 uint32_t pgd_memslot);
vm_paddr_t vm_phy_page_alloc(struct kvm_vm *vm,
	vm_paddr_t paddr_min, uint32_t memslot);

struct kvm_cpuid2 *kvm_get_supported_cpuid(void);
void vcpu_set_cpuid(
	struct kvm_vm *vm, uint32_t vcpuid, struct kvm_cpuid2 *cpuid);

struct kvm_cpuid_entry2 *
kvm_get_supported_cpuid_index(uint32_t function, uint32_t index);

static inline struct kvm_cpuid_entry2 *
kvm_get_supported_cpuid_entry(uint32_t function)
{
	return kvm_get_supported_cpuid_index(function, 0);
}
vm_paddr_t vm_phy_page_alloc(struct kvm_vm *vm, vm_paddr_t paddr_min,
			     uint32_t memslot);

struct kvm_vm *vm_create_default(uint32_t vcpuid, uint64_t extra_mem_size,
				 void *guest_code);
void vm_vcpu_add_default(struct kvm_vm *vm, uint32_t vcpuid, void *guest_code);

typedef void (*vmx_guest_code_t)(vm_vaddr_t vmxon_vaddr,
				 vm_paddr_t vmxon_paddr,
				 vm_vaddr_t vmcs_vaddr,
				 vm_paddr_t vmcs_paddr);

struct kvm_userspace_memory_region *
kvm_userspace_memory_region_find(struct kvm_vm *vm, uint64_t start,
				 uint64_t end);
+19 −1
Original line number Diff line number Diff line
@@ -305,7 +305,25 @@ static inline unsigned long get_xmm(int n)

struct kvm_x86_state;
struct kvm_x86_state *vcpu_save_state(struct kvm_vm *vm, uint32_t vcpuid);
void vcpu_load_state(struct kvm_vm *vm, uint32_t vcpuid, struct kvm_x86_state *state);
void vcpu_load_state(struct kvm_vm *vm, uint32_t vcpuid,
		     struct kvm_x86_state *state);

struct kvm_cpuid2 *kvm_get_supported_cpuid(void);
void vcpu_set_cpuid(struct kvm_vm *vm, uint32_t vcpuid,
		    struct kvm_cpuid2 *cpuid);

struct kvm_cpuid_entry2 *
kvm_get_supported_cpuid_index(uint32_t function, uint32_t index);

static inline struct kvm_cpuid_entry2 *
kvm_get_supported_cpuid_entry(uint32_t function)
{
	return kvm_get_supported_cpuid_index(function, 0);
}

uint64_t vcpu_get_msr(struct kvm_vm *vm, uint32_t vcpuid, uint64_t msr_index);
void vcpu_set_msr(struct kvm_vm *vm, uint32_t vcpuid, uint64_t msr_index,
	  	  uint64_t msr_value);

/*
 * Basic CPU control in CR0
+106 −332
Original line number Diff line number Diff line
@@ -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 &region->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
@@ -910,7 +828,8 @@ static vm_vaddr_t vm_vaddr_unused_gap(struct kvm_vm *vm, size_t sz,
	return pgidx_start * vm->page_size;
}

/* VM Virtual Address Allocate
/*
 * VM Virtual Address Allocate
 *
 * Input Args:
 *   vm - Virtual Machine
@@ -937,7 +856,8 @@ vm_vaddr_t vm_vaddr_alloc(struct kvm_vm *vm, size_t sz, vm_vaddr_t vaddr_min,

	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
@@ -1133,7 +1058,8 @@ int _vcpu_run(struct kvm_vm *vm, uint32_t vcpuid)
	return rc;
}

/* VM VCPU Set MP State
/*
 * VM VCPU Set MP State
 *
 * Input Args:
 *   vm - Virtual Machine
@@ -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,15 +1128,13 @@ 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);
@@ -1224,7 +1148,6 @@ void vcpu_events_get(struct kvm_vm *vm, uint32_t vcpuid,

	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);
@@ -1238,129 +1161,13 @@ void vcpu_events_set(struct kvm_vm *vm, uint32_t vcpuid,

	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, &regs);

	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, &regs);
	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, &regs);
		regs_dump(stream, &regs, 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
+10 −12

File changed.

Preview size limit exceeded, changes collapsed.

+245 −0

File changed.

Preview size limit exceeded, changes collapsed.

Loading