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

kvm: selftests: introduce new VM mode for 64K pages



Rename VM_MODE_FLAT48PG to be more descriptive of its config and add a
new config that has the same parameters, except with 64K pages.

Signed-off-by: default avatarAndrew Jones <drjones@redhat.com>
Signed-off-by: default avatarPaolo Bonzini <pbonzini@redhat.com>
parent 0bec140f
Loading
Loading
Loading
Loading
+6 −1
Original line number Diff line number Diff line
@@ -34,9 +34,14 @@ typedef uint64_t vm_vaddr_t; /* Virtual Machine (Guest) virtual address */
#define DEFAULT_STACK_PGS		5

enum vm_guest_mode {
	VM_MODE_FLAT48PG,
	VM_MODE_P52V48_4K,
	VM_MODE_P52V48_64K,
	NUM_VM_MODES,
};

#define vm_guest_mode_string(m) vm_guest_mode_string[m]
extern const char * const vm_guest_mode_string[];

enum vm_mem_backing_src_type {
	VM_MEM_SRC_ANONYMOUS,
	VM_MEM_SRC_ANONYMOUS_THP,
+6 −2
Original line number Diff line number Diff line
@@ -226,7 +226,7 @@ struct kvm_vm *vm_create_default(uint32_t vcpuid, uint64_t extra_mem_pages,
	uint64_t extra_pg_pages = (extra_mem_pages / ptrs_per_4k_pte) * 2;
	struct kvm_vm *vm;

	vm = vm_create(VM_MODE_FLAT48PG, DEFAULT_GUEST_PHY_PAGES + extra_pg_pages, O_RDWR);
	vm = vm_create(VM_MODE_P52V48_4K, DEFAULT_GUEST_PHY_PAGES + extra_pg_pages, O_RDWR);

	kvm_vm_elf_load(vm, program_invocation_name, 0, 0);
	vm_vcpu_add_default(vm, vcpuid, guest_code);
@@ -267,10 +267,14 @@ void vcpu_setup(struct kvm_vm *vm, int vcpuid, int pgd_memslot, int gdt_memslot)
	get_reg(vm, vcpuid, ARM64_SYS_REG(TCR_EL1), &tcr_el1);

	switch (vm->mode) {
	case VM_MODE_FLAT48PG:
	case VM_MODE_P52V48_4K:
		tcr_el1 |= 0ul << 14; /* TG0 = 4KB */
		tcr_el1 |= 6ul << 32; /* IPS = 52 bits */
		break;
	case VM_MODE_P52V48_64K:
		tcr_el1 |= 1ul << 14; /* TG0 = 64KB */
		tcr_el1 |= 6ul << 32; /* IPS = 52 bits */
		break;
	default:
		TEST_ASSERT(false, "Unknown guest mode, mode: 0x%x", vm->mode);
	}
+29 −17
Original line number Diff line number Diff line
@@ -17,7 +17,7 @@
#include <linux/kernel.h>

#define KVM_UTIL_PGS_PER_HUGEPG 512
#define KVM_UTIL_MIN_PADDR      0x2000
#define KVM_UTIL_MIN_PFN	2

/* Aligns x up to the next multiple of size. Size must be a power of 2. */
static void *align(void *x, size_t size)
@@ -96,11 +96,16 @@ static void vm_open(struct kvm_vm *vm, int perm)
		"rc: %i errno: %i", vm->fd, errno);
}

const char * const vm_guest_mode_string[] = {
	"PA-bits:52, VA-bits:48, 4K pages",
	"PA-bits:52, VA-bits:48, 64K pages",
};

/*
 * VM Create
 *
 * Input Args:
 *   mode - VM Mode (e.g. VM_MODE_FLAT48PG)
 *   mode - VM Mode (e.g. VM_MODE_P52V48_4K)
 *   phy_pages - Physical memory pages
 *   perm - permission
 *
@@ -109,7 +114,7 @@ static void vm_open(struct kvm_vm *vm, int perm)
 * Return:
 *   Pointer to opaque structure that describes the created VM.
 *
 * Creates a VM with the mode specified by mode (e.g. VM_MODE_FLAT48PG).
 * Creates a VM with the mode specified by mode (e.g. VM_MODE_P52V48_4K).
 * When phy_pages is non-zero, a memory region of phy_pages physical pages
 * is created and mapped starting at guest physical address 0.  The file
 * descriptor to control the created VM is created with the permissions
@@ -128,27 +133,33 @@ struct kvm_vm *vm_create(enum vm_guest_mode mode, uint64_t phy_pages, int perm)

	/* Setup mode specific traits. */
	switch (vm->mode) {
	case VM_MODE_FLAT48PG:
	case VM_MODE_P52V48_4K:
		vm->pgtable_levels = 4;
		vm->page_size = 0x1000;
		vm->page_shift = 12;
		vm->va_bits = 48;
		break;
	case VM_MODE_P52V48_64K:
		vm->pgtable_levels = 3;
		vm->pa_bits = 52;
		vm->page_size = 0x10000;
		vm->page_shift = 16;
		vm->va_bits = 48;
		break;
	default:
		TEST_ASSERT(false, "Unknown guest mode, mode: 0x%x", mode);
	}

		/* Limit to 48-bit canonical virtual addresses. */
	/* Limit to VA-bit canonical virtual addresses. */
	vm->vpages_valid = sparsebit_alloc();
	sparsebit_set_num(vm->vpages_valid,
			0, (1ULL << (48 - 1)) >> vm->page_shift);
		0, (1ULL << (vm->va_bits - 1)) >> vm->page_shift);
	sparsebit_set_num(vm->vpages_valid,
			(~((1ULL << (48 - 1)) - 1)) >> vm->page_shift,
			(1ULL << (48 - 1)) >> vm->page_shift);

		/* Limit physical addresses to 52-bits. */
		vm->max_gfn = ((1ULL << 52) >> vm->page_shift) - 1;
		break;
		(~((1ULL << (vm->va_bits - 1)) - 1)) >> vm->page_shift,
		(1ULL << (vm->va_bits - 1)) >> vm->page_shift);

	default:
		TEST_ASSERT(false, "Unknown guest mode, mode: 0x%x", mode);
	}
	/* Limit physical addresses to PA-bits. */
	vm->max_gfn = ((1ULL << vm->pa_bits) >> vm->page_shift) - 1;

	/* Allocate and setup memory for guest. */
	vm->vpages_mapped = sparsebit_alloc();
