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

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
...@@ -34,9 +34,14 @@ typedef uint64_t vm_vaddr_t; /* Virtual Machine (Guest) virtual address */ ...@@ -34,9 +34,14 @@ typedef uint64_t vm_vaddr_t; /* Virtual Machine (Guest) virtual address */
#define DEFAULT_STACK_PGS 5 #define DEFAULT_STACK_PGS 5
enum vm_guest_mode { 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 { enum vm_mem_backing_src_type {
VM_MEM_SRC_ANONYMOUS, VM_MEM_SRC_ANONYMOUS,
VM_MEM_SRC_ANONYMOUS_THP, VM_MEM_SRC_ANONYMOUS_THP,
......
...@@ -226,7 +226,7 @@ struct kvm_vm *vm_create_default(uint32_t vcpuid, uint64_t extra_mem_pages, ...@@ -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; uint64_t extra_pg_pages = (extra_mem_pages / ptrs_per_4k_pte) * 2;
struct kvm_vm *vm; 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); kvm_vm_elf_load(vm, program_invocation_name, 0, 0);
vm_vcpu_add_default(vm, vcpuid, guest_code); 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) ...@@ -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); get_reg(vm, vcpuid, ARM64_SYS_REG(TCR_EL1), &tcr_el1);
switch (vm->mode) { switch (vm->mode) {
case VM_MODE_FLAT48PG: case VM_MODE_P52V48_4K:
tcr_el1 |= 0ul << 14; /* TG0 = 4KB */ tcr_el1 |= 0ul << 14; /* TG0 = 4KB */
tcr_el1 |= 6ul << 32; /* IPS = 52 bits */ tcr_el1 |= 6ul << 32; /* IPS = 52 bits */
break; break;
case VM_MODE_P52V48_64K:
tcr_el1 |= 1ul << 14; /* TG0 = 64KB */
tcr_el1 |= 6ul << 32; /* IPS = 52 bits */
break;
default: default:
TEST_ASSERT(false, "Unknown guest mode, mode: 0x%x", vm->mode); TEST_ASSERT(false, "Unknown guest mode, mode: 0x%x", vm->mode);
} }
......
...@@ -17,7 +17,7 @@ ...@@ -17,7 +17,7 @@
#include <linux/kernel.h> #include <linux/kernel.h>
#define KVM_UTIL_PGS_PER_HUGEPG 512 #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. */ /* Aligns x up to the next multiple of size. Size must be a power of 2. */
static void *align(void *x, size_t size) static void *align(void *x, size_t size)
...@@ -96,11 +96,16 @@ static void vm_open(struct kvm_vm *vm, int perm) ...@@ -96,11 +96,16 @@ static void vm_open(struct kvm_vm *vm, int perm)
"rc: %i errno: %i", vm->fd, errno); "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 * VM Create
* *
* Input Args: * Input Args:
* mode - VM Mode (e.g. VM_MODE_FLAT48PG) * mode - VM Mode (e.g. VM_MODE_P52V48_4K)
* phy_pages - Physical memory pages * phy_pages - Physical memory pages
* perm - permission * perm - permission
* *
...@@ -109,7 +114,7 @@ static void vm_open(struct kvm_vm *vm, int perm) ...@@ -109,7 +114,7 @@ static void vm_open(struct kvm_vm *vm, int perm)
* Return: * Return:
* Pointer to opaque structure that describes the created VM. * 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 * 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 * is created and mapped starting at guest physical address 0. The file
* descriptor to control the created VM is created with the permissions * descriptor to control the created VM is created with the permissions
...@@ -128,28 +133,34 @@ struct kvm_vm *vm_create(enum vm_guest_mode mode, uint64_t phy_pages, int perm) ...@@ -128,28 +133,34 @@ struct kvm_vm *vm_create(enum vm_guest_mode mode, uint64_t phy_pages, int perm)
/* Setup mode specific traits. */ /* Setup mode specific traits. */
switch (vm->mode) { switch (vm->mode) {
case VM_MODE_FLAT48PG: case VM_MODE_P52V48_4K:
vm->pgtable_levels = 4; vm->pgtable_levels = 4;
vm->page_size = 0x1000; vm->page_size = 0x1000;
vm->page_shift = 12; vm->page_shift = 12;
vm->va_bits = 48; vm->va_bits = 48;
/* Limit to 48-bit canonical virtual addresses. */
vm->vpages_valid = sparsebit_alloc();
sparsebit_set_num(vm->vpages_valid,
0, (1ULL << (48 - 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; 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: default:
TEST_ASSERT(false, "Unknown guest mode, mode: 0x%x", mode); TEST_ASSERT(false, "Unknown guest mode, mode: 0x%x", mode);
} }
/* Limit to VA-bit canonical virtual addresses. */
vm->vpages_valid = sparsebit_alloc();
sparsebit_set_num(vm->vpages_valid,
0, (1ULL << (vm->va_bits - 1)) >> vm->page_shift);
sparsebit_set_num(vm->vpages_valid,
(~((1ULL << (vm->va_bits - 1)) - 1)) >> vm->page_shift,
(1ULL << (vm->va_bits - 1)) >> vm->page_shift);
/* Limit physical addresses to PA-bits. */
vm->max_gfn = ((1ULL << vm->pa_bits) >> vm->page_shift) - 1;
/* Allocate and setup memory for guest. */ /* Allocate and setup memory for guest. */
vm->vpages_mapped = sparsebit_alloc(); vm->vpages_mapped = sparsebit_alloc();
if (phy_pages != 0) if (phy_pages != 0)
...@@ -868,7 +879,8 @@ vm_vaddr_t vm_vaddr_alloc(struct kvm_vm *vm, size_t sz, vm_vaddr_t vaddr_min, ...@@ -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) { pages--, vaddr += vm->page_size) {
vm_paddr_t paddr; 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); virt_pg_map(vm, vaddr, paddr, pgd_memslot);
......
...@@ -49,6 +49,7 @@ struct kvm_vm { ...@@ -49,6 +49,7 @@ struct kvm_vm {
unsigned int pgtable_levels; unsigned int pgtable_levels;
unsigned int page_size; unsigned int page_size;
unsigned int page_shift; unsigned int page_shift;
unsigned int pa_bits;
unsigned int va_bits; unsigned int va_bits;
uint64_t max_gfn; uint64_t max_gfn;
struct vcpu *vcpu_head; struct vcpu *vcpu_head;
......
...@@ -231,7 +231,7 @@ void virt_pgd_alloc(struct kvm_vm *vm, uint32_t pgd_memslot) ...@@ -231,7 +231,7 @@ void virt_pgd_alloc(struct kvm_vm *vm, uint32_t pgd_memslot)
{ {
int rc; 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); "unknown or unsupported guest mode, mode: 0x%x", vm->mode);
/* If needed, create page map l4 table. */ /* 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, ...@@ -264,7 +264,7 @@ void virt_pg_map(struct kvm_vm *vm, uint64_t vaddr, uint64_t paddr,
uint16_t index[4]; uint16_t index[4];
struct pageMapL4Entry *pml4e; 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); "unknown or unsupported guest mode, mode: 0x%x", vm->mode);
TEST_ASSERT((vaddr % vm->page_size) == 0, TEST_ASSERT((vaddr % vm->page_size) == 0,
...@@ -551,7 +551,7 @@ vm_paddr_t addr_gva2gpa(struct kvm_vm *vm, vm_vaddr_t gva) ...@@ -551,7 +551,7 @@ vm_paddr_t addr_gva2gpa(struct kvm_vm *vm, vm_vaddr_t gva)
struct pageTableEntry *pte; struct pageTableEntry *pte;
void *hva; 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); "unknown or unsupported guest mode, mode: 0x%x", vm->mode);
index[0] = (gva >> 12) & 0x1ffu; index[0] = (gva >> 12) & 0x1ffu;
...@@ -624,7 +624,7 @@ void vcpu_setup(struct kvm_vm *vm, int vcpuid, int pgd_memslot, int gdt_memslot) ...@@ -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); kvm_setup_gdt(vm, &sregs.gdt, gdt_memslot, pgd_memslot);
switch (vm->mode) { switch (vm->mode) {
case VM_MODE_FLAT48PG: case VM_MODE_P52V48_4K:
sregs.cr0 = X86_CR0_PE | X86_CR0_NE | X86_CR0_PG; sregs.cr0 = X86_CR0_PE | X86_CR0_NE | X86_CR0_PG;
sregs.cr4 |= X86_CR4_PAE | X86_CR4_OSFXSR; sregs.cr4 |= X86_CR4_PAE | X86_CR4_OSFXSR;
sregs.efer |= (EFER_LME | EFER_LMA | EFER_NX); 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, ...@@ -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; uint64_t extra_pg_pages = extra_mem_pages / 512 * 2;
/* Create VM */ /* Create VM */
vm = vm_create(VM_MODE_FLAT48PG, vm = vm_create(VM_MODE_P52V48_4K,
DEFAULT_GUEST_PHY_PAGES + extra_pg_pages, DEFAULT_GUEST_PHY_PAGES + extra_pg_pages,
O_RDWR); O_RDWR);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment