kvm.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [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, &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).