* [PATCH v2 0/3] 52-bit VA guest mode ID support
@ 2026-09-14 7:30 Itaru Kitayama
2026-09-14 7:30 ` [PATCH v2 1/3] KVM: arm64: selftests: Support five-level stage-1 page tables Itaru Kitayama
` (2 more replies)
0 siblings, 3 replies; 5+ messages in thread
From: Itaru Kitayama @ 2026-09-14 7:30 UTC (permalink / raw)
To: Marc Zyngier, Oliver Upton, Fuad Tabba, Joey Gouly, Steffen Eiden,
Suzuki K Poulose, Zenghui Yu, Paolo Bonzini, Shuah Khan,
Sean Christopherson
Cc: linux-arm-kernel, kvmarm, kvm, linux-kselftest, linux-kernel,
Itaru Kitayama, Takayuki Okamoto
This patch series extends the arm64 KVM selftest framework
to support 52-bit guest virtual address (VA) modes in addition to
the existing 52-bit physical address (PA) configurations.
The motivation is to enable validation of LPA2 guest memory-management
behaviour in configurations that use a 52-bit VA space.
While the selftest framework already supports testing 52-bit PA
configurations, it lacks the ability to exercise guests running with
52-bit virtual addresses, leaving part of the LPA2 functionality untested.
To address this, the series introduces new guest modes for 52-bit VA
operation, adds five-level page table support where required, and
performs runtime detection of host 52-bit VA capability so that
LPA2-enabled guest VA tests are executed only on supported systems.
Testing:
Built and ran lpa_test on QEMU with 52-bit VA support.
The test verified shared mappings at low and high guest virtual addresses,
then remapped the high VA to a different GPA and verified that
the mappings remained independent.
Signed-off-by: Itaru Kitayama <itaru.kitayama@fujitsu.com>
Reviewed-by: Takayuki Okamoto <tokamoto@fujitsu.com>
---
Changes in v2:
- Reorganize the series so that each patch builds independently.
- Move all P52V52 mode definitions and uses into the same patch.
- Use the standard "KVM: arm64: selftests:" subject prefix.
- Reuse one probe VM and vCPU for IPA and 64K VA capability detection.
- Make the VARange result explicitly specific to the 64K granule.
- Clarify that only the 4K P52V52 mode uses five page-table levels.
- Link to v1: https://patch.msgid.link/20260826-arm64-52bit-va-v1-0-14ec98211363@fujitsu.com
To: Marc Zyngier <maz@kernel.org>
To: Oliver Upton <oupton@kernel.org>
To: Fuad Tabba <fuad.tabba@linux.dev>
To: Joey Gouly <joey.gouly@arm.com>
To: Steffen Eiden <seiden@linux.ibm.com>
To: Suzuki K Poulose <suzuki.poulose@arm.com>
To: Zenghui Yu <yuzenghui@huawei.com>
To: Paolo Bonzini <pbonzini@redhat.com>
To: Sean Christopherson <seanjc@google.com>
To: Shuah Khan <shuah@kernel.org>
Cc: linux-arm-kernel@lists.infradead.org
Cc: kvmarm@lists.linux.dev
Cc: kvm@vger.kernel.org
Cc: linux-kselftest@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
---
Itaru Kitayama (3):
KVM: arm64: selftests: Support five-level stage-1 page tables
KVM: arm64: selftests: Add 52-bit VA guest modes
KVM: arm64: selftests: Test 52-bit guest virtual addresses
tools/testing/selftests/kvm/Makefile.kvm | 1 +
tools/testing/selftests/kvm/arm64/lpa_test.c | 124 +++++++++++++++++++++
.../selftests/kvm/include/arm64/processor.h | 3 +-
tools/testing/selftests/kvm/include/kvm_util.h | 3 +
tools/testing/selftests/kvm/lib/arm64/processor.c | 60 +++++++++-
tools/testing/selftests/kvm/lib/guest_modes.c | 7 +-
tools/testing/selftests/kvm/lib/kvm_util.c | 11 ++
7 files changed, 200 insertions(+), 9 deletions(-)
---
base-commit: 28924df2a08f440c73991b83028032c901de2ae4
change-id: 20260825-arm64-52bit-va-32f1f4cd050d
Best regards,
--
Itaru Kitayama <itaru.kitayama@fujitsu.com>
^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH v2 1/3] KVM: arm64: selftests: Support five-level stage-1 page tables
2026-09-14 7:30 [PATCH v2 0/3] 52-bit VA guest mode ID support Itaru Kitayama
@ 2026-09-14 7:30 ` Itaru Kitayama
2026-09-14 7:44 ` sashiko-bot
2026-09-14 7:30 ` [PATCH v2 2/3] KVM: arm64: selftests: Add 52-bit VA guest modes Itaru Kitayama
2026-09-14 7:30 ` [PATCH v2 3/3] KVM: arm64: selftests: Test 52-bit guest virtual addresses Itaru Kitayama
2 siblings, 1 reply; 5+ messages in thread
From: Itaru Kitayama @ 2026-09-14 7:30 UTC (permalink / raw)
To: Marc Zyngier, Oliver Upton, Fuad Tabba, Joey Gouly, Steffen Eiden,
Suzuki K Poulose, Zenghui Yu, Paolo Bonzini, Shuah Khan,
Sean Christopherson
Cc: linux-arm-kernel, kvmarm, kvm, linux-kselftest, linux-kernel,
Itaru Kitayama, Takayuki Okamoto
Add support for populating and walking five-level stage-1 page tables.
A five-level translation starts at architectural level -1, so extend
the page-table helpers and level validation accordingly.
This enables the page-table infrastructure required by 52-bit VA
configurations using the 4K translation granule.
Signed-off-by: Itaru Kitayama <itaru.kitayama@fujitsu.com>
Reviewed-by: Takayuki Okamoto <tokamoto@fujitsu.com>
---
.../selftests/kvm/include/arm64/processor.h | 1 +
tools/testing/selftests/kvm/lib/arm64/processor.c | 45 +++++++++++++++++++---
2 files changed, 41 insertions(+), 5 deletions(-)
diff --git a/tools/testing/selftests/kvm/include/arm64/processor.h b/tools/testing/selftests/kvm/include/arm64/processor.h
index b8a902ba8573..7457503df956 100644
--- a/tools/testing/selftests/kvm/include/arm64/processor.h
+++ b/tools/testing/selftests/kvm/include/arm64/processor.h
@@ -113,6 +113,7 @@
#define PTE_VALID BIT(0)
#define PGD_TYPE_TABLE BIT(1)
+#define P4D_TYPE_TABLE BIT(1)
#define PUD_TYPE_TABLE BIT(1)
#define PMD_TYPE_TABLE BIT(1)
#define PTE_TYPE_PAGE BIT(1)
diff --git a/tools/testing/selftests/kvm/lib/arm64/processor.c b/tools/testing/selftests/kvm/lib/arm64/processor.c
index 01325bf4d36f..b589368bf822 100644
--- a/tools/testing/selftests/kvm/lib/arm64/processor.c
+++ b/tools/testing/selftests/kvm/lib/arm64/processor.c
@@ -29,13 +29,25 @@ static u64 pgd_index(struct kvm_vm *vm, gva_t gva)
return (gva >> shift) & mask;
}
+static u64 p4d_index(struct kvm_vm *vm, gva_t gva)
+{
+ unsigned int shift = 3 * (vm->page_shift - 3) + vm->page_shift;
+ u64 mask = (1UL << (vm->page_shift - 3)) - 1;
+
+ TEST_ASSERT(vm->mmu.pgtable_levels == 5,
+ "Mode %d does not have 5 page table levels", vm->mode);
+
+ return (gva >> shift) & mask;
+}
+
static u64 pud_index(struct kvm_vm *vm, gva_t gva)
{
unsigned int shift = 2 * (vm->page_shift - 3) + vm->page_shift;
u64 mask = (1UL << (vm->page_shift - 3)) - 1;
- TEST_ASSERT(vm->mmu.pgtable_levels == 4,
- "Mode %d does not have 4 page table levels", vm->mode);
+ TEST_ASSERT(vm->mmu.pgtable_levels >= 4,
+ "Mode %d does not have >= 4 page table levels",
+ vm->mode);
return (gva >> shift) & mask;
}
@@ -147,6 +159,12 @@ static void _virt_pg_map(struct kvm_vm *vm, gva_t gva, gpa_t gpa,
PGD_TYPE_TABLE | PTE_VALID);
switch (vm->mmu.pgtable_levels) {
+ case 5:
+ ptep = addr_gpa2hva(vm, pte_addr(vm, *ptep)) + p4d_index(vm, gva) * 8;
+ if (!*ptep)
+ *ptep = addr_pte(vm, vm_alloc_page_table(vm),
+ P4D_TYPE_TABLE | PTE_VALID);
+ /* fall through */
case 4:
ptep = addr_gpa2hva(vm, pte_addr(vm, *ptep)) + pud_index(vm, gva) * 8;
if (!*ptep)
@@ -163,7 +181,7 @@ static void _virt_pg_map(struct kvm_vm *vm, gva_t gva, gpa_t gpa,
ptep = addr_gpa2hva(vm, pte_addr(vm, *ptep)) + pte_index(vm, gva) * 8;
break;
default:
- TEST_FAIL("Page table levels must be 2, 3, or 4");
+ TEST_FAIL("Page table levels must be 2, 3, 4, or 5");
}
pg_attr = PTE_AF | PTE_ATTRINDX(attr_idx) | PTE_TYPE_PAGE | PTE_VALID;
@@ -182,18 +200,35 @@ void virt_arch_pg_map(struct kvm_vm *vm, gva_t gva, gpa_t gpa)
u64 *virt_get_pte_hva_at_level(struct kvm_vm *vm, gva_t gva, int level)
{
+ int start_level = 4 - vm->mmu.pgtable_levels;
u64 *ptep;
+ TEST_ASSERT(level >= start_level && level <= 3,
+ "Invalid translation level %d, valid range is %d-3",
+ level, start_level);
+
if (!vm->mmu.pgd_created)
goto unmapped_gva;
ptep = addr_gpa2hva(vm, vm->mmu.pgd) + pgd_index(vm, gva) * 8;
if (!ptep)
goto unmapped_gva;
- if (level == 0)
+ /*
+ * Stage-1 translation starts at level -1 for a five-level page
+ * table, and at levels 0, 1, or 2 for four-, three-, or two-level
+ * page tables, respectively.
+ */
+ if (level == start_level)
return ptep;
switch (vm->mmu.pgtable_levels) {
+ case 5:
+ ptep = addr_gpa2hva(vm, pte_addr(vm, *ptep)) + p4d_index(vm, gva) * 8;
+ if (!ptep)
+ goto unmapped_gva;
+ if (level == 0)
+ break;
+ /* fall through */
case 4:
ptep = addr_gpa2hva(vm, pte_addr(vm, *ptep)) + pud_index(vm, gva) * 8;
if (!ptep)
@@ -214,7 +249,7 @@ u64 *virt_get_pte_hva_at_level(struct kvm_vm *vm, gva_t gva, int level)
goto unmapped_gva;
break;
default:
- TEST_FAIL("Page table levels must be 2, 3, or 4");
+ TEST_FAIL("Page table levels must be 2, 3, 4, or 5");
}
return ptep;
--
2.43.0
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH v2 2/3] KVM: arm64: selftests: Add 52-bit VA guest modes
2026-09-14 7:30 [PATCH v2 0/3] 52-bit VA guest mode ID support Itaru Kitayama
2026-09-14 7:30 ` [PATCH v2 1/3] KVM: arm64: selftests: Support five-level stage-1 page tables Itaru Kitayama
@ 2026-09-14 7:30 ` Itaru Kitayama
2026-09-14 7:30 ` [PATCH v2 3/3] KVM: arm64: selftests: Test 52-bit guest virtual addresses Itaru Kitayama
2 siblings, 0 replies; 5+ messages in thread
From: Itaru Kitayama @ 2026-09-14 7:30 UTC (permalink / raw)
To: Marc Zyngier, Oliver Upton, Fuad Tabba, Joey Gouly, Steffen Eiden,
Suzuki K Poulose, Zenghui Yu, Paolo Bonzini, Shuah Khan,
Sean Christopherson
Cc: linux-arm-kernel, kvmarm, kvm, linux-kselftest, linux-kernel,
Itaru Kitayama, Takayuki Okamoto
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 <itaru.kitayama@fujitsu.com>
Reviewed-by: Takayuki Okamoto <tokamoto@fujitsu.com>
---
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
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH v2 3/3] KVM: arm64: selftests: Test 52-bit guest virtual addresses
2026-09-14 7:30 [PATCH v2 0/3] 52-bit VA guest mode ID support Itaru Kitayama
2026-09-14 7:30 ` [PATCH v2 1/3] KVM: arm64: selftests: Support five-level stage-1 page tables Itaru Kitayama
2026-09-14 7:30 ` [PATCH v2 2/3] KVM: arm64: selftests: Add 52-bit VA guest modes Itaru Kitayama
@ 2026-09-14 7:30 ` Itaru Kitayama
2 siblings, 0 replies; 5+ messages in thread
From: Itaru Kitayama @ 2026-09-14 7:30 UTC (permalink / raw)
To: Marc Zyngier, Oliver Upton, Fuad Tabba, Joey Gouly, Steffen Eiden,
Suzuki K Poulose, Zenghui Yu, Paolo Bonzini, Shuah Khan,
Sean Christopherson
Cc: linux-arm-kernel, kvmarm, kvm, linux-kselftest, linux-kernel,
Itaru Kitayama, Takayuki Okamoto
Exercise reads and writes through low and high guest virtual addresses
in the 52-bit VA modes with 4K, 16K and 64K pages. Verify that mappings
to the same GPA share data and mappings to distinct GPAs remain
independent.
Signed-off-by: Itaru Kitayama <itaru.kitayama@fujitsu.com>
---
tools/testing/selftests/kvm/Makefile.kvm | 1 +
tools/testing/selftests/kvm/arm64/lpa_test.c | 124 +++++++++++++++++++++++++++
2 files changed, 125 insertions(+)
diff --git a/tools/testing/selftests/kvm/Makefile.kvm b/tools/testing/selftests/kvm/Makefile.kvm
index 96bab7002d39..1e9d059ffb24 100644
--- a/tools/testing/selftests/kvm/Makefile.kvm
+++ b/tools/testing/selftests/kvm/Makefile.kvm
@@ -179,6 +179,7 @@ TEST_GEN_PROGS_arm64 += arm64/hello_el2
TEST_GEN_PROGS_arm64 += arm64/host_sve
TEST_GEN_PROGS_arm64 += arm64/hypercalls
TEST_GEN_PROGS_arm64 += arm64/external_aborts
+TEST_GEN_PROGS_arm64 += arm64/lpa_test
TEST_GEN_PROGS_arm64 += arm64/mmio_sign_ext
TEST_GEN_PROGS_arm64 += arm64/page_fault_test
TEST_GEN_PROGS_arm64 += arm64/psci_test
diff --git a/tools/testing/selftests/kvm/arm64/lpa_test.c b/tools/testing/selftests/kvm/arm64/lpa_test.c
new file mode 100644
index 000000000000..8fe6f254db28
--- /dev/null
+++ b/tools/testing/selftests/kvm/arm64/lpa_test.c
@@ -0,0 +1,124 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Higher virtual addresses read/write test
+ */
+#include <test_util.h>
+
+#include "kvm_syscalls.h"
+#include "kvm_util.h"
+#include "ucall_common.h"
+#include "guest_modes.h"
+#include "processor.h"
+
+#define LOW_GVA 0xc0000000
+#define HIGH_GVA (LOW_GVA | BIT(48))
+
+static void guest_code(void)
+{
+ u64 *low = (u64 *)LOW_GVA;
+ u64 *high = (u64 *)HIGH_GVA;
+
+ WRITE_ONCE(*low, 1);
+ GUEST_ASSERT_EQ(READ_ONCE(*high), 1);
+ WRITE_ONCE(*high, 2);
+ GUEST_ASSERT_EQ(READ_ONCE(*low), 2);
+
+ GUEST_SYNC(0);
+
+ asm volatile("dsb sy\n\t"
+ "tlbi vmalle1is\n\t"
+ "dsb sy\n\t"
+ "isb"
+ : : : "memory");
+
+ GUEST_SYNC(1); /* Host installs HIGH_GVA -> gpa_b. */
+
+ asm volatile("dsb sy\n\t"
+ "isb\n\t"
+ : : : "memory");
+
+ /* low and high map to different GPAs. */
+ WRITE_ONCE(*low, 1);
+ WRITE_ONCE(*high, 2);
+
+ /* Check both after both writes to detect accidental aliasing. */
+ GUEST_ASSERT_EQ(READ_ONCE(*low), 1);
+ GUEST_ASSERT_EQ(READ_ONCE(*high), 2);
+
+ /* Updating the low mapping must not change the high mapping. */
+ WRITE_ONCE(*low, 3);
+
+ GUEST_ASSERT_EQ(READ_ONCE(*low), 3);
+ GUEST_ASSERT_EQ(READ_ONCE(*high), 2);
+
+ GUEST_DONE();
+}
+
+static void run_test(enum vm_guest_mode mode, void *arg)
+{
+ unsigned int *nr_tests = arg;
+ struct kvm_vcpu_init init;
+ struct kvm_vm *vm;
+ struct kvm_vcpu *vcpu;
+ struct ucall uc;
+
+ if (mode != VM_MODE_P52V52_4K &&
+ mode != VM_MODE_P52V52_16K &&
+ mode != VM_MODE_P52V52_64K)
+ return;
+
+ vm = __vm_create(VM_SHAPE(mode), 1, 0);
+ kvm_get_default_vcpu_target(vm, &init);
+ vcpu = aarch64_vcpu_add(vm, 0, &init, guest_code);
+ kvm_arch_vm_finalize_vcpus(vm);
+
+ vm_init_descriptor_tables(vm);
+ vcpu_init_descriptor_tables(vcpu);
+
+ u64 gpa_a = vm_phy_pages_alloc(vm, 1, 0, 0);
+ u64 gpa_b = vm_phy_pages_alloc(vm, 1, 0, 0);
+
+ virt_pg_map(vm, LOW_GVA, gpa_a);
+ virt_pg_map(vm, HIGH_GVA, gpa_a);
+
+ for (;;) {
+ vcpu_run(vcpu);
+ switch (get_ucall(vcpu, &uc)) {
+ case UCALL_DONE:
+ goto done;
+ case UCALL_ABORT:
+ REPORT_GUEST_ASSERT(uc);
+ break;
+ case UCALL_SYNC:
+ switch (uc.args[1]) {
+ case 0:
+ WRITE_ONCE(*virt_get_pte_hva(vm, HIGH_GVA), 0);
+ break;
+ case 1:
+ virt_pg_map(vm, HIGH_GVA, gpa_b);
+ break;
+ default:
+ TEST_FAIL("Unexpected sync stage: %lu\n", uc.args[1]);
+ }
+ /* Complete the host's PTE store before resuming the guest. */
+ asm volatile("dsb sy" : : : "memory");
+ break;
+ default:
+ TEST_FAIL("Unhandled ucall: %ld\n", uc.cmd);
+ }
+ }
+
+done:
+ kvm_vm_free(vm);
+ (*nr_tests)++;
+}
+
+int main(int argc, char **argv)
+{
+ unsigned int nr_tests = 0;
+
+ for_each_guest_mode(run_test, &nr_tests);
+ if (!nr_tests)
+ ksft_exit_skip("No supported 52-bit VA guest mode; skipping test\n");
+ return 0;
+}
--
2.43.0
^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [PATCH v2 1/3] KVM: arm64: selftests: Support five-level stage-1 page tables
2026-09-14 7:30 ` [PATCH v2 1/3] KVM: arm64: selftests: Support five-level stage-1 page tables Itaru Kitayama
@ 2026-09-14 7:44 ` sashiko-bot
0 siblings, 0 replies; 5+ messages in thread
From: sashiko-bot @ 2026-09-14 7:44 UTC (permalink / raw)
To: Itaru Kitayama; +Cc: kvmarm, Marc Zyngier, kvm, Oliver Upton
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Low] The `type` array in `pte_dump` is missing the entry for P4D, causing it to print an empty string for level 0.
--
commit ec0c73a180f67ed464cb14e88f74413194ff828e
Author: Itaru Kitayama <itaru.kitayama@fujitsu.com>
KVM: arm64: selftests: Support five-level stage-1 page tables
This commit adds support for five-level stage-1 page tables in the ARM64
KVM selftests. It extends the page-table helpers and level validation to
handle the new architectural level -1. This enables testing 52-bit VA
configurations with a 4K translation granule.
> diff --git a/tools/testing/selftests/kvm/lib/arm64/processor.c b/tools/testing/selftests/kvm/lib/arm64/processor.c
> index 01325bf4d36fc..b589368bf8222 100644
> --- a/tools/testing/selftests/kvm/lib/arm64/processor.c
> +++ b/tools/testing/selftests/kvm/lib/arm64/processor.c
[ ... ]
> @@ -214,7 +249,7 @@ u64 *virt_get_pte_hva_at_level(struct kvm_vm *vm, gva_t gva, int level)
> goto unmapped_gva;
> break;
> default:
> - TEST_FAIL("Page table levels must be 2, 3, or 4");
> + TEST_FAIL("Page table levels must be 2, 3, 4, or 5");
> }
>
> return ptep;
[Severity: Low]
Does this change miss updating the string names in pte_dump()?
Looking at pte_dump() in tools/testing/selftests/kvm/lib/arm64/processor.c,
the type array maps the translation level to its string name:
static const char * const type[] = { "", "pud", "pmd", "pte" };
When the test framework is compiled with DEBUG and dumps a 5-level page
table, virt_arch_dump() calculates the starting level for pte_dump() as 0.
Since the array was not updated to include "p4d", debug output for level 0
will print an empty string instead of "p4d".
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260914-arm64-52bit-va-v2-0-3911cb9d4ad4@fujitsu.com?part=1
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2026-09-14 7:44 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-09-14 7:30 [PATCH v2 0/3] 52-bit VA guest mode ID support Itaru Kitayama
2026-09-14 7:30 ` [PATCH v2 1/3] KVM: arm64: selftests: Support five-level stage-1 page tables Itaru Kitayama
2026-09-14 7:44 ` sashiko-bot
2026-09-14 7:30 ` [PATCH v2 2/3] KVM: arm64: selftests: Add 52-bit VA guest modes Itaru Kitayama
2026-09-14 7:30 ` [PATCH v2 3/3] KVM: arm64: selftests: Test 52-bit guest virtual addresses Itaru Kitayama
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).