Module Name:    src
Committed By:   skrll
Date:           Fri Apr 30 20:07:23 UTC 2021

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

Log Message:
Make the ddb for pmap / pte information pmap agnostic


To generate a diff of this commit:
cvs rdiff -u -r1.12 -r1.13 src/sys/arch/aarch64/aarch64/db_interface.c
cvs rdiff -u -r1.39 -r1.40 src/sys/arch/aarch64/aarch64/db_machdep.c
cvs rdiff -u -r1.106 -r1.107 src/sys/arch/aarch64/aarch64/pmap.c
cvs rdiff -u -r1.16 -r1.17 src/sys/arch/aarch64/aarch64/pmapboot.c
cvs rdiff -u -r1.13 -r1.14 src/sys/arch/aarch64/include/db_machdep.h
cvs rdiff -u -r1.46 -r1.47 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_interface.c
diff -u src/sys/arch/aarch64/aarch64/db_interface.c:1.12 src/sys/arch/aarch64/aarch64/db_interface.c:1.13
--- src/sys/arch/aarch64/aarch64/db_interface.c:1.12	Fri Feb  5 21:44:34 2021
+++ src/sys/arch/aarch64/aarch64/db_interface.c	Fri Apr 30 20:07:22 2021
@@ -1,4 +1,4 @@
-/* $NetBSD: db_interface.c,v 1.12 2021/02/05 21:44:34 joerg Exp $ */
+/* $NetBSD: db_interface.c,v 1.13 2021/04/30 20:07:22 skrll Exp $ */
 
 /*
  * Copyright (c) 2017 Ryo Shimizu <r...@nerv.org>
@@ -27,13 +27,17 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: db_interface.c,v 1.12 2021/02/05 21:44:34 joerg Exp $");
+__KERNEL_RCSID(0, "$NetBSD: db_interface.c,v 1.13 2021/04/30 20:07:22 skrll Exp $");
 
 #include <sys/param.h>
 #include <sys/types.h>
 
 #include <uvm/uvm.h>
+#include <uvm/uvm_ddb.h>
 #include <uvm/uvm_prot.h>
+#ifdef __HAVE_PMAP_PV_TRACK
+#include <uvm/pmap/pmap_pvt.h>
+#endif
 
 #include <aarch64/db_machdep.h>
 #include <aarch64/machdep.h>
@@ -53,6 +57,21 @@ __KERNEL_RCSID(0, "$NetBSD: db_interface
 
 db_regs_t ddb_regs;
 
+static int
+db_validate_address(vaddr_t addr)
+{
+	struct proc *p = curproc;
+	struct pmap *pmap;
+
+	if (!p || !p->p_vmspace || !p->p_vmspace->vm_map.pmap ||
+	    addr >= VM_MAXUSER_ADDRESS)
+		pmap = pmap_kernel();
+	else
+		pmap = p->p_vmspace->vm_map.pmap;
+
+	return (pmap_extract(pmap, addr, NULL) == false);
+}
+
 void
 db_read_bytes(vaddr_t addr, size_t size, char *data)
 {
@@ -60,15 +79,15 @@ db_read_bytes(vaddr_t addr, size_t size,
 	const char *src;
 
 	for (src = (const char *)addr; size > 0;) {
+		const vaddr_t va = (vaddr_t)src;
 		uintptr_t tmp;
 
-		if ((lastpage != atop((vaddr_t)src)) &&
-		    vtophys((vaddr_t)src) == VTOPHYS_FAILED) {
+		if (lastpage != atop(va) && db_validate_address(va)) {
 			db_printf("address %p is invalid\n", src);
 			memset(data, 0, size);	/* stubs are filled by zero */
 			return;
 		}
-		lastpage = atop((vaddr_t)src);
+		lastpage = atop(va);
 
 		if (aarch64_pan_enabled)
 			reg_pan_write(0); /* disable PAN */
