Commit 10a0cc3b authored by Ryan Roberts's avatar Ryan Roberts Committed by Marc Zyngier

KVM: selftests: arm64: Support P52V48 4K and 16K guest_modes

Add support for VM_MODE_P52V48_4K and VM_MODE_P52V48_16K guest modes by
using the FEAT_LPA2 pte format for stage1, when FEAT_LPA2 is available.
Reviewed-by: default avatarOliver Upton <oliver.upton@linux.dev>
Signed-off-by: default avatarRyan Roberts <ryan.roberts@arm.com>
Signed-off-by: default avatarMarc Zyngier <maz@kernel.org>
Link: https://lore.kernel.org/r/20231127111737.1897081-13-ryan.roberts@arm.com
parent 72324ac5
...@@ -171,6 +171,7 @@ static inline struct userspace_mem_region *vm_get_mem_region(struct kvm_vm *vm, ...@@ -171,6 +171,7 @@ static inline struct userspace_mem_region *vm_get_mem_region(struct kvm_vm *vm,
enum vm_guest_mode { enum vm_guest_mode {
VM_MODE_P52V48_4K, VM_MODE_P52V48_4K,
VM_MODE_P52V48_16K,
VM_MODE_P52V48_64K, VM_MODE_P52V48_64K,
VM_MODE_P48V48_4K, VM_MODE_P48V48_4K,
VM_MODE_P48V48_16K, VM_MODE_P48V48_16K,
......
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#include "kvm_util.h" #include "kvm_util.h"
#include "processor.h" #include "processor.h"
#include <linux/bitfield.h> #include <linux/bitfield.h>
#include <linux/sizes.h>
#define DEFAULT_ARM64_GUEST_STACK_VADDR_MIN 0xac0000 #define DEFAULT_ARM64_GUEST_STACK_VADDR_MIN 0xac0000
...@@ -58,13 +59,25 @@ static uint64_t pte_index(struct kvm_vm *vm, vm_vaddr_t gva) ...@@ -58,13 +59,25 @@ static uint64_t pte_index(struct kvm_vm *vm, vm_vaddr_t gva)
return (gva >> vm->page_shift) & mask; return (gva >> vm->page_shift) & mask;
} }
static inline bool use_lpa2_pte_format(struct kvm_vm *vm)
{
return (vm->page_size == SZ_4K || vm->page_size == SZ_16K) &&
(vm->pa_bits > 48 || vm->va_bits > 48);
}
static uint64_t addr_pte(struct kvm_vm *vm, uint64_t pa, uint64_t attrs) static uint64_t addr_pte(struct kvm_vm *vm, uint64_t pa, uint64_t attrs)
{ {
uint64_t pte; uint64_t pte;
pte = pa & GENMASK(47, vm->page_shift); if (use_lpa2_pte_format(vm)) {
if (vm->page_shift == 16) pte = pa & GENMASK(49, vm->page_shift);
pte |= FIELD_GET(GENMASK(51, 48), pa) << 12; pte |= FIELD_GET(GENMASK(51, 50), pa) << 8;
attrs &= ~GENMASK(9, 8);
} else {
pte = pa & GENMASK(47, vm->page_shift);
if (vm->page_shift == 16)
pte |= FIELD_GET(GENMASK(51, 48), pa) << 12;
}
pte |= attrs; pte |= attrs;
return pte; return pte;
...@@ -74,9 +87,14 @@ static uint64_t pte_addr(struct kvm_vm *vm, uint64_t pte) ...@@ -74,9 +87,14 @@ static uint64_t pte_addr(struct kvm_vm *vm, uint64_t pte)
{ {
uint64_t pa; uint64_t pa;
pa = pte & GENMASK(47, vm->page_shift); if (use_lpa2_pte_format(vm)) {
if (vm->page_shift == 16) pa = pte & GENMASK(49, vm->page_shift);
pa |= FIELD_GET(GENMASK(15, 12), pte) << 48; pa |= FIELD_GET(GENMASK(9, 8), pte) << 50;
} else {
pa = pte & GENMASK(47, vm->page_shift);
if (vm->page_shift == 16)
pa |= FIELD_GET(GENMASK(15, 12), pte) << 48;
}
return pa; return pa;
} }
...@@ -266,9 +284,6 @@ void aarch64_vcpu_setup(struct kvm_vcpu *vcpu, struct kvm_vcpu_init *init) ...@@ -266,9 +284,6 @@ void aarch64_vcpu_setup(struct kvm_vcpu *vcpu, struct kvm_vcpu_init *init)
/* Configure base granule size */ /* Configure base granule size */
switch (vm->mode) { switch (vm->mode) {
case VM_MODE_P52V48_4K:
TEST_FAIL("AArch64 does not support 4K sized pages "
"with 52-bit physical address ranges");
case VM_MODE_PXXV48_4K: case VM_MODE_PXXV48_4K:
TEST_FAIL("AArch64 does not support 4K sized pages " TEST_FAIL("AArch64 does not support 4K sized pages "
"with ANY-bit physical address ranges"); "with ANY-bit physical address ranges");
...@@ -278,12 +293,14 @@ void aarch64_vcpu_setup(struct kvm_vcpu *vcpu, struct kvm_vcpu_init *init) ...@@ -278,12 +293,14 @@ void aarch64_vcpu_setup(struct kvm_vcpu *vcpu, struct kvm_vcpu_init *init)
case VM_MODE_P36V48_64K: case VM_MODE_P36V48_64K:
tcr_el1 |= 1ul << 14; /* TG0 = 64KB */ tcr_el1 |= 1ul << 14; /* TG0 = 64KB */
break; break;
case VM_MODE_P52V48_16K:
case VM_MODE_P48V48_16K: case VM_MODE_P48V48_16K:
case VM_MODE_P40V48_16K: case VM_MODE_P40V48_16K:
case VM_MODE_P36V48_16K: case VM_MODE_P36V48_16K:
case VM_MODE_P36V47_16K: case VM_MODE_P36V47_16K:
tcr_el1 |= 2ul << 14; /* TG0 = 16KB */ tcr_el1 |= 2ul << 14; /* TG0 = 16KB */
break; break;
case VM_MODE_P52V48_4K:
case VM_MODE_P48V48_4K: case VM_MODE_P48V48_4K:
case VM_MODE_P40V48_4K: case VM_MODE_P40V48_4K:
case VM_MODE_P36V48_4K: case VM_MODE_P36V48_4K:
...@@ -297,6 +314,8 @@ void aarch64_vcpu_setup(struct kvm_vcpu *vcpu, struct kvm_vcpu_init *init) ...@@ -297,6 +314,8 @@ void aarch64_vcpu_setup(struct kvm_vcpu *vcpu, struct kvm_vcpu_init *init)
/* Configure output size */ /* Configure output size */
switch (vm->mode) { switch (vm->mode) {
case VM_MODE_P52V48_4K:
case VM_MODE_P52V48_16K:
case VM_MODE_P52V48_64K: case VM_MODE_P52V48_64K:
tcr_el1 |= 6ul << 32; /* IPS = 52 bits */ tcr_el1 |= 6ul << 32; /* IPS = 52 bits */
ttbr0_el1 |= FIELD_GET(GENMASK(51, 48), vm->pgd) << 2; ttbr0_el1 |= FIELD_GET(GENMASK(51, 48), vm->pgd) << 2;
...@@ -325,6 +344,8 @@ void aarch64_vcpu_setup(struct kvm_vcpu *vcpu, struct kvm_vcpu_init *init) ...@@ -325,6 +344,8 @@ void aarch64_vcpu_setup(struct kvm_vcpu *vcpu, struct kvm_vcpu_init *init)
/* TCR_EL1 |= IRGN0:WBWA | ORGN0:WBWA | SH0:Inner-Shareable */; /* TCR_EL1 |= IRGN0:WBWA | ORGN0:WBWA | SH0:Inner-Shareable */;
tcr_el1 |= (1 << 8) | (1 << 10) | (3 << 12); tcr_el1 |= (1 << 8) | (1 << 10) | (3 << 12);
tcr_el1 |= (64 - vm->va_bits) /* T0SZ */; tcr_el1 |= (64 - vm->va_bits) /* T0SZ */;
if (use_lpa2_pte_format(vm))
tcr_el1 |= (1ul << 59) /* DS */;
vcpu_set_reg(vcpu, KVM_ARM64_SYS_REG(SYS_SCTLR_EL1), sctlr_el1); vcpu_set_reg(vcpu, KVM_ARM64_SYS_REG(SYS_SCTLR_EL1), sctlr_el1);
vcpu_set_reg(vcpu, KVM_ARM64_SYS_REG(SYS_TCR_EL1), tcr_el1); vcpu_set_reg(vcpu, KVM_ARM64_SYS_REG(SYS_TCR_EL1), tcr_el1);
......
...@@ -23,6 +23,8 @@ void guest_modes_append_default(void) ...@@ -23,6 +23,8 @@ void guest_modes_append_default(void)
aarch64_get_supported_page_sizes(limit, &ipa4k, &ipa16k, &ipa64k); aarch64_get_supported_page_sizes(limit, &ipa4k, &ipa16k, &ipa64k);
guest_mode_append(VM_MODE_P52V48_4K, ipa4k >= 52);
guest_mode_append(VM_MODE_P52V48_16K, ipa16k >= 52);
guest_mode_append(VM_MODE_P52V48_64K, ipa64k >= 52); guest_mode_append(VM_MODE_P52V48_64K, ipa64k >= 52);
guest_mode_append(VM_MODE_P48V48_4K, ipa4k >= 48); guest_mode_append(VM_MODE_P48V48_4K, ipa4k >= 48);
......
...@@ -148,6 +148,7 @@ const char *vm_guest_mode_string(uint32_t i) ...@@ -148,6 +148,7 @@ const char *vm_guest_mode_string(uint32_t i)
{ {
static const char * const strings[] = { static const char * const strings[] = {
[VM_MODE_P52V48_4K] = "PA-bits:52, VA-bits:48, 4K pages", [VM_MODE_P52V48_4K] = "PA-bits:52, VA-bits:48, 4K pages",
[VM_MODE_P52V48_16K] = "PA-bits:52, VA-bits:48, 16K pages",
[VM_MODE_P52V48_64K] = "PA-bits:52, VA-bits:48, 64K pages", [VM_MODE_P52V48_64K] = "PA-bits:52, VA-bits:48, 64K pages",
[VM_MODE_P48V48_4K] = "PA-bits:48, VA-bits:48, 4K pages", [VM_MODE_P48V48_4K] = "PA-bits:48, VA-bits:48, 4K pages",
[VM_MODE_P48V48_16K] = "PA-bits:48, VA-bits:48, 16K pages", [VM_MODE_P48V48_16K] = "PA-bits:48, VA-bits:48, 16K pages",
...@@ -173,6 +174,7 @@ const char *vm_guest_mode_string(uint32_t i) ...@@ -173,6 +174,7 @@ const char *vm_guest_mode_string(uint32_t i)
const struct vm_guest_mode_params vm_guest_mode_params[] = { const struct vm_guest_mode_params vm_guest_mode_params[] = {
[VM_MODE_P52V48_4K] = { 52, 48, 0x1000, 12 }, [VM_MODE_P52V48_4K] = { 52, 48, 0x1000, 12 },
[VM_MODE_P52V48_16K] = { 52, 48, 0x4000, 14 },
[VM_MODE_P52V48_64K] = { 52, 48, 0x10000, 16 }, [VM_MODE_P52V48_64K] = { 52, 48, 0x10000, 16 },
[VM_MODE_P48V48_4K] = { 48, 48, 0x1000, 12 }, [VM_MODE_P48V48_4K] = { 48, 48, 0x1000, 12 },
[VM_MODE_P48V48_16K] = { 48, 48, 0x4000, 14 }, [VM_MODE_P48V48_16K] = { 48, 48, 0x4000, 14 },
...@@ -251,6 +253,7 @@ struct kvm_vm *____vm_create(enum vm_guest_mode mode) ...@@ -251,6 +253,7 @@ struct kvm_vm *____vm_create(enum vm_guest_mode mode)
case VM_MODE_P36V48_64K: case VM_MODE_P36V48_64K:
vm->pgtable_levels = 3; vm->pgtable_levels = 3;
break; break;
case VM_MODE_P52V48_16K:
case VM_MODE_P48V48_16K: case VM_MODE_P48V48_16K:
case VM_MODE_P40V48_16K: case VM_MODE_P40V48_16K:
case VM_MODE_P36V48_16K: case VM_MODE_P36V48_16K:
......
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