@@ -868,7 +879,8 @@ vm_vaddr_t vm_vaddr_alloc(struct kvm_vm *vm, size_t sz, vm_vaddr_t vaddr_min,
		pages--, vaddr += vm->page_size) {
		vm_paddr_t paddr;

		paddr = vm_phy_page_alloc(vm, KVM_UTIL_MIN_PADDR, data_memslot);
		paddr = vm_phy_page_alloc(vm,
				KVM_UTIL_MIN_PFN * vm->page_size, data_memslot);

		virt_pg_map(vm, vaddr, paddr, pgd_memslot);

+1 −0
Original line number Diff line number Diff line
@@ -49,6 +49,7 @@ struct kvm_vm {
	unsigned int pgtable_levels;
	unsigned int page_size;
	unsigned int page_shift;
	unsigned int pa_bits;
	unsigned int va_bits;
	uint64_t max_gfn;
	struct vcpu *vcpu_head;
+5 −5
Original line number Diff line number Diff line
@@ -231,7 +231,7 @@ void virt_pgd_alloc(struct kvm_vm *vm, uint32_t pgd_memslot)
{
	int rc;

	TEST_ASSERT(vm->mode == VM_MODE_FLAT48PG, "Attempt to use "
	TEST_ASSERT(vm->mode == VM_MODE_P52V48_4K, "Attempt to use "
		"unknown or unsupported guest mode, mode: 0x%x", vm->mode);

	/* If needed, create page map l4 table. */
@@ -264,7 +264,7 @@ void virt_pg_map(struct kvm_vm *vm, uint64_t vaddr, uint64_t paddr,
	uint16_t index[4];
	struct pageMapL4Entry *pml4e;

	TEST_ASSERT(vm->mode == VM_MODE_FLAT48PG, "Attempt to use "
	TEST_ASSERT(vm->mode == VM_MODE_P52V48_4K, "Attempt to use "
		"unknown or unsupported guest mode, mode: 0x%x", vm->mode);

	TEST_ASSERT((vaddr % vm->page_size) == 0,
@@ -551,7 +551,7 @@ vm_paddr_t addr_gva2gpa(struct kvm_vm *vm, vm_vaddr_t gva)
	struct pageTableEntry *pte;
	void *hva;

	TEST_ASSERT(vm->mode == VM_MODE_FLAT48PG, "Attempt to use "
	TEST_ASSERT(vm->mode == VM_MODE_P52V48_4K, "Attempt to use "
		"unknown or unsupported guest mode, mode: 0x%x", vm->mode);

	index[0] = (gva >> 12) & 0x1ffu;
@@ -624,7 +624,7 @@ void vcpu_setup(struct kvm_vm *vm, int vcpuid, int pgd_memslot, int gdt_memslot)
	kvm_setup_gdt(vm, &sregs.gdt, gdt_memslot, pgd_memslot);

	switch (vm->mode) {
	case VM_MODE_FLAT48PG:
	case VM_MODE_P52V48_4K:
		sregs.cr0 = X86_CR0_PE | X86_CR0_NE | X86_CR0_PG;
		sregs.cr4 |= X86_CR4_PAE | X86_CR4_OSFXSR;
		sregs.efer |= (EFER_LME | EFER_LMA | EFER_NX);
@@ -823,7 +823,7 @@ struct kvm_vm *vm_create_default(uint32_t vcpuid, uint64_t extra_mem_pages,
	uint64_t extra_pg_pages = extra_mem_pages / 512 * 2;

	/* Create VM */
	vm = vm_create(VM_MODE_FLAT48PG,
	vm = vm_create(VM_MODE_P52V48_4K,
		       DEFAULT_GUEST_PHY_PAGES + extra_pg_pages,
		       O_RDWR);