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 <[email protected]>
@@ -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 <[email protected]>
@@ -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 <[email protected]>
@@ -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 */