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 <[email protected]>
Reviewed-by: Takayuki Okamoto <[email protected]>
---
 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, &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


Reply via email to