The Linux Kernel Mailing List
 help / color / mirror / Atom feed
* [PATCH v2 0/2] arm64: ptdump flush fixes
@ 2026-07-24 18:54 Wei-Lin Chang
  2026-07-24 18:54 ` [PATCH v2 1/2] arm64: ptdump: Make note_page_flush() range aware Wei-Lin Chang
  2026-07-24 18:54 ` [PATCH v2 2/2] KVM: arm64: ptdump: Flush the last region Wei-Lin Chang
  0 siblings, 2 replies; 5+ messages in thread
From: Wei-Lin Chang @ 2026-07-24 18:54 UTC (permalink / raw)
  To: linux-arm-kernel, kvmarm, linux-kernel
  Cc: Marc Zyngier, Oliver Upton, Fuad Tabba, Joey Gouly, Steffen Eiden,
	Suzuki K Poulose, Zenghui Yu, Catalin Marinas, Will Deacon,
	Anshuman Khandual, Ryan Roberts, Dev Jain,
	David Hildenbrand (Arm), Matt Fleming, Ard Biesheuvel,
	Mark Rutland, Sebastian Ene, Vincent Donnefort, Wei-Lin Chang

Hi,

This series fixes two problems around ptdumps:

1. note_page_flush(), which flushes out the last row of ptdumps, does
   not account for address spacees that have IA < 64. Other than making
   the last region extremely huge, the attributes of the last region
   within the address spaces appear to extend all the way to 1 << 64.

2. KVM/arm64's stage-2 ptdump missed calling note_page_flush().

Please see the patches for more detail.

* Changes from v1 [1]:

  - Instead of manually calling note_page() for flushing, fix
    note_page_flush() so that it ends the ptdump at the end of the
    address space.

  - Changed the start address of the second marker to ULONG_MAX for KVM
    ptdump, so we don't output extra marker names, and advance past the
    end of the marker array.

Thanks!

[1]: https://lore.kernel.org/kvmarm/20260717231233.2299068-1-weilin.chang@arm.com/

Wei-Lin Chang (2):
  arm64: ptdump: Make note_page_flush() range aware
  KVM: arm64: ptdump: Flush the last region

 arch/arm64/kvm/ptdump.c | 16 ++++++++++++----
 arch/arm64/mm/ptdump.c  | 17 ++++++++++++++++-
 2 files changed, 28 insertions(+), 5 deletions(-)


base-commit: 679d7201c1f09e37fa1c12ce28d84079c17fc87f
-- 
2.43.0


^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH v2 1/2] arm64: ptdump: Make note_page_flush() range aware
  2026-07-24 18:54 [PATCH v2 0/2] arm64: ptdump flush fixes Wei-Lin Chang
@ 2026-07-24 18:54 ` Wei-Lin Chang
  2026-07-24 18:54 ` [PATCH v2 2/2] KVM: arm64: ptdump: Flush the last region Wei-Lin Chang
  1 sibling, 0 replies; 5+ messages in thread
From: Wei-Lin Chang @ 2026-07-24 18:54 UTC (permalink / raw)
  To: linux-arm-kernel, kvmarm, linux-kernel
  Cc: Marc Zyngier, Oliver Upton, Fuad Tabba, Joey Gouly, Steffen Eiden,
	Suzuki K Poulose, Zenghui Yu, Catalin Marinas, Will Deacon,
	Anshuman Khandual, Ryan Roberts, Dev Jain,
	David Hildenbrand (Arm), Matt Fleming, Ard Biesheuvel,
	Mark Rutland, Sebastian Ene, Vincent Donnefort, Wei-Lin Chang

note_page_flush() calls note_page() with addr == 0 and level == -1 to
dump the last row of a ptdump. addr == 0 (1 << 64 wrapped around)
renders a huge region with enormous size for address spaces with
IA bits < 64. For example the stage-2 page tables and the EFI runtime
page table.

