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 */