linux-mm.kvack.org archive mirror
 help / color / mirror / Atom feed
From: Maxwell Bland <mbland@motorola.com>
To: linux-mm@kvack.org
Cc: Catalin Marinas <catalin.marinas@arm.com>,
	Will Deacon <will@kernel.org>, Jonathan Corbet <corbet@lwn.net>,
	Andrew Morton <akpm@linux-foundation.org>,
	Ard Biesheuvel <ardb@kernel.org>,
	Mark Rutland <mark.rutland@arm.com>,
	Christophe Leroy <christophe.leroy@csgroup.eu>,
	Maxwell Bland <mbland@motorola.com>,
	Alexandre Ghiti <alexghiti@rivosinc.com>,
	linux-arm-kernel@lists.infradead.org, linux-doc@vger.kernel.org,
	linux-kernel@vger.kernel.org
Subject: [PATCH v5 3/6] arm64: table descriptor ptdump support
Date: Mon, 24 Jun 2024 17:13:16 -0500	[thread overview]
Message-ID: <3z4hwt3fcvscs7zu767vp33tp2mqjor5edfnpgmd2s5p66sg6j@elmhqmeujb5m> (raw)
In-Reply-To: <2bcb3htsjhepxdybpw2bwot2jnuezl3p5mnj5rhjwgitlsufe7@xzhkyntridw3>

Distinguish between table and block descriptor attribute bitfields,
enable the Kconfig option to print table descriptors and intermediate
page table entries, and support printing of attributes specific to table
descriptors, such as PXNTable.

This is useful when debugging protection systems that leverage
hierarchical access control.

Signed-off-by: Maxwell Bland <mbland@motorola.com>
---
 arch/arm64/Kconfig     |   1 +
 arch/arm64/mm/ptdump.c | 142 +++++++++++++++++++++++++++++++----------
 2 files changed, 108 insertions(+), 35 deletions(-)

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 5d91259ee7b5..f4c3290160db 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -98,6 +98,7 @@ config ARM64
 	select ARCH_SUPPORTS_NUMA_BALANCING
 	select ARCH_SUPPORTS_PAGE_TABLE_CHECK
 	select ARCH_SUPPORTS_PER_VMA_LOCK
+	select ARCH_SUPPORTS_NON_LEAF_PTDUMP
 	select ARCH_WANT_BATCHED_UNMAP_TLB_FLUSH
 	select ARCH_WANT_COMPAT_IPC_PARSE_VERSION if COMPAT
 	select ARCH_WANT_DEFAULT_BPF_JIT
diff --git a/arch/arm64/mm/ptdump.c b/arch/arm64/mm/ptdump.c
index 6986827e0d64..33ca6d182a6a 100644
--- a/arch/arm64/mm/ptdump.c
+++ b/arch/arm64/mm/ptdump.c
@@ -24,6 +24,7 @@
 #include <asm/memory.h>
 #include <asm/pgtable-hwdef.h>
 #include <asm/ptdump.h>
+#include <asm/pgalloc.h>
 
 
 #define pt_dump_seq_printf(m, fmt, args...)	\
@@ -64,7 +65,7 @@ struct prot_bits {
 	const char	*clear;
 };
 
