* [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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.