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/ce2d7e368c3f
branches: trunk
changeset: 983042:ce2d7e368c3f
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 2968819f7473 -r ce2d7e368c3f 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 @@
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 @@
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 @@
* 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 @@
/* 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 @@
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