More importantly, the last region of the address space and everything
after the address space up to 1 << 64 are merged into one row of
output. If the last region within the address space is valid, it will
appear to remain valid up to 1 << 64 with the same attributes.

Currently only the EFI runtime ptdump is affected by this, but KVM will
soon fix its stage-2 ptdump by using note_page_flush(). Here is an
example of an EFI runtime ptdump (last row):

0x0000008000000000-0x0000000000000000   17179868672G PGD

With this patch:

0x0000008000000000-0x0001000000000000      261632G PGD

To fix this, use ptdump_state.range[] to figure out where the address
space ends, and call note_page() with that.

Fixes: 9d80448ac92b ("efi/arm64: Add debugfs node to dump UEFI runtime page tables")
Signed-off-by: Wei-Lin Chang <weilin.chang@arm.com>
---
 arch/arm64/mm/ptdump.c | 17 ++++++++++++++++-
 1 file changed, 16 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/mm/ptdump.c b/arch/arm64/mm/ptdump.c
index 1c20144700d7..5b34060ceb96 100644
--- a/arch/arm64/mm/ptdump.c
+++ b/arch/arm64/mm/ptdump.c
@@ -278,9 +278,24 @@ void note_page_pgd(struct ptdump_state *pt_st, unsigned long addr, pgd_t pgd)
 
 void note_page_flush(struct ptdump_state *pt_st)
 {
+	const struct ptdump_range *range = pt_st->range;
+	unsigned long end = 0;
 	pte_t pte_zero = {0};
 
-	note_page(pt_st, 0, -1, pte_val(pte_zero));
+	while (range->start != range->end) {
+		end = range->end;
+		range++;
+	}
+
+	/*
+	 * Address spaces that end at 1 << 64 have range->end == ULONG_MAX,
+	 * but note_page() expects the exclusive end. In this case adjust end
+	 * to the wraparound value 0.
+	 */
+	if (end == ULONG_MAX)
+		end = 0;
+
+	note_page(pt_st, end, -1, pte_val(pte_zero));
 }
 
 static void arm64_ptdump_walk_pgd(struct ptdump_state *st, struct mm_struct *mm)
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH v2 2/2] KVM: arm64: ptdump: Flush the last region
  2026-07-24 18:54 [PATCH v2 0/2] arm64: ptdump flush fixes Wei-Lin Chang
  2026-07-24 18:54 ` [PATCH v2 1/2] arm64: ptdump: Make note_page_flush() range aware Wei-Lin Chang
@ 2026-07-24 18:54 ` Wei-Lin Chang
  2026-07-25 17:16   ` Dev Jain
  1 sibling, 1 reply; 5+ messages in thread
From: Wei-Lin Chang @ 2026-07-24 18:54 UTC (permalink / raw)
  To: linux-arm-kernel, kvmarm, linux-kernel
  Cc: Marc Zyngier, Oliver Upton, Fuad Tabba, Joey Gouly, Steffen Eiden,
	Suzuki K Poulose, Zenghui Yu, Catalin Marinas, Will Deacon,
	Anshuman Khandual, Ryan Roberts, Dev Jain,
	David Hildenbrand (Arm), Matt Fleming, Ard Biesheuvel,
	Mark Rutland, Sebastian Ene, Vincent Donnefort, Wei-Lin Chang,
	Sashiko AI

Currently the stage-2 ptdump calls note_page() at each leaf entry visit.
This simply misses the output of the last region, because note_page()
only dumps output when it detects a change in level/prot, or when the
walk enters a next marker section. The last region in the guest IPA
space with the same level/prot is not dumped since there is no change
after it.

Call note_page_flush() to dump the final region. note_page_flush()
expects ptdump_state.range[] to be initialized to the range of the
address space, so also do that.

Also change the second marker's start address to ULONG_MAX so we never
cross it. This avoids dumping redundant marker names (which are NULL),
and advancing beyond the end of the marker array.

Fixes: 7c4f73548ed1 ("KVM: arm64: Register ptdump with debugfs on guest creation")
Reported-by: Sashiko AI <sashiko-bot@kernel.org>
Closes: https://lore.kernel.org/kvmarm/20260630122758.891011F00A3A@smtp.kernel.org/
Signed-off-by: Wei-Lin Chang <weilin.chang@arm.com>
---
 arch/arm64/kvm/ptdump.c | 16 ++++++++++++----
 1 file changed, 12 insertions(+), 4 deletions(-)

diff --git a/arch/arm64/kvm/ptdump.c b/arch/arm64/kvm/ptdump.c
index c9140e22abcf..222577163d2b 100644
--- a/arch/arm64/kvm/ptdump.c
+++ b/arch/arm64/kvm/ptdump.c
@@ -130,7 +130,7 @@ static struct kvm_ptdump_guest_state *kvm_ptdump_parser_create(struct kvm_s2_mmu
 	}
 
 	st->ipa_marker[0].name		= "Guest IPA";
-	st->ipa_marker[1].start_address = BIT(pgtable->ia_bits);
+	st->ipa_marker[1].start_address = ULONG_MAX;
 
 	st->mmu				= mmu;
 	return st;
@@ -148,18 +148,26 @@ static int kvm_ptdump_guest_show(struct seq_file *m, void *unused)
 		.flags	= KVM_PGTABLE_WALK_LEAF,
 	};
 
+	guard(write_lock)(&kvm->mmu_lock);
 	st->parser_state = (struct ptdump_pg_state) {
 		.marker		= &st->ipa_marker[0],
 		.level		= -1,
 		.pg_level	= &st->level[0],
 		.seq		= m,
+		.ptdump		= {
+			.range = (struct ptdump_range[]){
+				{0, BIT(mmu->pgt->ia_bits)},
+				{0, 0}
+			}
+		}
 	};
 
-	write_lock(&kvm->mmu_lock);
 	ret = kvm_pgtable_walk(mmu->pgt, 0, BIT(mmu->pgt->ia_bits), &walker);
-	write_unlock(&kvm->mmu_lock);
+	if (ret)
+		return ret;
+	note_page_flush(&st->parser_state.ptdump);
 
-	return ret;
+	return 0;
 }
 
 static int kvm_ptdump_guest_open(struct inode *m, struct file *file)
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [PATCH v2 2/2] KVM: arm64: ptdump: Flush the last region
  2026-07-24 18:54 ` [PATCH v2 2/2] KVM: arm64: ptdump: Flush the last region Wei-Lin Chang