@@ -120,9 +139,6 @@ db_write_text(vaddr_t addr, size_t size,
 		ptep = kvtopte(addr);
 		KASSERT(ptep != NULL);
 
-		/* save pte */
-		pte = *ptep;
-
 		/*
 		 * change to writable.  it is required to keep execute permission.
 		 * because if the block/page to which the target address belongs is
@@ -130,7 +146,8 @@ db_write_text(vaddr_t addr, size_t size,
 		 * if PROT_EXECUTE is dropped and TLB is invalidated, the program
 		 * will stop...
 		 */
-		pmap_kvattr(addr, VM_PROT_EXECUTE|VM_PROT_READ|VM_PROT_WRITE);
+		/* old pte is returned by pmap_kvattr */
+		pte = pmap_kvattr(ptep, VM_PROT_EXECUTE|VM_PROT_READ|VM_PROT_WRITE);
 		aarch64_tlbi_all();
 
 		s = size;
@@ -175,14 +192,14 @@ db_write_bytes(vaddr_t addr, size_t size
 
 	/* XXX: need to check read only block/page */
 	for (dst = (char *)addr; size > 0;) {
+		const vaddr_t va = (vaddr_t)dst;
 		uintptr_t tmp;
 
-		if ((lastpage != atop((vaddr_t)dst)) &&
-		    (vtophys((vaddr_t)dst) == VTOPHYS_FAILED)) {
+		if (lastpage != atop(va) && db_validate_address(va)) {
 			db_printf("address %p is invalid\n", dst);
 			return;
 		}
-		lastpage = atop((vaddr_t)dst);
+		lastpage = atop(va);
 
 		tmp = (uintptr_t)dst | (uintptr_t)data;
 		if ((size >= 8) && ((tmp & 7) == 0)) {
@@ -290,3 +307,313 @@ db_inst_unconditional_flow_transfer(db_e
 
 	return false;
 }
+
+void
+db_pte_print(pt_entry_t pte, int level,
+    void (*pr)(const char *, ...) __printflike(1, 2))
+{
+	if (pte == 0) {
+		pr(" UNUSED\n");
+		return;
+	}
+
+	pr(" %s", (pte & LX_VALID) ? "VALID" : "**INVALID**");
+
+	if ((level == 0) ||
+	    ((level == 1) && l1pde_is_table(pte)) ||
+	    ((level == 2) && l2pde_is_table(pte))) {
+
+		/* L0/L1/L2 TABLE */
+		if ((level == 0) && ((pte & LX_TYPE) != LX_TYPE_TBL))
+			pr(" **ILLEGAL TYPE**"); /* L0 doesn't support block */
+		else
+			pr(" L%d-TABLE", level);
+
+		pr(", PA=%lx", l0pde_pa(pte));
+
+		if (pte & LX_TBL_NSTABLE)
+			pr(", NSTABLE");
+		if (pte & LX_TBL_APTABLE)
+			pr(", APTABLE");
+		if (pte & LX_TBL_UXNTABLE)
+			pr(", UXNTABLE");
+		if (pte & LX_TBL_PXNTABLE)
+			pr(", PXNTABLE");
+
+	} else if (((level == 1) && l1pde_is_block(pte)) ||
+	    ((level == 2) && l2pde_is_block(pte)) ||
+	    (level == 3)) {
+
+		/* L1/L2 BLOCK or L3 PAGE */
+		switch (level) {
+		case 1:
+			pr(" L1(1G)-BLOCK");
+			break;
+		case 2:
+			pr(" L2(2M)-BLOCK");
+			break;
+		case 3:
+			pr(" %s", l3pte_is_page(pte) ?
+			    "L3(4K)-PAGE" : "**ILLEGAL TYPE**");
+			break;
+		}
+
+		pr(", PA=%lx", l3pte_pa(pte));
+
+		pr(", %s", (pte & LX_BLKPAG_UXN) ?
+		    "UXN" : "UX ");
+		pr(", %s", (pte & LX_BLKPAG_PXN) ?
+		   "PXN" :  "PX ");
+
+		if (pte & LX_BLKPAG_CONTIG)
+			pr(", CONTIG");
+
+		pr(", %s", (pte & LX_BLKPAG_NG) ? "NG" : "global");
+		pr(", %s", (pte & LX_BLKPAG_AF) ?
+		    "accessible" :
+		    "**fault** ");
+
+		switch (pte & LX_BLKPAG_SH) {
+		case LX_BLKPAG_SH_NS:
+			pr(", SH_NS");
+			break;
+		case LX_BLKPAG_SH_OS:
+			pr(", SH_OS");
+			break;
+		case LX_BLKPAG_SH_IS:
+			pr(", SH_IS");
+			break;
+		default:
+			pr(", SH_??");
+			break;
+		}
+
+		pr(", %s", (pte & LX_BLKPAG_AP_RO) ? "RO" : "RW");
+		pr(", %s", (pte & LX_BLKPAG_APUSER) ? "EL0" : "EL1");
+		pr(", %s", (pte & LX_BLKPAG_NS) ? "NS" : "secure");
+
+		switch (pte & LX_BLKPAG_ATTR_MASK) {
+		case LX_BLKPAG_ATTR_NORMAL_WB:
+			pr(", WB");
+			break;
+		case LX_BLKPAG_ATTR_NORMAL_NC:
+			pr(", NC");
+			break;
+		case LX_BLKPAG_ATTR_NORMAL_WT:
+			pr(", WT");
+			break;
+		case LX_BLKPAG_ATTR_DEVICE_MEM:
+			pr(", DEVICE");
+			break;
+		case LX_BLKPAG_ATTR_DEVICE_MEM_SO:
+			pr(", DEVICE(SO)");
+			break;
+		default:
+			pr(", ATTR(%lu)", __SHIFTOUT(pte, LX_BLKPAG_ATTR_INDX));
+			break;
+		}
+
+		if (pte & LX_BLKPAG_OS_BOOT)
+			pr(", boot");
+		if (pte & LX_BLKPAG_OS_READ)
+			pr(", pmap_read");
+		if (pte & LX_BLKPAG_OS_WRITE)
+			pr(", pmap_write");
+		if (pte & LX_BLKPAG_OS_WIRED)
+			pr(", wired");
+	} else {
+		pr(" **ILLEGAL TYPE**");
+	}
+	pr("\n");
+}
+
+void
+db_pteinfo(vaddr_t va, void (*pr)(const char *, ...) __printflike(1, 2))
+{
+	struct vm_page *pg;
+	bool user;
+	pd_entry_t *l0, *l1, *l2, *l3;
+	pd_entry_t pde;
+	pt_entry_t pte;
+	uint64_t ttbr;
+	paddr_t pa;
+	unsigned int idx;
+
+	switch (aarch64_addressspace(va)) {
+	case AARCH64_ADDRSPACE_UPPER:
+		user = false;
+		ttbr = reg_ttbr1_el1_read();
+		break;
+	case AARCH64_ADDRSPACE_LOWER:
+		user = true;
+		ttbr = reg_ttbr0_el1_read();
+		break;
+	default:
+		pr("illegal address space\n");
+		return;
+	}
+	pa = ttbr & TTBR_BADDR;
+	l0 = (pd_entry_t *)AARCH64_PA_TO_KVA(pa);
+
+	/*
+	 * traverse L0 -> L1 -> L2 -> L3 table
+	 */
+	pr("TTBR%d=%016"PRIx64", pa=%016"PRIxPADDR", va=%p",
+	    user ? 0 : 1, ttbr, pa, l0);
+	pr(", input-va=%016"PRIxVADDR
+	    ", L0-index=%ld, L1-index=%ld, L2-index=%ld, L3-index=%ld\n",
+	    va,
+	    (va & L0_ADDR_BITS) >> L0_SHIFT,
+	    (va & L1_ADDR_BITS) >> L1_SHIFT,
+	    (va & L2_ADDR_BITS) >> L2_SHIFT,
+	    (va & L3_ADDR_BITS) >> L3_SHIFT);
+
+	idx = l0pde_index(va);
+	pde = l0[idx];
+
+	pr("L0[%3d]=%016"PRIx64":", idx, pde);
+	db_pte_print(pde, 0, pr);
+
+	if (!l0pde_valid(pde))
+		return;
+
+	l1 = (pd_entry_t *)AARCH64_PA_TO_KVA(l0pde_pa(pde));
+	idx = l1pde_index(va);
+	pde = l1[idx];
+
+	pr(" L1[%3d]=%016"PRIx64":", idx, pde);
+	db_pte_print(pde, 1, pr);
+
+	if (!l1pde_valid(pde) || l1pde_is_block(pde))
+		return;
+
+	l2 = (pd_entry_t *)AARCH64_PA_TO_KVA(l1pde_pa(pde));
+	idx = l2pde_index(va);
+	pde = l2[idx];
+
+	pr("  L2[%3d]=%016"PRIx64":", idx, pde);
+	db_pte_print(pde, 2, pr);
+
+	if (!l2pde_valid(pde) || l2pde_is_block(pde))
+		return;
+
+	l3 = (pd_entry_t *)AARCH64_PA_TO_KVA(l2pde_pa(pde));
+	idx = l3pte_index(va);
+	pte = l3[idx];
+
+	pr("   L3[%3d]=%016"PRIx64":", idx, pte);
+	db_pte_print(pte, 3, pr);
+
+	pa = l3pte_pa(pte);
+	pg = PHYS_TO_VM_PAGE(pa);
+
+	if (pg != NULL) {
+		uvm_page_printit(pg, false, pr);
+
+		pmap_db_mdpg_print(pg, pr);
+	} else {
+#ifdef __HAVE_PMAP_PV_TRACK
+		if (pmap_pv_tracked(pa))
+			pr("PV tracked");
+		else
+			pr("No VM_PAGE or PV tracked");
+#else
+		pr("no VM_PAGE\n");
+#endif
+	}
+}
+
+static void
+dump_ln_table(bool countmode, pd_entry_t *pdp, int level, int lnindex,
+    vaddr_t va, void (*pr)(const char *, ...) __printflike(1, 2))
+{
+	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)
+					db_pte_print(pde, level, pr);
+			} else if ((level != 3) && l1pde_is_table(pde)) {
+				if (!countmode)
+					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)
+					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
+db_dump_l0table(bool countmode, pd_entry_t *pdp, vaddr_t va_base,
+    void (*pr)(const char *, ...) __printflike(1, 2))
+{
+	dump_ln_table(countmode, pdp, 0, 0, va_base, pr);
+}
+
+void
+db_ttbrdump(bool countmode, vaddr_t va,
+    void (*pr)(const char *, ...) __printflike(1, 2))
+{
+	struct pmap *pm, _pm;
+
+	pm = (struct pmap *)va;
+	db_read_bytes((db_addr_t)va, sizeof(_pm), (char *)&_pm);
+
+	pr("pmap=%p\n", pm);
+	pmap_db_pmap_print(&_pm, pr);
+
+	db_dump_l0table(countmode, pmap_l0table(pm),
+	    (pm == pmap_kernel()) ? 0xffff000000000000UL : 0, pr);
+}

Index: src/sys/arch/aarch64/aarch64/db_machdep.c
diff -u src/sys/arch/aarch64/aarch64/db_machdep.c:1.39 src/sys/arch/aarch64/aarch64/db_machdep.c:1.40
--- src/sys/arch/aarch64/aarch64/db_machdep.c:1.39	Thu Mar 11 10:34:34 2021
+++ src/sys/arch/aarch64/aarch64/db_machdep.c	Fri Apr 30 20:07:22 2021
@@ -1,4 +1,4 @@
-/* $NetBSD: db_machdep.c,v 1.39 2021/03/11 10:34:34 ryo Exp $ */
+/* $NetBSD: db_machdep.c,v 1.40 2021/04/30 20:07:22 skrll 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.39 2021/03/11 10:34:34 ryo Exp $");
+__KERNEL_RCSID(0, "$NetBSD: db_machdep.c,v 1.40 2021/04/30 20:07:22 skrll Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_compat_netbsd32.h"
@@ -492,7 +492,7 @@ db_md_pte_cmd(db_expr_t addr, bool have_
 	db_printf("Stage1 EL1 translation %016llx -> PAR_EL1 = ", addr);
 	db_par_print(par, addr);
 
-	pmap_db_pteinfo(addr, db_printf);
+	db_pteinfo(addr, db_printf);
 }
 
 void
@@ -553,7 +553,7 @@ db_md_ttbr_cmd(db_expr_t addr, bool have
 		addr = (db_addr_t)p->p_vmspace->vm_map.pmap;
 	}
 
-	pmap_db_ttbrdump(countmode, addr, db_printf);
+	db_ttbrdump(countmode, addr, db_printf);
 }
 
 void

Index: src/sys/arch/aarch64/aarch64/pmap.c
diff -u src/sys/arch/aarch64/aarch64/pmap.c:1.106 src/sys/arch/aarch64/aarch64/pmap.c:1.107
--- src/sys/arch/aarch64/aarch64/pmap.c:1.106	Thu Apr 29 09:27:29 2021
+++ src/sys/arch/aarch64/aarch64/pmap.c	Fri Apr 30 20:07:22 2021
@@ -1,4 +1,4 @@
-/*	$NetBSD: pmap.c,v 1.106 2021/04/29 09:27:29 skrll Exp $	*/
+/*	$NetBSD: pmap.c,v 1.107 2021/04/30 20:07:22 skrll Exp $	*/
 
 /*
  * Copyright (c) 2017 Ryo Shimizu <r...@nerv.org>
@@ -27,7 +27,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: pmap.c,v 1.106 2021/04/29 09:27:29 skrll Exp $");
+__KERNEL_RCSID(0, "$NetBSD: pmap.c,v 1.107 2021/04/30 20:07:22 skrll Exp $");
 
 #include "opt_arm_debug.h"
 #include "opt_ddb.h"
@@ -536,6 +536,13 @@ _pmap_pv_ctor(void *arg, void *v, int fl
 	return 0;
 }
 
+pd_entry_t *
+pmap_l0table(struct pmap *pm)
+{
+
+	return pm->pm_l0table;
+}
+
 void
 pmap_init(void)
 {
@@ -1153,23 +1160,10 @@ str_vmflags(uint32_t flags)
 	return p;
 }
 
-static void
-pg_dump(struct vm_page *pg, void (*pr)(const char *, ...) __printflike(1, 2))
-{
-	pr("pg=%p\n", pg);
-	pr(" pg->uanon   = %p\n", pg->uanon);
-	pr(" pg->uobject = %p\n", pg->uobject);
-	pr(" pg->offset  = %zu\n", pg->offset);
-	pr(" pg->flags      = %u\n", pg->flags);
-	pr(" pg->loan_count = %u\n", pg->loan_count);
-	pr(" pg->wire_count = %u\n", pg->wire_count);
-	pr(" pg->pqflags    = %u\n", pg->pqflags);
-	pr(" pg->phys_addr  = %016lx\n", VM_PAGE_TO_PHYS(pg));
-}
-
-static void
-pv_dump(struct pmap_page *pp, void (*pr)(const char *, ...) __printflike(1, 2))
+void
+pmap_db_mdpg_print(struct vm_page *pg, void (*pr)(const char *, ...) __printflike(1, 2))
 {
+	struct pmap_page *pp = VM_PAGE_TO_PP(pg);
 	struct pv_entry *pv;
 	int i, flags;
 
@@ -2642,353 +2636,15 @@ kvtopte(vaddr_t va)
 
 #ifdef DDB
 
-/* change attribute of kernel segment */
-pt_entry_t
-pmap_kvattr(vaddr_t va, vm_prot_t prot)
-{
-	pt_entry_t *ptep, pte, opte;
-
-	KASSERT(IN_RANGE(va, VM_MIN_KERNEL_ADDRESS, VM_MAX_KERNEL_ADDRESS));
-
-	ptep = kvtopte(va);
-	if (ptep == NULL)
-		panic("%s: %016lx is not mapped\n", __func__, va);
-
-	opte = pte = *ptep;
-
-	pte &= ~(LX_BLKPAG_AF|LX_BLKPAG_AP);
-	switch (prot & (VM_PROT_READ|VM_PROT_WRITE)) {
-	case 0:
-		break;
-	case VM_PROT_READ:
-		pte |= (LX_BLKPAG_AF|LX_BLKPAG_AP_RO);
-		break;
-	case VM_PROT_WRITE:
-	case VM_PROT_READ|VM_PROT_WRITE:
-		pte |= (LX_BLKPAG_AF|LX_BLKPAG_AP_RW);
-		break;
-	}
-
-	if ((prot & VM_PROT_EXECUTE) == 0) {
-		pte |= LX_BLKPAG_PXN;
-	} else {
-		pte |= LX_BLKPAG_AF;
-		pte &= ~LX_BLKPAG_PXN;
-	}
-
-	*ptep = pte;
-
-	return opte;
-}
-
-void
-pmap_db_pte_print(pt_entry_t pte, int level,
-    void (*pr)(const char *, ...) __printflike(1, 2))
-{
-	if (pte == 0) {
-		pr(" UNUSED\n");
-		return;
-	}
-
-	pr(" %s", (pte & LX_VALID) ? "VALID" : "**INVALID**");
-
-	if ((level == 0) ||
-	    ((level == 1) && l1pde_is_table(pte)) ||
-	    ((level == 2) && l2pde_is_table(pte))) {
-
-		/* L0/L1/L2 TABLE */
-		if ((level == 0) && ((pte & LX_TYPE) != LX_TYPE_TBL))
-			pr(" **ILLEGAL TYPE**"); /* L0 doesn't support block */
-		else
-			pr(" L%d-TABLE", level);
-
-		pr(", PA=%lx", l0pde_pa(pte));
-
-		if (pte & LX_TBL_NSTABLE)
-			pr(", NSTABLE");
-		if (pte & LX_TBL_APTABLE)
-			pr(", APTABLE");
-		if (pte & LX_TBL_UXNTABLE)
-			pr(", UXNTABLE");
-		if (pte & LX_TBL_PXNTABLE)
-			pr(", PXNTABLE");
-
-	} else if (((level == 1) && l1pde_is_block(pte)) ||
-	    ((level == 2) && l2pde_is_block(pte)) ||
-	    (level == 3)) {
-
-		/* L1/L2 BLOCK or L3 PAGE */
-		switch (level) {
-		case 1:
-			pr(" L1(1G)-BLOCK");
-			break;
-		case 2:
-			pr(" L2(2M)-BLOCK");
-			break;
-		case 3:
-			pr(" %s", l3pte_is_page(pte) ?
-			    "L3(4K)-PAGE" : "**ILLEGAL TYPE**");
-			break;
-		}
-
-		pr(", PA=%lx", l3pte_pa(pte));
-
-		pr(", %s", (pte & LX_BLKPAG_UXN) ?
-		    "UXN" : "UX ");
-		pr(", %s", (pte & LX_BLKPAG_PXN) ?
-		   "PXN" :  "PX ");
-
-		if (pte & LX_BLKPAG_CONTIG)
-			pr(", CONTIG");
-
-		pr(", %s", (pte & LX_BLKPAG_NG) ? "NG" : "global");
-		pr(", %s", (pte & LX_BLKPAG_AF) ?
-		    "accessible" :
-		    "**fault** ");
-
-		switch (pte & LX_BLKPAG_SH) {
-		case LX_BLKPAG_SH_NS:
-			pr(", SH_NS");
-			break;
-		case LX_BLKPAG_SH_OS:
-			pr(", SH_OS");
-			break;
-		case LX_BLKPAG_SH_IS:
-			pr(", SH_IS");
-			break;
-		default:
-			pr(", SH_??");
-			break;
-		}
-
-		pr(", %s", (pte & LX_BLKPAG_AP_RO) ? "RO" : "RW");
-		pr(", %s", (pte & LX_BLKPAG_APUSER) ? "EL0" : "EL1");
-		pr(", %s", (pte & LX_BLKPAG_NS) ? "NS" : "secure");
-
-		switch (pte & LX_BLKPAG_ATTR_MASK) {
-		case LX_BLKPAG_ATTR_NORMAL_WB:
-			pr(", WB");
-			break;
-		case LX_BLKPAG_ATTR_NORMAL_NC:
-			pr(", NC");
-			break;
-		case LX_BLKPAG_ATTR_NORMAL_WT:
-			pr(", WT");
-			break;
-		case LX_BLKPAG_ATTR_DEVICE_MEM:
-			pr(", DEVICE");
-			break;
-		case LX_BLKPAG_ATTR_DEVICE_MEM_SO:
-			pr(", DEVICE(SO)");
-			break;
-		default:
-			pr(", ATTR(%lu)", __SHIFTOUT(pte, LX_BLKPAG_ATTR_INDX));
-			break;
-		}
-
-		if (pte & LX_BLKPAG_OS_BOOT)
-			pr(", boot");
-		if (pte & LX_BLKPAG_OS_READ)
-			pr(", pmap_read");
-		if (pte & LX_BLKPAG_OS_WRITE)
-			pr(", pmap_write");
-		if (pte & LX_BLKPAG_OS_WIRED)
-			pr(", wired");
-	} else {
-		pr(" **ILLEGAL TYPE**");
-	}
-	pr("\n");
-}
-
-void
-pmap_db_pteinfo(vaddr_t va, void (*pr)(const char *, ...) __printflike(1, 2))
-{
-	struct vm_page *pg;
-	struct pmap_page *pp;
-	bool user;
-	pd_entry_t *l0, *l1, *l2, *l3;
-	pd_entry_t pde;
-	pt_entry_t pte;
-	uint64_t ttbr;
-	paddr_t pa;
-	unsigned int idx;
-
-	switch (aarch64_addressspace(va)) {
-	case AARCH64_ADDRSPACE_UPPER:
-		user = false;
-		ttbr = reg_ttbr1_el1_read();
-		break;
-	case AARCH64_ADDRSPACE_LOWER:
-		user = true;
-		ttbr = reg_ttbr0_el1_read();
-		break;
-	default:
-		pr("illegal address space\n");
-		return;
-	}
-	pa = ttbr & TTBR_BADDR;
-	l0 = (pd_entry_t *)AARCH64_PA_TO_KVA(pa);
-
-	/*
-	 * traverse L0 -> L1 -> L2 -> L3 table
-	 */
-	pr("TTBR%d=%016"PRIx64", pa=%016"PRIxPADDR", va=%p",
-	    user ? 0 : 1, ttbr, pa, l0);
-	pr(", input-va=%016"PRIxVADDR
-	    ", L0-index=%ld, L1-index=%ld, L2-index=%ld, L3-index=%ld\n",
-	    va,
-	    (va & L0_ADDR_BITS) >> L0_SHIFT,
-	    (va & L1_ADDR_BITS) >> L1_SHIFT,
-	    (va & L2_ADDR_BITS) >> L2_SHIFT,
-	    (va & L3_ADDR_BITS) >> L3_SHIFT);
-
-	idx = l0pde_index(va);
-	pde = l0[idx];
-
-	pr("L0[%3d]=%016"PRIx64":", idx, pde);
-	pmap_db_pte_print(pde, 0, pr);
-
-	if (!l0pde_valid(pde))
-		return;
-
-	l1 = (pd_entry_t *)AARCH64_PA_TO_KVA(l0pde_pa(pde));
-	idx = l1pde_index(va);
-	pde = l1[idx];
-
-	pr(" L1[%3d]=%016"PRIx64":", idx, pde);
-	pmap_db_pte_print(pde, 1, pr);
-
-	if (!l1pde_valid(pde) || l1pde_is_block(pde))
-		return;
-
-	l2 = (pd_entry_t *)AARCH64_PA_TO_KVA(l1pde_pa(pde));
-	idx = l2pde_index(va);
-	pde = l2[idx];
-
-	pr("  L2[%3d]=%016"PRIx64":", idx, pde);
-	pmap_db_pte_print(pde, 2, pr);
-
-	if (!l2pde_valid(pde) || l2pde_is_block(pde))
-		return;
-
-	l3 = (pd_entry_t *)AARCH64_PA_TO_KVA(l2pde_pa(pde));
-	idx = l3pte_index(va);
-	pte = l3[idx];
-
-	pr("   L3[%3d]=%016"PRIx64":", idx, pte);
-	pmap_db_pte_print(pte, 3, pr);
-
-	pa = l3pte_pa(pte);
-	pg = PHYS_TO_VM_PAGE(pa);
-	pp = phys_to_pp(pa);
-	if (pp == NULL) {
-		pr("No VM_PAGE nor PMAP_PAGE\n");
-	} else {
-		if (pg != NULL)
-			pg_dump(pg, pr);
-		else
-			pr("no VM_PAGE. pv-tracked page?\n");
-		pv_dump(pp, pr);
-	}
-}
-
-static void
-dump_ln_table(bool countmode, pd_entry_t *pdp, int level, int lnindex,
-    vaddr_t va, void (*pr)(const char *, ...) __printflike(1, 2))
-{
-	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 *, ...) __printflike(1, 2))
-{
-	dump_ln_table(countmode, pdp, 0, 0, va_base, pr);
-}
-
 void
-pmap_db_ttbrdump(bool countmode, vaddr_t va,
+pmap_db_pmap_print(struct pmap *pm,
     void (*pr)(const char *, ...) __printflike(1, 2))
 {
-	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);
+	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);
 }
-
 #endif /* DDB */
+

Index: src/sys/arch/aarch64/aarch64/pmapboot.c
diff -u src/sys/arch/aarch64/aarch64/pmapboot.c:1.16 src/sys/arch/aarch64/aarch64/pmapboot.c:1.17
--- src/sys/arch/aarch64/aarch64/pmapboot.c:1.16	Sat Mar 20 14:30:50 2021
+++ src/sys/arch/aarch64/aarch64/pmapboot.c	Fri Apr 30 20:07:22 2021
@@ -1,4 +1,4 @@
-/*	$NetBSD: pmapboot.c,v 1.16 2021/03/20 14:30:50 skrll Exp $	*/
+/*	$NetBSD: pmapboot.c,v 1.17 2021/04/30 20:07:22 skrll Exp $	*/
 
 /*
  * Copyright (c) 2018 Ryo Shimizu <r...@nerv.org>
@@ -27,7 +27,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: pmapboot.c,v 1.16 2021/03/20 14:30:50 skrll Exp $");
+__KERNEL_RCSID(0, "$NetBSD: pmapboot.c,v 1.17 2021/04/30 20:07:22 skrll Exp $");
 
 #include "opt_arm_debug.h"
 #include "opt_ddb.h"
@@ -162,7 +162,7 @@ pmapboot_pte_print(pt_entry_t pte, int l
     void (*pr)(const char *, ...) __printflike(1, 2))
 {
 #ifdef DDB
-	pmap_db_pte_print(pte, level, pr);
+	db_pmap_pte_print(pte, level, pr);
 #else
 	__USE(level);
 	pr(" %s PA=%016lx\n",

Index: src/sys/arch/aarch64/include/db_machdep.h
diff -u src/sys/arch/aarch64/include/db_machdep.h:1.13 src/sys/arch/aarch64/include/db_machdep.h:1.14
--- src/sys/arch/aarch64/include/db_machdep.h:1.13	Thu Mar 11 09:48:40 2021
+++ src/sys/arch/aarch64/include/db_machdep.h	Fri Apr 30 20:07:23 2021
@@ -1,4 +1,4 @@
-/* $NetBSD: db_machdep.h,v 1.13 2021/03/11 09:48:40 ryo Exp $ */
+/* $NetBSD: db_machdep.h,v 1.14 2021/04/30 20:07:23 skrll Exp $ */
 
 /*-
  * Copyright (c) 2014 The NetBSD Foundation, Inc.
@@ -67,7 +67,12 @@
 #ifdef __aarch64__
 
 #include <sys/types.h>
+
+#include <uvm/uvm.h>
+
 #include <aarch64/frame.h>
+#include <aarch64/pmap.h>
+
 #include <ddb/db_user.h>
 
 typedef long long int db_expr_t;
@@ -211,8 +216,16 @@ db_addr_t db_branch_taken(db_expr_t, db_
 #endif /* SOFTWARE_SSTEP */
 
 #define DB_MACHINE_COMMANDS
-void dump_trapframe(struct trapframe *, void (*)(const char *, ...));
-void dump_switchframe(struct trapframe *, void (*)(const char *, ...));
+
+#ifdef _KERNEL
+void db_pteinfo(vaddr_t, void (*)(const char *, ...) __printflike(1, 2));
+void db_pte_print(pt_entry_t, int, void (*)(const char *, ...) __printflike(1, 2));
+void db_ttbrdump(bool, vaddr_t, void (*pr)(const char *, ...) __printflike(1, 2));
+#endif
+
+void dump_trapframe(struct trapframe *, void (*)(const char *, ...) __printflike(1, 2));
+
+void dump_switchframe(struct trapframe *, void (*)(const char *, ...) __printflike(1, 2));
 const char *strdisasm(vaddr_t, uint64_t);
 void db_machdep_init(void);
 

Index: src/sys/arch/aarch64/include/pmap.h
diff -u src/sys/arch/aarch64/include/pmap.h:1.46 src/sys/arch/aarch64/include/pmap.h:1.47
--- src/sys/arch/aarch64/include/pmap.h:1.46	Sat Mar 20 14:30:50 2021
+++ src/sys/arch/aarch64/include/pmap.h	Fri Apr 30 20:07:23 2021
@@ -1,4 +1,4 @@
-/* $NetBSD: pmap.h,v 1.46 2021/03/20 14:30:50 skrll Exp $ */
+/* $NetBSD: pmap.h,v 1.47 2021/04/30 20:07:23 skrll Exp $ */
 
 /*-
  * Copyright (c) 2014 The NetBSD Foundation, Inc.
@@ -172,11 +172,43 @@ void pmap_bootstrap(vaddr_t, vaddr_t);
 bool pmap_fault_fixup(struct pmap *, vaddr_t, vm_prot_t, bool user);
 
 /* 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);
+void pmap_db_pmap_print(struct pmap *, void (*)(const char *, ...) __printflike(1, 2));
+void pmap_db_mdpg_print(struct vm_page *, void (*)(const char *, ...) __printflike(1, 2));
+
+pd_entry_t *pmap_l0table(struct pmap *);
+
+/* change attribute of kernel segment */
+static inline pt_entry_t
+pmap_kvattr(pt_entry_t *ptep, vm_prot_t prot)
+{
+	pt_entry_t pte = *ptep;
+	const pt_entry_t opte = pte;
+
+	pte &= ~(LX_BLKPAG_AF|LX_BLKPAG_AP);
+	switch (prot & (VM_PROT_READ|VM_PROT_WRITE)) {
+	case 0:
+		break;
+	case VM_PROT_READ:
+		pte |= (LX_BLKPAG_AF|LX_BLKPAG_AP_RO);
+		break;
+	case VM_PROT_WRITE:
+	case VM_PROT_READ|VM_PROT_WRITE:
+		pte |= (LX_BLKPAG_AF|LX_BLKPAG_AP_RW);
+		break;
+	}
+
+	if ((prot & VM_PROT_EXECUTE) == 0) {
+		pte |= LX_BLKPAG_PXN;
+	} else {
+		pte |= LX_BLKPAG_AF;
+		pte &= ~LX_BLKPAG_PXN;
+	}
+
+	*ptep = pte;
+
+	return opte;
+}
 
 /* pmapboot.c */
 pd_entry_t *pmapboot_pagealloc(void);
@@ -185,15 +217,12 @@ void pmapboot_enter(vaddr_t, paddr_t, ps
 void pmapboot_enter_range(vaddr_t, paddr_t, psize_t, pt_entry_t,
     void (*)(const char *, ...) __printflike(1, 2));
 int pmapboot_protect(vaddr_t, vaddr_t, vm_prot_t);
-void pmap_db_pte_print(pt_entry_t, int,
-    void (*pr)(const char *, ...) __printflike(1, 2));
 
 /* Hooks for the pool allocator */
 paddr_t vtophys(vaddr_t);
 #define VTOPHYS_FAILED		((paddr_t)-1L)	/* POOL_PADDR_INVALID */
 #define POOL_VTOPHYS(va)	vtophys((vaddr_t) (va))
 
-
 /* devmap */
 struct pmap_devmap {
 	vaddr_t pd_va;		/* virtual address */

Reply via email to