-static const struct prot_bits pte_bits[] = {
+static const struct prot_bits blk_bits[] = {
 	{
 		.mask	= PTE_VALID,
 		.val	= PTE_VALID,
@@ -78,13 +79,13 @@ static const struct prot_bits pte_bits[] = {
 	}, {
 		.mask	= PTE_RDONLY,
 		.val	= PTE_RDONLY,
-		.set	= "ro",
+		.set	= "RO",
 		.clear	= "RW",
 	}, {
 		.mask	= PTE_PXN,
 		.val	= PTE_PXN,
 		.set	= "NX",
-		.clear	= "x ",
+		.clear	= "X ",
 	}, {
 		.mask	= PTE_SHARED,
 		.val	= PTE_SHARED,
@@ -142,44 +143,101 @@ static const struct prot_bits pte_bits[] = {
 		.set	= "MEM/NORMAL-TAGGED",
 	}
 };
+static const size_t num_blk_bits = ARRAY_SIZE(blk_bits);
+
+static const struct prot_bits tbl_bits[] = {
+	{
+		.mask	= PTE_VALID,
+		.val	= PTE_VALID,
+		.set	= " ",
+		.clear	= "F",
+	}, {
+		.mask	= PMD_TABLE_BIT,
+		.val	= PMD_TABLE_BIT,
+		.set	= "TBL",
+		.clear	= "   ",
+	}, {
+		.mask	= PTE_AF,
+		.val	= PTE_AF,
+		.set	= "AF",
+		.clear	= "  ",
+	}, {
+		.mask	= PMD_TABLE_PXN,
+		.val	= PMD_TABLE_PXN,
+		.set	= "NX",
+		.clear	= "     ",
+	}, {
+		.mask	= PMD_TABLE_UXN,
+		.val	= PMD_TABLE_UXN,
+		.set	= "UXN",
+		.clear	= "      ",
+	}, {
+		.mask	= PMD_TABLE_KERN,
+		.val	= PMD_TABLE_KERN,
+		.set	= "KRN",
+		.clear	= "    "
+	}, {
+		.mask	= PMD_TABLE_PRDONLY,
+		.val	= PMD_TABLE_PRDONLY,
+		.set	= "RO",
+		.clear	= "RW"
+	}
+};
+static const size_t num_tbl_bits = ARRAY_SIZE(tbl_bits);
 
 struct pg_level {
-	const struct prot_bits *bits;
+	const struct prot_bits *blk_bits;
+	const struct prot_bits *tbl_bits;
 	char name[4];
-	int num;
 	u64 mask;
+	unsigned long size;
 };
 
 static struct pg_level pg_level[] __ro_after_init = {
 	{ /* pgd */
-		.name	= "PGD",
-		.bits	= pte_bits,
-		.num	= ARRAY_SIZE(pte_bits),
+		.name		= "PGD",
+		.blk_bits	= blk_bits,
+		.size		= PGDIR_SIZE,
+		.tbl_bits	= tbl_bits
 	}, { /* p4d */
-		.name	= "P4D",
-		.bits	= pte_bits,
-		.num	= ARRAY_SIZE(pte_bits),
+		.name		= "P4D",
+		.blk_bits	= blk_bits,
+		.size		= P4D_SIZE,
+		.tbl_bits	= tbl_bits
 	}, { /* pud */
-		.name	= "PUD",
-		.bits	= pte_bits,
-		.num	= ARRAY_SIZE(pte_bits),
+		.name		= "PUD",
+		.blk_bits	= blk_bits,
+		.size		= PUD_SIZE,
+		.tbl_bits	= tbl_bits
 	}, { /* pmd */
-		.name	= "PMD",
-		.bits	= pte_bits,
-		.num	= ARRAY_SIZE(pte_bits),
+		.name		= "PMD",
+		.blk_bits	= blk_bits,
+		.size		= PMD_SIZE,
+		.tbl_bits	= tbl_bits
 	}, { /* pte */
-		.name	= "PTE",
-		.bits	= pte_bits,
-		.num	= ARRAY_SIZE(pte_bits),
+		.name		= "PTE",
+		.blk_bits	= blk_bits,
+		.size		= PAGE_SIZE,
+		.tbl_bits	= NULL
 	},
 };
 
-static void dump_prot(struct pg_state *st, const struct prot_bits *bits,
-			size_t num)
+static void dump_prot(struct pg_state *st, struct pg_level level)
 {
 	unsigned i;
+	const struct prot_bits *bits;
+	int num_bits;
 
-	for (i = 0; i < num; i++, bits++) {
+	if ((st->current_prot & PTE_TABLE_BIT) == PTE_TABLE_BIT &&
+	    level.tbl_bits) {
+		bits = level.tbl_bits;
+		num_bits = num_tbl_bits;
+	} else {
+		bits = level.blk_bits;
+		num_bits = num_blk_bits;
+	}
+
+	for (i = 0; i < num_bits; i++, bits++) {
 		const char *s;
 
 		if ((st->current_prot & bits->mask) == bits->val)
@@ -251,21 +309,30 @@ static void note_page(struct ptdump_state *pt_st, unsigned long addr, int level,
 			note_prot_wx(st, addr);
 		}
 
-		pt_dump_seq_printf(st->seq, "0x%016lx-0x%016lx   ",
-				   st->start_address, addr);
+		if (st->start_address == addr) {
+			if (check_add_overflow(addr, pg_level[st->level].size,
+					       &delta))
+				delta = ULONG_MAX - addr + 1;
+			else
+				delta = pg_level[st->level].size;
+			pt_dump_seq_printf(st->seq, "0x%016lx-0x%016lx   ",
+					   addr, addr + delta);
+		} else {
+			delta = (addr - st->start_address);
+			pt_dump_seq_printf(st->seq, "0x%016lx-0x%016lx   ",
+					   st->start_address, addr);
+		}
 
-		delta = (addr - st->start_address) >> 10;
+		delta >>= 10;
 		while (!(delta & 1023) && unit[1]) {
 			delta >>= 10;
 			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);
+		if (st->current_prot && pg_level[st->level].blk_bits)
+			dump_prot(st, pg_level[st->level]);
 		pt_dump_seq_puts(st->seq, "\n");
-
 		if (addr >= st->marker[1].start_address) {
 			st->marker++;
 			pt_dump_seq_printf(st->seq, "---[ %s ]---\n", st->marker->name);
@@ -311,11 +378,16 @@ void ptdump_walk(struct seq_file *s, struct ptdump_info *info)
 static void __init ptdump_initialize(void)
 {
 	unsigned i, j;
-
-	for (i = 0; i < ARRAY_SIZE(pg_level); i++)
-		if (pg_level[i].bits)
-			for (j = 0; j < pg_level[i].num; j++)
-				pg_level[i].mask |= pg_level[i].bits[j].mask;
+	struct pg_level *level = pg_level;
+
+	for (i = 0; i < ARRAY_SIZE(pg_level); i++, level++) {
+		if (level->blk_bits)
+			for (j = 0; j < num_blk_bits; j++)
+				level->mask |= level->blk_bits[j].mask;
+		if (level->tbl_bits)
+			for (j = 0; j < num_tbl_bits; j++)
+				level->mask |= level->tbl_bits[j].mask;
+	}
 }
 
 static struct ptdump_info kernel_ptdump_info __ro_after_init = {
-- 
2.43.0




  parent reply	other threads:[~2024-06-24 22:13 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-06-24 22:07 [PATCH v5 0/6] ptdump: add intermediate directory support Maxwell Bland
2024-06-24 22:11 ` [PATCH v5 1/6] mm: add ARCH_SUPPORTS_NON_LEAF_PTDUMP Maxwell Bland
2024-07-05  2:52   ` kernel test robot
2024-07-15 21:24     ` Maxwell Bland
2024-06-24 22:12 ` [PATCH v5 2/6] arm64: add APTable encoding to pagetable defs Maxwell Bland
2024-06-24 22:13 ` Maxwell Bland [this message]
2024-06-24 22:14 ` [PATCH v5 4/6] arm64: indent ptdump by level, aligning attributes Maxwell Bland
2024-06-24 22:15 ` [PATCH v5 5/6] arm64: exclusive upper bound for ptdump entries Maxwell Bland
2024-06-24 22:16 ` [PATCH v5 6/6] arm64: add attrs and format to ptdump document Maxwell Bland
2024-06-26 23:45   ` Randy Dunlap

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=3z4hwt3fcvscs7zu767vp33tp2mqjor5edfnpgmd2s5p66sg6j@elmhqmeujb5m \
    --to=mbland@motorola.com \
    --cc=akpm@linux-foundation.org \
    --cc=alexghiti@rivosinc.com \
    --cc=ardb@kernel.org \
    --cc=catalin.marinas@arm.com \
    --cc=christophe.leroy@csgroup.eu \
    --cc=corbet@lwn.net \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=linux-doc@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-mm@kvack.org \
    --cc=mark.rutland@arm.com \
    --cc=will@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox