Module Name:    src
Committed By:   ryo
Date:           Tue Mar 19 16:45:28 UTC 2019

Modified Files:
        src/sys/arch/aarch64/aarch64: db_machdep.c pmap.c
        src/sys/arch/aarch64/include: pmap.h

Log Message:
- add ddb command "machine ttbr" to dump MMU tables.
- tidy up descriptions, usages and messages.


To generate a diff of this commit:
cvs rdiff -u -r1.14 -r1.15 src/sys/arch/aarch64/aarch64/db_machdep.c
cvs rdiff -u -r1.36 -r1.37 src/sys/arch/aarch64/aarch64/pmap.c
cvs rdiff -u -r1.22 -r1.23 src/sys/arch/aarch64/include/pmap.h

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/arch/aarch64/aarch64/db_machdep.c
diff -u src/sys/arch/aarch64/aarch64/db_machdep.c:1.14 src/sys/arch/aarch64/aarch64/db_machdep.c:1.15
--- src/sys/arch/aarch64/aarch64/db_machdep.c:1.14	Sun Jan 27 02:08:36 2019
+++ src/sys/arch/aarch64/aarch64/db_machdep.c	Tue Mar 19 16:45:28 2019
@@ -1,4 +1,4 @@
-/* $NetBSD: db_machdep.c,v 1.14 2019/01/27 02:08:36 pgoyette Exp $ */
+/* $NetBSD: db_machdep.c,v 1.15 2019/03/19 16:45:28 ryo Exp $ */
 
 /*-
  * Copyright (c) 2014 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: db_machdep.c,v 1.14 2019/01/27 02:08:36 pgoyette Exp $");
+__KERNEL_RCSID(0, "$NetBSD: db_machdep.c,v 1.15 2019/03/19 16:45:28 ryo Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_compat_netbsd32.h"
@@ -54,6 +54,7 @@ __KERNEL_RCSID(0, "$NetBSD: db_machdep.c
 #include <ddb/db_access.h>
 #include <ddb/db_command.h>
 #include <ddb/db_output.h>
+#include <ddb/db_proc.h>
 #include <ddb/db_variables.h>
 #include <ddb/db_run.h>
 #include <ddb/db_sym.h>
@@ -68,6 +69,7 @@ void db_md_frame_cmd(db_expr_t, bool, db
 void db_md_lwp_cmd(db_expr_t, bool, db_expr_t, const char *);
 void db_md_pte_cmd(db_expr_t, bool, db_expr_t, const char *);
 void db_md_tlbi_cmd(db_expr_t, bool, db_expr_t, const char *);
+void db_md_ttbr_cmd(db_expr_t, bool, db_expr_t, const char *);
 void db_md_sysreg_cmd(db_expr_t, bool, db_expr_t, const char *);
 void db_md_watch_cmd(db_expr_t, bool, db_expr_t, const char *);
 #if defined(_KERNEL) && defined(MULTIPROCESSOR)
@@ -87,28 +89,28 @@ const struct db_command db_machine_comma
 	{
 		DDB_ADD_CMD(
 		    "cpuinfo", db_md_cpuinfo_cmd, 0,
-		    "Displays the cpuinfo",
+		    "Displays the current cpuinfo",
 		    NULL, NULL)
 	},
 	{
 		DDB_ADD_CMD(
 		    "frame", db_md_frame_cmd, 0,
 		    "Displays the contents of a trapframe",
-		    "<address>",
-		    "\taddress:\taddress of trapfame to display")
+		    "address",
+		    "\taddress:\taddress of trapframe to display")
 	},
 	{
 		DDB_ADD_CMD(
 		    "lwp", db_md_lwp_cmd, 0,
 		    "Displays the lwp",
-		    "<address>",
+		    "address",
 		    "\taddress:\taddress of lwp to display")
 	},
 	{
 		DDB_ADD_CMD(
 		    "pte", db_md_pte_cmd, 0,
 		    "Display information of pte",
-		    "<address>",
+		    "address",
 		    "\taddress:\tvirtual address of page")
 	},
 	{
@@ -125,16 +127,26 @@ const struct db_command db_machine_comma
 	},
 	{
 		DDB_ADD_CMD(
+		    "ttbr", db_md_ttbr_cmd, 0,
+		    "Dump or count TTBR table",
+		    "[/apc] address | pid",
+		    "\taddress:\taddress of pmap to display\n"
+		    "\tpid:\t\tpid of pmap to display")
+	},
+	{
+		DDB_ADD_CMD(
 		    "watch", db_md_watch_cmd, 0,
 		    "set or clear watchpoint",
-		    "<param>",
-		    "\tparam: <address> | <#>")
+		    "[/12345678] [address|#]",
+		    "\taddress: watchpoint address to set\n"
+		    "\t#: watchpoint number to remove"
+		    "\t/1..8: size of data\n")
 	},
 #endif
 	{
 		DDB_ADD_CMD(NULL, NULL, 0,
 		    NULL,
-		    NULL,NULL)
+		    NULL, NULL)
 	}
 };
 
@@ -290,7 +302,7 @@ db_md_frame_cmd(db_expr_t addr, bool hav
 	struct trapframe *tf;
 
 	if (!have_addr) {
-		db_printf("frame: <address>\n");
+		db_printf("frame address must be specified\n");
 		return;
 	}
 
@@ -306,7 +318,7 @@ db_md_lwp_cmd(db_expr_t addr, bool have_
 	struct pcb *pcb;
 
 	if (!have_addr) {
-		db_printf("lwp: <address>\n");
+		db_printf("lwp address must be specified\n");
 		return;
 	}
 	l = (lwp_t *)addr;
@@ -339,7 +351,7 @@ db_md_pte_cmd(db_expr_t addr, bool have_
     const char *modif)
 {
 	if (!have_addr) {
-		db_printf("pte: <address>\n");
+		db_printf("pte address must be specified\n");
 		return;
 	}
 	pmap_db_pteinfo(addr, db_printf);
@@ -353,6 +365,48 @@ db_md_tlbi_cmd(db_expr_t addr, bool have
 }
 
 void
+db_md_ttbr_cmd(db_expr_t addr, bool have_addr, db_expr_t count,
+    const char *modif)
+{
+	bool countmode = false, by_pid = true;
+
+	if (!have_addr) {
+		db_printf("usage: machine ttbr [/a] [/p] [/c] address|pid\n");
+		db_printf("\t/a == argument is an address of any pmap_t\n");
+		db_printf("\t/p == argument is a pid [default]\n");
+		db_printf("\t/c == count TLB entries\n");
+		return;
+	}
+
+	if (modif != NULL) {
+		for (; *modif != '\0'; modif++) {
+			switch (*modif) {
+			case 'c':
+				countmode = true;
+				break;
+			case 'a':
+				by_pid = false;
+				break;
+			case 'p':
+				by_pid = true;
+				break;
+			}
+		}
+	}
+
+	if (by_pid) {
+		proc_t *p = db_proc_find((pid_t)addr);
+		if (p == NULL) {
+			db_printf("bad address\n");
+			return;
+		}
+		addr = (db_addr_t)p->p_vmspace->vm_map.pmap;
+	}
+
+	pmap_db_ttbrdump(countmode, addr, db_printf);
+}
+
+void
 db_md_sysreg_cmd(db_expr_t addr, bool have_addr, db_expr_t count,
     const char *modif)
 {

Index: src/sys/arch/aarch64/aarch64/pmap.c
diff -u src/sys/arch/aarch64/aarch64/pmap.c:1.36 src/sys/arch/aarch64/aarch64/pmap.c:1.37
--- src/sys/arch/aarch64/aarch64/pmap.c:1.36	Tue Mar 19 16:05:49 2019
+++ src/sys/arch/aarch64/aarch64/pmap.c	Tue Mar 19 16:45:28 2019
@@ -1,4 +1,4 @@
-/*	$NetBSD: pmap.c,v 1.36 2019/03/19 16:05:49 ryo Exp $	*/
+/*	$NetBSD: pmap.c,v 1.37 2019/03/19 16:45:28 ryo Exp $	*/
 
 /*
  * Copyright (c) 2017 Ryo Shimizu <[email protected]>
@@ -27,7 +27,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: pmap.c,v 1.36 2019/03/19 16:05:49 ryo Exp $");
+__KERNEL_RCSID(0, "$NetBSD: pmap.c,v 1.37 2019/03/19 16:45:28 ryo Exp $");
 
 #include "opt_arm_debug.h"
 #include "opt_ddb.h"
@@ -50,6 +50,10 @@ __KERNEL_RCSID(0, "$NetBSD: pmap.c,v 1.3
 #include <aarch64/armreg.h>
 #include <aarch64/cpufunc.h>
 #include <aarch64/machdep.h>
+#ifdef DDB
+#include <aarch64/db_machdep.h>
+#include <ddb/db_access.h>
+#endif
 
 //#define PMAP_DEBUG
 //#define PMAP_PV_DEBUG
@@ -2165,6 +2169,7 @@ pmap_is_referenced(struct vm_page *pg)
 }
 
 #ifdef DDB
+
 /* get pointer to kernel segment L2 or L3 table entry */
 pt_entry_t *
 kvtopte(vaddr_t va)
