Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/arch/aarch64 Make the ddb for pmap / pte information pma...



details:   https://anonhg.NetBSD.org/src/rev/4c01612465b7
branches:  trunk
changeset: 378941:4c01612465b7
user:      skrll <skrll%NetBSD.org@localhost>
date:      Fri Apr 30 20:07:22 2021 +0000

description:
Make the ddb for pmap / pte information pmap agnostic

diffstat:

 sys/arch/aarch64/aarch64/db_interface.c |  351 ++++++++++++++++++++++++++++-
 sys/arch/aarch64/aarch64/db_machdep.c   |    8 +-
 sys/arch/aarch64/aarch64/pmap.c         |  382 +------------------------------
 sys/arch/aarch64/aarch64/pmapboot.c     |    6 +-
 sys/arch/aarch64/include/db_machdep.h   |   19 +-
 sys/arch/aarch64/include/pmap.h         |   45 +++-
 6 files changed, 418 insertions(+), 393 deletions(-)

diffs (truncated from 1018 to 300 lines):

diff -r 2191ced93e1d -r 4c01612465b7 sys/arch/aarch64/aarch64/db_interface.c
--- a/sys/arch/aarch64/aarch64/db_interface.c   Fri Apr 30 19:46:24 2021 +0000
+++ b/sys/arch/aarch64/aarch64/db_interface.c   Fri Apr 30 20:07:22 2021 +0000
@@ -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 <ryo%nerv.org@localhost>
@@ -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 @@
 
 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;



Home | Main Index | Thread Index | Old Index