Printing the descriptor attributes requires accessing a mask which has a
different set of attributes for stage-2. In preparation for adding support
for the stage-2 pagetables dumping, use the mask from the local context
and not from the globally defined pg_level array. Store a pointer to
the pg_level array in the ptdump state structure. This will allow us to
extract the mask which is wrapped in the pg_level array and use it for
descriptor parsing in the note_page.
Signed-off-by: Sebastian Ene <sebastianene@google.com>
---
arch/arm64/include/asm/ptdump.h | 1 +
arch/arm64/mm/ptdump.c | 13 ++++++++-----
2 files changed, 9 insertions(+), 5 deletions(-)
diff --git a/arch/arm64/include/asm/ptdump.h b/arch/arm64/include/asm/ptdump.h
index c550b2afcab7..a4125d8d5a32 100644
--- a/arch/arm64/include/asm/ptdump.h
+++ b/arch/arm64/include/asm/ptdump.h
@@ -44,6 +44,7 @@ struct pg_level {
*/
struct pg_state {
struct ptdump_state ptdump;
+ struct pg_level *pg_level;
struct seq_file *seq;
const struct addr_marker *marker;
const struct mm_struct *mm;
diff --git a/arch/arm64/mm/ptdump.c b/arch/arm64/mm/ptdump.c
index e370b7a945de..9637a6415ea7 100644
--- a/arch/arm64/mm/ptdump.c
+++ b/arch/arm64/mm/ptdump.c
@@ -192,6 +192,7 @@ void note_page(struct ptdump_state *pt_st, unsigned long addr, int level,
u64 val)
{
struct pg_state *st = container_of(pt_st, struct pg_state, ptdump);
+ struct pg_level *pg_info = st->pg_level;
static const char units[] = "KMGTPE";
u64 prot = 0;
@@ -201,7 +202,7 @@ void note_page(struct ptdump_state *pt_st, unsigned long addr, int level,
level = 0;
if (level >= 0)
- prot = val & pg_level[level].mask;
+ prot = val & pg_info[level].mask;
if (st->level == -1) {
st->level = level;
@@ -227,10 +228,10 @@ void note_page(struct ptdump_state *pt_st, unsigned long addr, int level,
unit++;
}
pt_dump_seq_printf(st->seq, "%9lu%c %s", delta, *unit,
- pg_level[st->level].name);
- if (st->current_prot && pg_level[st->level].bits)
- dump_prot(st, pg_level[st->level].bits,
- pg_level[st->level].num);
+ pg_info[st->level].name);
+ if (st->current_prot && pg_info[st->level].bits)
+ dump_prot(st, pg_info[st->level].bits,
+ pg_info[st->level].num);
pt_dump_seq_puts(st->seq, "\n");
if (addr >= st->marker[1].start_address) {
@@ -262,6 +263,7 @@ void ptdump_walk(struct seq_file *s, struct ptdump_info *info)
.seq = s,
.marker = info->markers,
.mm = info->mm,
+ .pg_level = &pg_level[0],
.level = -1,
.ptdump = {
.note_page = note_page,
@@ -297,6 +299,7 @@ bool ptdump_check_wx(void)
{ 0, NULL},
{ -1, NULL},
},
+ .pg_level = &pg_level[0],
.level = -1,
.check_wx = true,
.ptdump = {
--
2.45.2.741.gdbec12cfda-goog
On Fri, Jun 21, 2024 at 12:32:27PM +0000, Sebastian Ene wrote:
> Printing the descriptor attributes requires accessing a mask which has a
> different set of attributes for stage-2. In preparation for adding support
> for the stage-2 pagetables dumping, use the mask from the local context
> and not from the globally defined pg_level array. Store a pointer to
> the pg_level array in the ptdump state structure. This will allow us to
> extract the mask which is wrapped in the pg_level array and use it for
> descriptor parsing in the note_page.
>
> Signed-off-by: Sebastian Ene <sebastianene@google.com>
> ---
> arch/arm64/include/asm/ptdump.h | 1 +
> arch/arm64/mm/ptdump.c | 13 ++++++++-----
> 2 files changed, 9 insertions(+), 5 deletions(-)
>
> diff --git a/arch/arm64/include/asm/ptdump.h b/arch/arm64/include/asm/ptdump.h
> index c550b2afcab7..a4125d8d5a32 100644
> --- a/arch/arm64/include/asm/ptdump.h
> +++ b/arch/arm64/include/asm/ptdump.h
> @@ -44,6 +44,7 @@ struct pg_level {
> */
> struct pg_state {
> struct ptdump_state ptdump;
> + struct pg_level *pg_level;
> struct seq_file *seq;
> const struct addr_marker *marker;
> const struct mm_struct *mm;
> diff --git a/arch/arm64/mm/ptdump.c b/arch/arm64/mm/ptdump.c
> index e370b7a945de..9637a6415ea7 100644
> --- a/arch/arm64/mm/ptdump.c
> +++ b/arch/arm64/mm/ptdump.c
> @@ -192,6 +192,7 @@ void note_page(struct ptdump_state *pt_st, unsigned long addr, int level,
> u64 val)
> {
> struct pg_state *st = container_of(pt_st, struct pg_state, ptdump);
> + struct pg_level *pg_info = st->pg_level;
> static const char units[] = "KMGTPE";
> u64 prot = 0;
>
> @@ -201,7 +202,7 @@ void note_page(struct ptdump_state *pt_st, unsigned long addr, int level,
> level = 0;
>
> if (level >= 0)
> - prot = val & pg_level[level].mask;
> + prot = val & pg_info[level].mask;
If you rename the existing 'pg_level' array to something like
'kernel_pg_levels' then I think your local 'pg_info' variable can be
called 'pg_level' and this line doesn't need to change.
>
> if (st->level == -1) {
> st->level = level;
> @@ -227,10 +228,10 @@ void note_page(struct ptdump_state *pt_st, unsigned long addr, int level,
> unit++;
> }
> pt_dump_seq_printf(st->seq, "%9lu%c %s", delta, *unit,
> - pg_level[st->level].name);
> - if (st->current_prot && pg_level[st->level].bits)
> - dump_prot(st, pg_level[st->level].bits,
> - pg_level[st->level].num);
> + pg_info[st->level].name);
> + if (st->current_prot && pg_info[st->level].bits)
> + dump_prot(st, pg_info[st->level].bits,
> + pg_info[st->level].num);
I think this could then stay as-is too.
> pt_dump_seq_puts(st->seq, "\n");
>
> if (addr >= st->marker[1].start_address) {
> @@ -262,6 +263,7 @@ void ptdump_walk(struct seq_file *s, struct ptdump_info *info)
> .seq = s,
> .marker = info->markers,
> .mm = info->mm,
> + .pg_level = &pg_level[0],
Can't this just be '.pg_level = kernel_pg_levels'?
Will
On Fri, Jul 05, 2024 at 12:12:29PM +0100, Will Deacon wrote:
> On Fri, Jun 21, 2024 at 12:32:27PM +0000, Sebastian Ene wrote:
> > Printing the descriptor attributes requires accessing a mask which has a
> > different set of attributes for stage-2. In preparation for adding support
> > for the stage-2 pagetables dumping, use the mask from the local context
> > and not from the globally defined pg_level array. Store a pointer to
> > the pg_level array in the ptdump state structure. This will allow us to
> > extract the mask which is wrapped in the pg_level array and use it for
> > descriptor parsing in the note_page.
> >
> > Signed-off-by: Sebastian Ene <sebastianene@google.com>
> > ---
> > arch/arm64/include/asm/ptdump.h | 1 +
> > arch/arm64/mm/ptdump.c | 13 ++++++++-----
> > 2 files changed, 9 insertions(+), 5 deletions(-)
> >
> > diff --git a/arch/arm64/include/asm/ptdump.h b/arch/arm64/include/asm/ptdump.h
> > index c550b2afcab7..a4125d8d5a32 100644
> > --- a/arch/arm64/include/asm/ptdump.h
> > +++ b/arch/arm64/include/asm/ptdump.h
> > @@ -44,6 +44,7 @@ struct pg_level {
> > */
> > struct pg_state {
> > struct ptdump_state ptdump;
> > + struct pg_level *pg_level;
> > struct seq_file *seq;
> > const struct addr_marker *marker;
> > const struct mm_struct *mm;
> > diff --git a/arch/arm64/mm/ptdump.c b/arch/arm64/mm/ptdump.c
> > index e370b7a945de..9637a6415ea7 100644
> > --- a/arch/arm64/mm/ptdump.c
> > +++ b/arch/arm64/mm/ptdump.c
> > @@ -192,6 +192,7 @@ void note_page(struct ptdump_state *pt_st, unsigned long addr, int level,
> > u64 val)
> > {
> > struct pg_state *st = container_of(pt_st, struct pg_state, ptdump);
> > + struct pg_level *pg_info = st->pg_level;
> > static const char units[] = "KMGTPE";
> > u64 prot = 0;
> >
> > @@ -201,7 +202,7 @@ void note_page(struct ptdump_state *pt_st, unsigned long addr, int level,
> > level = 0;
> >
> > if (level >= 0)
> > - prot = val & pg_level[level].mask;
> > + prot = val & pg_info[level].mask;
>
> If you rename the existing 'pg_level' array to something like
> 'kernel_pg_levels' then I think your local 'pg_info' variable can be
> called 'pg_level' and this line doesn't need to change.
>
This is a good ideea, thanks. I applied your suggestion
> >
> > if (st->level == -1) {
> > st->level = level;
> > @@ -227,10 +228,10 @@ void note_page(struct ptdump_state *pt_st, unsigned long addr, int level,
> > unit++;
> > }
> > pt_dump_seq_printf(st->seq, "%9lu%c %s", delta, *unit,
> > - pg_level[st->level].name);
> > - if (st->current_prot && pg_level[st->level].bits)
> > - dump_prot(st, pg_level[st->level].bits,
> > - pg_level[st->level].num);
> > + pg_info[st->level].name);
> > + if (st->current_prot && pg_info[st->level].bits)
> > + dump_prot(st, pg_info[st->level].bits,
> > + pg_info[st->level].num);
>
> I think this could then stay as-is too.
>
> > pt_dump_seq_puts(st->seq, "\n");
> >
> > if (addr >= st->marker[1].start_address) {
> > @@ -262,6 +263,7 @@ void ptdump_walk(struct seq_file *s, struct ptdump_info *info)
> > .seq = s,
> > .marker = info->markers,
> > .mm = info->mm,
> > + .pg_level = &pg_level[0],
>
> Can't this just be '.pg_level = kernel_pg_levels'?
>
> Will
Seb
© 2016 - 2025 Red Hat, Inc.