Reuse the descriptor parsing functionality to keep the same output format
as the original ptdump code. In order for this to happen, move the state
tracking objects into a common header.
Signed-off-by: Sebastian Ene <sebastianene@google.com>
---
arch/arm64/include/asm/ptdump.h | 41 +++++++++++++++++++++++-
arch/arm64/mm/ptdump.c | 55 +++++++--------------------------
2 files changed, 51 insertions(+), 45 deletions(-)
diff --git a/arch/arm64/include/asm/ptdump.h b/arch/arm64/include/asm/ptdump.h
index 5b1701c76d1c..bd5d3ee3e8dc 100644
--- a/arch/arm64/include/asm/ptdump.h
+++ b/arch/arm64/include/asm/ptdump.h
@@ -9,6 +9,7 @@
#include <linux/mm_types.h>
#include <linux/seq_file.h>
+#include <linux/ptdump.h>
struct addr_marker {
unsigned long start_address;
@@ -21,14 +22,52 @@ struct ptdump_info {
unsigned long base_addr;
};
+struct ptdump_prot_bits {
+ u64 mask;
+ u64 val;
+ const char *set;
+ const char *clear;
+};
+
+struct ptdump_pg_level {
+ const struct ptdump_prot_bits *bits;
+ char name[4];
+ int num;
+ u64 mask;
+};
+
+/*
+ * The page dumper groups page table entries of the same type into a single
+ * description. It uses pg_state to track the range information while
+ * iterating over the pte entries. When the continuity is broken it then
+ * dumps out a description of the range.
+ */
+struct ptdump_pg_state {
+ struct ptdump_state ptdump;
+ struct seq_file *seq;
+ const struct addr_marker *marker;
+ const struct mm_struct *mm;
+ unsigned long start_address;
+ int level;
+ u64 current_prot;
+ bool check_wx;
+ unsigned long wx_pages;
+ unsigned long uxn_pages;
+};
+
void ptdump_walk(struct seq_file *s, struct ptdump_info *info);
+void note_page(struct ptdump_state *pt_st, unsigned long addr, int level,
+ u64 val);
#ifdef CONFIG_PTDUMP_DEBUGFS
#define EFI_RUNTIME_MAP_END DEFAULT_MAP_WINDOW_64
void __init ptdump_debugfs_register(struct ptdump_info *info, const char *name);
#else
static inline void ptdump_debugfs_register(struct ptdump_info *info,
const char *name) { }
-#endif
+#endif /* CONFIG_PTDUMP_DEBUGFS */
+#else
+static inline void note_page(void *pt_st, unsigned long addr,
+ int level, u64 val) { }
#endif /* CONFIG_PTDUMP_CORE */
#endif /* __ASM_PTDUMP_H */
diff --git a/arch/arm64/mm/ptdump.c b/arch/arm64/mm/ptdump.c
index 6986827e0d64..404751fd30fe 100644
--- a/arch/arm64/mm/ptdump.c
+++ b/arch/arm64/mm/ptdump.c
@@ -38,33 +38,7 @@
seq_printf(m, fmt); \
})
-/*
- * The page dumper groups page table entries of the same type into a single
- * description. It uses pg_state to track the range information while
- * iterating over the pte entries. When the continuity is broken it then
- * dumps out a description of the range.
- */
-struct pg_state {
- struct ptdump_state ptdump;
- struct seq_file *seq;
- const struct addr_marker *marker;
- const struct mm_struct *mm;
- unsigned long start_address;
- int level;
- u64 current_prot;
- bool check_wx;
- unsigned long wx_pages;
- unsigned long uxn_pages;
-};
-
-struct prot_bits {
- u64 mask;
- u64 val;
- const char *set;
- const char *clear;
-};
-
-static const struct prot_bits pte_bits[] = {
+static const struct ptdump_prot_bits pte_bits[] = {
{
.mask = PTE_VALID,
.val = PTE_VALID,
@@ -143,14 +117,7 @@ static const struct prot_bits pte_bits[] = {
}
};
-struct pg_level {
- const struct prot_bits *bits;
- char name[4];
- int num;
- u64 mask;
-};
-
-static struct pg_level pg_level[] __ro_after_init = {
+static struct ptdump_pg_level pg_level[] __ro_after_init = {
{ /* pgd */
.name = "PGD",
.bits = pte_bits,
@@ -174,7 +141,7 @@ static struct pg_level pg_level[] __ro_after_init = {
},
};
-static void dump_prot(struct pg_state *st, const struct prot_bits *bits,
+static void dump_prot(struct ptdump_pg_state *st, const struct ptdump_prot_bits *bits,
size_t num)
{
unsigned i;
@@ -192,7 +159,7 @@ static void dump_prot(struct pg_state *st, const struct prot_bits *bits,
}
}
-static void note_prot_uxn(struct pg_state *st, unsigned long addr)
+static void note_prot_uxn(struct ptdump_pg_state *st, unsigned long addr)
{
if (!st->check_wx)
return;
@@ -206,7 +173,7 @@ static void note_prot_uxn(struct pg_state *st, unsigned long addr)
st->uxn_pages += (addr - st->start_address) / PAGE_SIZE;
}
-static void note_prot_wx(struct pg_state *st, unsigned long addr)
+static void note_prot_wx(struct ptdump_pg_state *st, unsigned long addr)
{
if (!st->check_wx)
return;
@@ -221,10 +188,10 @@ static void note_prot_wx(struct pg_state *st, unsigned long addr)
st->wx_pages += (addr - st->start_address) / PAGE_SIZE;
}
-static void note_page(struct ptdump_state *pt_st, unsigned long addr, int level,
- u64 val)
+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 ptdump_pg_state *st = container_of(pt_st, struct ptdump_pg_state, ptdump);
static const char units[] = "KMGTPE";
u64 prot = 0;
@@ -286,12 +253,12 @@ static void note_page(struct ptdump_state *pt_st, unsigned long addr, int level,
void ptdump_walk(struct seq_file *s, struct ptdump_info *info)
{
unsigned long end = ~0UL;
- struct pg_state st;
+ struct ptdump_pg_state st;
if (info->base_addr < TASK_SIZE_64)
end = TASK_SIZE_64;
- st = (struct pg_state){
+ st = (struct ptdump_pg_state){
.seq = s,
.marker = info->markers,
.mm = info->mm,
@@ -324,7 +291,7 @@ static struct ptdump_info kernel_ptdump_info __ro_after_init = {
bool ptdump_check_wx(void)
{
- struct pg_state st = {
+ struct ptdump_pg_state st = {
.seq = NULL,
.marker = (struct addr_marker[]) {
{ 0, NULL},
--
2.46.0.469.g59c65b2a67-goog
On Mon, Sep 09, 2024 at 12:47:18PM +0000, Sebastian Ene wrote: > Reuse the descriptor parsing functionality to keep the same output format > as the original ptdump code. In order for this to happen, move the state > tracking objects into a common header. > > Signed-off-by: Sebastian Ene <sebastianene@google.com> > --- > arch/arm64/include/asm/ptdump.h | 41 +++++++++++++++++++++++- > arch/arm64/mm/ptdump.c | 55 +++++++-------------------------- > 2 files changed, 51 insertions(+), 45 deletions(-) > > diff --git a/arch/arm64/include/asm/ptdump.h b/arch/arm64/include/asm/ptdump.h > index 5b1701c76d1c..bd5d3ee3e8dc 100644 > --- a/arch/arm64/include/asm/ptdump.h > +++ b/arch/arm64/include/asm/ptdump.h > @@ -9,6 +9,7 @@ > > #include <linux/mm_types.h> > #include <linux/seq_file.h> > +#include <linux/ptdump.h> > > struct addr_marker { > unsigned long start_address; > @@ -21,14 +22,52 @@ struct ptdump_info { > unsigned long base_addr; > }; > > +struct ptdump_prot_bits { > + u64 mask; > + u64 val; > + const char *set; > + const char *clear; > +}; > + > +struct ptdump_pg_level { > + const struct ptdump_prot_bits *bits; > + char name[4]; > + int num; > + u64 mask; > +}; > + > +/* > + * The page dumper groups page table entries of the same type into a single > + * description. It uses pg_state to track the range information while > + * iterating over the pte entries. When the continuity is broken it then > + * dumps out a description of the range. > + */ > +struct ptdump_pg_state { > + struct ptdump_state ptdump; > + struct seq_file *seq; > + const struct addr_marker *marker; > + const struct mm_struct *mm; > + unsigned long start_address; > + int level; > + u64 current_prot; > + bool check_wx; > + unsigned long wx_pages; > + unsigned long uxn_pages; > +}; > + > void ptdump_walk(struct seq_file *s, struct ptdump_info *info); > +void note_page(struct ptdump_state *pt_st, unsigned long addr, int level, > + u64 val); > #ifdef CONFIG_PTDUMP_DEBUGFS > #define EFI_RUNTIME_MAP_END DEFAULT_MAP_WINDOW_64 > void __init ptdump_debugfs_register(struct ptdump_info *info, const char *name); > #else > static inline void ptdump_debugfs_register(struct ptdump_info *info, > const char *name) { } > -#endif > +#endif /* CONFIG_PTDUMP_DEBUGFS */ > +#else > +static inline void note_page(void *pt_st, unsigned long addr, > + int level, u64 val) { } nit: but why isn't 'pt_st' a pointer to 'struct ptdump_state'? Perhaps you should #include <linux/ptdump.h> before the #ifdef CONFIG_PTDUMP_CORE ? In any case, the meat of the patch is fine: Acked-by: Will Deacon <will@kernel.org> Will
On Tue, 10 Sep 2024 10:57:18 +0100, Will Deacon <will@kernel.org> wrote: > > On Mon, Sep 09, 2024 at 12:47:18PM +0000, Sebastian Ene wrote: > > Reuse the descriptor parsing functionality to keep the same output format > > as the original ptdump code. In order for this to happen, move the state > > tracking objects into a common header. > > > > Signed-off-by: Sebastian Ene <sebastianene@google.com> > > --- > > arch/arm64/include/asm/ptdump.h | 41 +++++++++++++++++++++++- > > arch/arm64/mm/ptdump.c | 55 +++++++-------------------------- > > 2 files changed, 51 insertions(+), 45 deletions(-) > > > > diff --git a/arch/arm64/include/asm/ptdump.h b/arch/arm64/include/asm/ptdump.h > > index 5b1701c76d1c..bd5d3ee3e8dc 100644 > > --- a/arch/arm64/include/asm/ptdump.h > > +++ b/arch/arm64/include/asm/ptdump.h > > @@ -9,6 +9,7 @@ > > > > #include <linux/mm_types.h> > > #include <linux/seq_file.h> > > +#include <linux/ptdump.h> > > > > struct addr_marker { > > unsigned long start_address; > > @@ -21,14 +22,52 @@ struct ptdump_info { > > unsigned long base_addr; > > }; > > > > +struct ptdump_prot_bits { > > + u64 mask; > > + u64 val; > > + const char *set; > > + const char *clear; > > +}; > > + > > +struct ptdump_pg_level { > > + const struct ptdump_prot_bits *bits; > > + char name[4]; > > + int num; > > + u64 mask; > > +}; > > + > > +/* > > + * The page dumper groups page table entries of the same type into a single > > + * description. It uses pg_state to track the range information while > > + * iterating over the pte entries. When the continuity is broken it then > > + * dumps out a description of the range. > > + */ > > +struct ptdump_pg_state { > > + struct ptdump_state ptdump; > > + struct seq_file *seq; > > + const struct addr_marker *marker; > > + const struct mm_struct *mm; > > + unsigned long start_address; > > + int level; > > + u64 current_prot; > > + bool check_wx; > > + unsigned long wx_pages; > > + unsigned long uxn_pages; > > +}; > > + > > void ptdump_walk(struct seq_file *s, struct ptdump_info *info); > > +void note_page(struct ptdump_state *pt_st, unsigned long addr, int level, > > + u64 val); > > #ifdef CONFIG_PTDUMP_DEBUGFS > > #define EFI_RUNTIME_MAP_END DEFAULT_MAP_WINDOW_64 > > void __init ptdump_debugfs_register(struct ptdump_info *info, const char *name); > > #else > > static inline void ptdump_debugfs_register(struct ptdump_info *info, > > const char *name) { } > > -#endif > > +#endif /* CONFIG_PTDUMP_DEBUGFS */ > > +#else > > +static inline void note_page(void *pt_st, unsigned long addr, > > + int level, u64 val) { } > > nit: but why isn't 'pt_st' a pointer to 'struct ptdump_state'? > > Perhaps you should #include <linux/ptdump.h> before the #ifdef > CONFIG_PTDUMP_CORE ? Yup, that seems to do the trick. I'm folding this into the patch: diff --git a/arch/arm64/include/asm/ptdump.h b/arch/arm64/include/asm/ptdump.h index 71a7ed01153a4..6cf4aae052191 100644 --- a/arch/arm64/include/asm/ptdump.h +++ b/arch/arm64/include/asm/ptdump.h @@ -5,11 +5,12 @@ #ifndef __ASM_PTDUMP_H #define __ASM_PTDUMP_H +#include <linux/ptdump.h> + #ifdef CONFIG_PTDUMP_CORE #include <linux/mm_types.h> #include <linux/seq_file.h> -#include <linux/ptdump.h> struct addr_marker { unsigned long start_address; @@ -67,7 +68,7 @@ static inline void ptdump_debugfs_register(struct ptdump_info *info, const char *name) { } #endif /* CONFIG_PTDUMP_DEBUGFS */ #else -static inline void note_page(void *pt_st, unsigned long addr, +static inline void note_page(struct ptdump_state *pt_st, unsigned long addr, int level, u64 val) { } #endif /* CONFIG_PTDUMP_CORE */ > In any case, the meat of the patch is fine: > > Acked-by: Will Deacon <will@kernel.org> Thanks, M. -- Without deviation from the norm, progress is not possible.
© 2016 - 2024 Red Hat, Inc.