@@ -2232,7 +2237,7 @@ pmap_db_pte_print(pt_entry_t pte, int le
 		if ((level == 0) && ((pte & LX_TYPE) != LX_TYPE_TBL))
 			pr(" **ILLEGAL TYPE**"); /* L0 doesn't support block */
 		else
-			pr(" TABLE");
+			pr(" L%d-TABLE", level);
 
 		pr(", PA=%lx", l0pde_pa(pte));
 
@@ -2250,22 +2255,35 @@ pmap_db_pte_print(pt_entry_t pte, int le
 	    (level == 3)) {
 
 		/* L1/L2 BLOCK or L3 PAGE */
-		if (level == 3) {
+		switch (level) {
+		case 1:
+			pr(" L1(1G)-BLOCK");
+			break;
+		case 2:
+			pr(" L2(2M)-BLOCK");
+			break;
+		case 3:
 			pr(" %s", l3pte_is_page(pte) ?
-			    "PAGE" : "**ILLEGAL TYPE**");
-		} else
-			pr(" BLOCK");
+			    "L3(4K)-PAGE" : "**ILLEGAL TYPE**");
+			break;
+		}
 
 		pr(", PA=%lx", l3pte_pa(pte));
 
-		pr(", %s", (pte & LX_BLKPAG_UXN) ? "UXN" : "user-exec");
-		pr(", %s", (pte & LX_BLKPAG_PXN) ? "PXN" : "kernel-exec");
+		pr(", %s", (pte & LX_BLKPAG_UXN) ?
+		    "UXN      " :
+		    "user-exec");
+		pr(", %s", (pte & LX_BLKPAG_PXN) ?
+		   "PXN        " :
+		   "kernel-exec");
 
 		if (pte & LX_BLKPAG_CONTIG)
 			pr(", CONTIG");
 
 		pr(", %s", (pte & LX_BLKPAG_NG) ? "NG" : "global");
-		pr(", %s", (pte & LX_BLKPAG_AF) ? "AF" : "*cannot-access*");
+		pr(", %s", (pte & LX_BLKPAG_AF) ?
+		    "accessible" :
+		    "**fault** ");
 
 		switch (pte & LX_BLKPAG_SH) {
 		case LX_BLKPAG_SH_NS:
@@ -2396,4 +2414,103 @@ pmap_db_pteinfo(vaddr_t va, void (*pr)(c
 		pv_dump(md, pr);
 	}
 }
+
+static void
+dump_ln_table(bool countmode, pd_entry_t *pdp, int level, int lnindex,
+    vaddr_t va, void (*pr)(const char *, ...))
+{
+	struct vm_page *pg;
+	struct vm_page_md *md;
+	pd_entry_t pde;
+	paddr_t pa;
+	int i, n;
+	const char *spaces[4] = { " ", "  ", "   ", "    " };
+	const char *spc = spaces[level];
+
+	pa = AARCH64_KVA_TO_PA((vaddr_t)pdp);
+	pg = PHYS_TO_VM_PAGE(pa);
+	md = VM_PAGE_TO_MD(pg);
+
+	if (pg == NULL) {
+		pr("%sL%d: pa=%lx pg=NULL\n", spc, level, pa);
+	} else {
+		pr("%sL%d: pa=%lx pg=%p, wire_count=%d, mdpg_ptep_parent=%p\n",
+		    spc, level, pa, pg, pg->wire_count, md->mdpg_ptep_parent);
+	}
+
+	for (i = n = 0; i < Ln_ENTRIES; i++) {
+		db_read_bytes((db_addr_t)&pdp[i], sizeof(pdp[i]), (char *)&pde);
+		if (lxpde_valid(pde)) {
+			if (!countmode)
+				pr("%sL%d[%3d] %3dth, va=%016lx, pte=%016lx:",
+				    spc, level, i, n, va, pde);
+			n++;
+
+			if (((level != 0) && (level != 3) &&
+			    l1pde_is_block(pde)) ||
+			    ((level == 3) && l3pte_is_page(pde))) {
+				if (!countmode)
+					pmap_db_pte_print(pde, level, pr);
+			} else if ((level != 3) && l1pde_is_table(pde)) {
+				if (!countmode)
+					pmap_db_pte_print(pde, level, pr);
+				pa = l0pde_pa(pde);
+				dump_ln_table(countmode,
+				    (pd_entry_t *)AARCH64_PA_TO_KVA(pa),
+				    level + 1, i, va, pr);
+			} else {
+				if (!countmode)
+					pmap_db_pte_print(pde, level, pr);
+			}
+		}
+
+		switch (level) {
+		case 0:
+			va += L0_SIZE;
+			break;
+		case 1:
+			va += L1_SIZE;
+			break;
+		case 2:
+			va += L2_SIZE;
+			break;
+		case 3:
+			va += L3_SIZE;
+			break;
+		}
+	}
+
+	if (level == 0)
+		pr("L0 has %d entries\n", n);
+	else
+		pr("%sL%d[%3d] has %d L%d entries\n", spaces[level - 1],
+		    level - 1, lnindex, n, level);
+
+}
+
+static void
+pmap_db_dump_l0_table(bool countmode, pd_entry_t *pdp, vaddr_t va_base,
+    void (*pr)(const char *, ...))
+{
+	dump_ln_table(countmode, pdp, 0, 0, va_base, pr);
+}
+
+void
+pmap_db_ttbrdump(bool countmode, vaddr_t va, void (*pr)(const char *, ...))
+{
+	struct pmap *pm, _pm;
+
+	pm = (struct pmap *)va;
+	db_read_bytes((db_addr_t)va, sizeof(_pm), (char *)&_pm);
+
+	pr("pmap=%p\n", pm);
+	pr(" pm_asid       = %d\n", _pm.pm_asid);
+	pr(" pm_l0table    = %p\n", _pm.pm_l0table);
+	pr(" pm_l0table_pa = %lx\n", _pm.pm_l0table_pa);
+	pr(" pm_activated  = %d\n\n", _pm.pm_activated);
+
+	pmap_db_dump_l0_table(countmode, _pm.pm_l0table,
+	    (pm == pmap_kernel()) ? 0xffff000000000000UL : 0, pr);
+}
+
 #endif /* DDB */

Index: src/sys/arch/aarch64/include/pmap.h
diff -u src/sys/arch/aarch64/include/pmap.h:1.22 src/sys/arch/aarch64/include/pmap.h:1.23
--- src/sys/arch/aarch64/include/pmap.h:1.22	Tue Mar 19 16:05:49 2019
+++ src/sys/arch/aarch64/include/pmap.h	Tue Mar 19 16:45:28 2019
@@ -1,4 +1,4 @@
-/* $NetBSD: pmap.h,v 1.22 2019/03/19 16:05:49 ryo Exp $ */
+/* $NetBSD: pmap.h,v 1.23 2019/03/19 16:45:28 ryo Exp $ */
 
 /*-
  * Copyright (c) 2014 The NetBSD Foundation, Inc.
@@ -149,6 +149,8 @@ bool pmap_fault_fixup(struct pmap *, vad
 
 /* for ddb */
 void pmap_db_pteinfo(vaddr_t, void (*)(const char *, ...) __printflike(1, 2));
+void pmap_db_ttbrdump(bool, vaddr_t, void (*)(const char *, ...)
+    __printflike(1, 2));
 pt_entry_t *kvtopte(vaddr_t);
 pt_entry_t pmap_kvattr(vaddr_t, vm_prot_t);
 

Reply via email to