@ 2026-07-25 17:16   ` Dev Jain
  2026-07-25 17:28     ` Marc Zyngier
  0 siblings, 1 reply; 5+ messages in thread
From: Dev Jain @ 2026-07-25 17:16 UTC (permalink / raw)
  To: Wei-Lin Chang, linux-arm-kernel, kvmarm, linux-kernel
  Cc: Marc Zyngier, Oliver Upton, Fuad Tabba, Joey Gouly, Steffen Eiden,
	Suzuki K Poulose, Zenghui Yu, Catalin Marinas, Will Deacon,
	Anshuman Khandual, Ryan Roberts, David Hildenbrand (Arm),
	Matt Fleming, Ard Biesheuvel, Mark Rutland, Sebastian Ene,
	Vincent Donnefort, Sashiko AI



On 25/07/26 12:24 am, Wei-Lin Chang wrote:
> Currently the stage-2 ptdump calls note_page() at each leaf entry visit.
> This simply misses the output of the last region, because note_page()
> only dumps output when it detects a change in level/prot, or when the
> walk enters a next marker section. The last region in the guest IPA
> space with the same level/prot is not dumped since there is no change
> after it.
> 
> Call note_page_flush() to dump the final region. note_page_flush()
> expects ptdump_state.range[] to be initialized to the range of the
> address space, so also do that.
> 
> Also change the second marker's start address to ULONG_MAX so we never
> cross it. This avoids dumping redundant marker names (which are NULL),
> and advancing beyond the end of the marker array.
> 
> Fixes: 7c4f73548ed1 ("KVM: arm64: Register ptdump with debugfs on guest creation")
> Reported-by: Sashiko AI <sashiko-bot@kernel.org>
> Closes: https://lore.kernel.org/kvmarm/20260630122758.891011F00A3A@smtp.kernel.org/
> Signed-off-by: Wei-Lin Chang <weilin.chang@arm.com>
> ---
>  arch/arm64/kvm/ptdump.c | 16 ++++++++++++----
>  1 file changed, 12 insertions(+), 4 deletions(-)
> 
> diff --git a/arch/arm64/kvm/ptdump.c b/arch/arm64/kvm/ptdump.c
> index c9140e22abcf..222577163d2b 100644
> --- a/arch/arm64/kvm/ptdump.c
> +++ b/arch/arm64/kvm/ptdump.c
> @@ -130,7 +130,7 @@ static struct kvm_ptdump_guest_state *kvm_ptdump_parser_create(struct kvm_s2_mmu
>  	}
>  
>  	st->ipa_marker[0].name		= "Guest IPA";
> -	st->ipa_marker[1].start_address = BIT(pgtable->ia_bits);
> +	st->ipa_marker[1].start_address = ULONG_MAX;
>  
>  	st->mmu				= mmu;
>  	return st;
> @@ -148,18 +148,26 @@ static int kvm_ptdump_guest_show(struct seq_file *m, void *unused)
>  		.flags	= KVM_PGTABLE_WALK_LEAF,
>  	};
>  
> +	guard(write_lock)(&kvm->mmu_lock);
>  	st->parser_state = (struct ptdump_pg_state) {
>  		.marker		= &st->ipa_marker[0],
>  		.level		= -1,
>  		.pg_level	= &st->level[0],
>  		.seq		= m,
> +		.ptdump		= {
> +			.range = (struct ptdump_range[]){
> +				{0, BIT(mmu->pgt->ia_bits)},
> +				{0, 0}
> +			}

I am having a real hard time reading that indentation :) you
could make it look like what we have currently in ptdump_walk().

The code looks sensible to me. I have also tested by booting a
Linux VM inside a Linux VM on a Mac, and I see the stage2 ptdump
prints the last range upto the ia_bits correctly. So with the
nit addressed above:

Reviewed-by: Dev Jain <dev.jain@arm.com>
Tested-by: Dev Jain <dev.jain@arm.com>




> +		}
>  	};
>  
> -	write_lock(&kvm->mmu_lock);
>  	ret = kvm_pgtable_walk(mmu->pgt, 0, BIT(mmu->pgt->ia_bits), &walker);
> -	write_unlock(&kvm->mmu_lock);
> +	if (ret)
> +		return ret;
> +	note_page_flush(&st->parser_state.ptdump);
>  
> -	return ret;
> +	return 0;
>  }
>  
>  static int kvm_ptdump_guest_open(struct inode *m, struct file *file)


^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH v2 2/2] KVM: arm64: ptdump: Flush the last region
  2026-07-25 17:16   ` Dev Jain
@ 2026-07-25 17:28     ` Marc Zyngier
  0 siblings, 0 replies; 5+ messages in thread
From: Marc Zyngier @ 2026-07-25 17:28 UTC (permalink / raw)
  To: Dev Jain
  Cc: Wei-Lin Chang, linux-arm-kernel, kvmarm, linux-kernel,
	Oliver Upton, Fuad Tabba, Joey Gouly, Steffen Eiden,
	Suzuki K Poulose, Zenghui Yu, Catalin Marinas, Will Deacon,
	Anshuman Khandual, Ryan Roberts, David Hildenbrand (Arm),
	Matt Fleming, Ard Biesheuvel, Mark Rutland, Sebastian Ene,
	Vincent Donnefort, Sashiko AI

On Sat, 25 Jul 2026 18:16:37 +0100,
Dev Jain <dev.jain@arm.com> wrote:
> 
> 
> 
> On 25/07/26 12:24 am, Wei-Lin Chang wrote:
> > Currently the stage-2 ptdump calls note_page() at each leaf entry visit.
> > This simply misses the output of the last region, because note_page()
> > only dumps output when it detects a change in level/prot, or when the
> > walk enters a next marker section. The last region in the guest IPA
> > space with the same level/prot is not dumped since there is no change
> > after it.
> > 
> > Call note_page_flush() to dump the final region. note_page_flush()
> > expects ptdump_state.range[] to be initialized to the range of the
> > address space, so also do that.
> > 
> > Also change the second marker's start address to ULONG_MAX so we never
> > cross it. This avoids dumping redundant marker names (which are NULL),
> > and advancing beyond the end of the marker array.
> > 
> > Fixes: 7c4f73548ed1 ("KVM: arm64: Register ptdump with debugfs on guest creation")
> > Reported-by: Sashiko AI <sashiko-bot@kernel.org>
> > Closes: https://lore.kernel.org/kvmarm/20260630122758.891011F00A3A@smtp.kernel.org/
> > Signed-off-by: Wei-Lin Chang <weilin.chang@arm.com>
> > ---
> >  arch/arm64/kvm/ptdump.c | 16 ++++++++++++----
> >  1 file changed, 12 insertions(+), 4 deletions(-)
> > 
> > diff --git a/arch/arm64/kvm/ptdump.c b/arch/arm64/kvm/ptdump.c
> > index c9140e22abcf..222577163d2b 100644
> > --- a/arch/arm64/kvm/ptdump.c
> > +++ b/arch/arm64/kvm/ptdump.c
> > @@ -130,7 +130,7 @@ static struct kvm_ptdump_guest_state *kvm_ptdump_parser_create(struct kvm_s2_mmu
> >  	}
> >  
> >  	st->ipa_marker[0].name		= "Guest IPA";
> > -	st->ipa_marker[1].start_address = BIT(pgtable->ia_bits);
> > +	st->ipa_marker[1].start_address = ULONG_MAX;
> >  
> >  	st->mmu				= mmu;
> >  	return st;
> > @@ -148,18 +148,26 @@ static int kvm_ptdump_guest_show(struct seq_file *m, void *unused)
> >  		.flags	= KVM_PGTABLE_WALK_LEAF,
> >  	};
> >  
> > +	guard(write_lock)(&kvm->mmu_lock);
> >  	st->parser_state = (struct ptdump_pg_state) {
> >  		.marker		= &st->ipa_marker[0],
> >  		.level		= -1,
> >  		.pg_level	= &st->level[0],
> >  		.seq		= m,
> > +		.ptdump		= {
> > +			.range = (struct ptdump_range[]){
> > +				{0, BIT(mmu->pgt->ia_bits)},
> > +				{0, 0}
> > +			}
> 
> I am having a real hard time reading that indentation :) you
> could make it look like what we have currently in ptdump_walk().

This patch:

		.ptdump		= {
			.range = (struct ptdump_range[]){
				{0, BIT(mmu->pgt->ia_bits)},
				{0, 0}
			}
		}

ptdump_walk():

		.ptdump = {
			[...]
			.range = (struct ptdump_range[]){
				{info->base_addr, end},
				{0, 0}
			}
		}

Zero difference in indentation. Consider using a better email client,
or look at the applied patches.

	M.

-- 
Jazz isn't dead. It just smells funny.

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2026-07-25 17:27 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-24 18:54 [PATCH v2 0/2] arm64: ptdump flush fixes Wei-Lin Chang
2026-07-24 18:54 ` [PATCH v2 1/2] arm64: ptdump: Make note_page_flush() range aware Wei-Lin Chang
2026-07-24 18:54 ` [PATCH v2 2/2] KVM: arm64: ptdump: Flush the last region Wei-Lin Chang
2026-07-25 17:16   ` Dev Jain
2026-07-25 17:28     ` Marc Zyngier

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox