Add guest modes for 52-bit VA operation with the 4K, 16K, and 64K translation granules, using five, four, and three page-table levels, respectively. Extend the existing guest-mode capability probe to read ID_AA64MMFR2_EL1 from the same probe vCPU. Use VARange only when determining 52-bit VA support for the 64K granule. Signed-off-by: Itaru Kitayama Reviewed-by: Takayuki Okamoto --- tools/testing/selftests/kvm/include/arm64/processor.h | 2 +- tools/testing/selftests/kvm/include/kvm_util.h | 3 +++ tools/testing/selftests/kvm/lib/arm64/processor.c | 15 ++++++++++++++- tools/testing/selftests/kvm/lib/guest_modes.c | 7 +++++-- tools/testing/selftests/kvm/lib/kvm_util.c | 11 +++++++++++ 5 files changed, 34 insertions(+), 4 deletions(-) diff --git a/tools/testing/selftests/kvm/include/arm64/processor.h b/tools/testing/selftests/kvm/include/arm64/processor.h index 7457503df956..4ab00a7e6efb 100644 --- a/tools/testing/selftests/kvm/include/arm64/processor.h +++ b/tools/testing/selftests/kvm/include/arm64/processor.h @@ -169,7 +169,7 @@ enum { (v) == VECTOR_SYNC_LOWER_32) void aarch64_get_supported_page_sizes(u32 ipa, u32 *ipa4k, - u32 *ipa16k, u32 *ipa64k); + u32 *ipa16k, u32 *ipa64k, u32 *va64k); void vm_init_descriptor_tables(struct kvm_vm *vm); void vcpu_init_descriptor_tables(struct kvm_vcpu *vcpu); diff --git a/tools/testing/selftests/kvm/include/kvm_util.h b/tools/testing/selftests/kvm/include/kvm_util.h index 5a7a455b5387..1c268fa994aa 100644 --- a/tools/testing/selftests/kvm/include/kvm_util.h +++ b/tools/testing/selftests/kvm/include/kvm_util.h @@ -184,6 +184,9 @@ enum vm_guest_mode { VM_MODE_P52V48_4K, VM_MODE_P52V48_16K, VM_MODE_P52V48_64K, + VM_MODE_P52V52_4K, + VM_MODE_P52V52_16K, + VM_MODE_P52V52_64K, VM_MODE_P48V48_4K, VM_MODE_P48V48_16K, VM_MODE_P48V48_64K, diff --git a/tools/testing/selftests/kvm/lib/arm64/processor.c b/tools/testing/selftests/kvm/lib/arm64/processor.c index b589368bf822..9915f25f0287 100644 --- a/tools/testing/selftests/kvm/lib/arm64/processor.c +++ b/tools/testing/selftests/kvm/lib/arm64/processor.c @@ -356,12 +356,14 @@ void aarch64_vcpu_setup(struct kvm_vcpu *vcpu, struct kvm_vcpu_init *init) case VM_MODE_PXXVYY_4K: TEST_FAIL("AArch64 does not support 4K sized pages " "with ANY-bit physical address ranges"); + case VM_MODE_P52V52_64K: case VM_MODE_P52V48_64K: case VM_MODE_P48V48_64K: case VM_MODE_P40V48_64K: case VM_MODE_P36V48_64K: tcr_el1 |= TCR_TG0_64K; break; + case VM_MODE_P52V52_16K: case VM_MODE_P52V48_16K: case VM_MODE_P48V48_16K: case VM_MODE_P40V48_16K: @@ -369,6 +371,7 @@ void aarch64_vcpu_setup(struct kvm_vcpu *vcpu, struct kvm_vcpu_init *init) case VM_MODE_P36V47_16K: tcr_el1 |= TCR_TG0_16K; break; + case VM_MODE_P52V52_4K: case VM_MODE_P52V48_4K: case VM_MODE_P48V48_4K: case VM_MODE_P40V48_4K: @@ -383,6 +386,9 @@ void aarch64_vcpu_setup(struct kvm_vcpu *vcpu, struct kvm_vcpu_init *init) /* Configure output size */ switch (vm->mode) { + case VM_MODE_P52V52_4K: + case VM_MODE_P52V52_16K: + case VM_MODE_P52V52_64K: case VM_MODE_P52V48_4K: case VM_MODE_P52V48_16K: case VM_MODE_P52V48_64K: @@ -614,7 +620,7 @@ static u32 max_ipa_for_page_size(u32 vm_ipa, u32 gran, } void aarch64_get_supported_page_sizes(u32 ipa, u32 *ipa4k, - u32 *ipa16k, u32 *ipa64k) + u32 *ipa16k, u32 *ipa64k, u32 *va64k) { struct kvm_vcpu_init preferred_init; int kvm_fd, vm_fd, vcpu_fd, err; @@ -652,6 +658,13 @@ void aarch64_get_supported_page_sizes(u32 ipa, u32 *ipa4k, *ipa16k = max_ipa_for_page_size(ipa, gran, ID_AA64MMFR0_EL1_TGRAN16_NI, ID_AA64MMFR0_EL1_TGRAN16_52_BIT); + reg.id = KVM_ARM64_SYS_REG(SYS_ID_AA64MMFR2_EL1); + err = ioctl(vcpu_fd, KVM_GET_ONE_REG, ®); + TEST_ASSERT(err == 0, KVM_IOCTL_ERROR(KVM_GET_ONE_REG, err)); + + *va64k = FIELD_GET(ID_AA64MMFR2_EL1_VARange, val) >= + ID_AA64MMFR2_EL1_VARange_52 ? 52 : 48; + close(vcpu_fd); close(vm_fd); close(kvm_fd); diff --git a/tools/testing/selftests/kvm/lib/guest_modes.c b/tools/testing/selftests/kvm/lib/guest_modes.c index 7a96c43b5704..8d2748145f8f 100644 --- a/tools/testing/selftests/kvm/lib/guest_modes.c +++ b/tools/testing/selftests/kvm/lib/guest_modes.c @@ -20,11 +20,14 @@ void guest_modes_append_default(void) #ifdef __aarch64__ { unsigned int limit = kvm_check_cap(KVM_CAP_ARM_VM_IPA_SIZE); - u32 ipa4k, ipa16k, ipa64k; + u32 ipa4k, ipa16k, ipa64k, va64k; int i; - aarch64_get_supported_page_sizes(limit, &ipa4k, &ipa16k, &ipa64k); + aarch64_get_supported_page_sizes(limit, &ipa4k, &ipa16k, &ipa64k, &va64k); + guest_mode_append(VM_MODE_P52V52_4K, ipa4k >= 52); + guest_mode_append(VM_MODE_P52V52_16K, ipa16k >= 52); + guest_mode_append(VM_MODE_P52V52_64K, ipa64k >= 52 && va64k >= 52); 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); diff --git a/tools/testing/selftests/kvm/lib/kvm_util.c b/tools/testing/selftests/kvm/lib/kvm_util.c index 9ddc047d5c27..bc3ed034e203 100644 --- a/tools/testing/selftests/kvm/lib/kvm_util.c +++ b/tools/testing/selftests/kvm/lib/kvm_util.c @@ -203,6 +203,9 @@ const char *vm_guest_mode_string(u32 i) [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_P52V52_4K] = "PA-bits:52, VA-bits:52, 4K pages", + [VM_MODE_P52V52_16K] = "PA-bits:52, VA-bits:52, 16K pages", + [VM_MODE_P52V52_64K] = "PA-bits:52, VA-bits:52, 64K 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_64K] = "PA-bits:48, VA-bits:48, 64K pages", @@ -239,6 +242,9 @@ const struct vm_guest_mode_params vm_guest_mode_params[] = { [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_P52V52_4K] = { 52, 52, 0x1000, 12 }, + [VM_MODE_P52V52_16K] = { 52, 52, 0x4000, 14 }, + [VM_MODE_P52V52_64K] = { 52, 52, 0x10000, 16 }, [VM_MODE_P48V48_4K] = { 48, 48, 0x1000, 12 }, [VM_MODE_P48V48_16K] = { 48, 48, 0x4000, 14 }, [VM_MODE_P48V48_64K] = { 48, 48, 0x10000, 16 }, @@ -306,10 +312,14 @@ struct kvm_vm *____vm_create(struct vm_shape shape) /* Setup mode specific traits. */ switch (vm->mode) { + case VM_MODE_P52V52_4K: + vm->mmu.pgtable_levels = 5; + break; case VM_MODE_P52V48_4K: vm->mmu.pgtable_levels = 4; break; case VM_MODE_P52V48_64K: + case VM_MODE_P52V52_64K: vm->mmu.pgtable_levels = 3; break; case VM_MODE_P48V48_4K: @@ -330,6 +340,7 @@ struct kvm_vm *____vm_create(struct vm_shape shape) case VM_MODE_P48V48_16K: case VM_MODE_P40V48_16K: case VM_MODE_P36V48_16K: + case VM_MODE_P52V52_16K: vm->mmu.pgtable_levels = 4; break; case VM_MODE_P47V47_16K: -- 2.43.0