Implement db_write_text/bytes() which add support for ddb(4)'s breakpoints.
authormpi <mpi@openbsd.org>
Mon, 7 Nov 2022 09:43:04 +0000 (09:43 +0000)
committermpi <mpi@openbsd.org>
Mon, 7 Nov 2022 09:43:04 +0000 (09:43 +0000)
Based on a diff from gerhard@, ok kettenis@

sys/arch/arm64/arm64/db_interface.c
sys/arch/arm64/arm64/pmap.c
sys/arch/arm64/arm64/trap.c
sys/arch/arm64/include/pmap.h

index 0d9c43b..7b2a14e 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: db_interface.c,v 1.13 2022/10/15 08:04:02 jsg Exp $   */
+/*     $OpenBSD: db_interface.c,v 1.14 2022/11/07 09:43:04 mpi Exp $   */
 /*     $NetBSD: db_interface.c,v 1.34 2003/10/26 23:11:15 chris Exp $  */
 
 /*
 /*
  * Interface to new debugger.
  */
+
 #include <sys/param.h>
 #include <sys/proc.h>
 #include <sys/reboot.h>
-#include <sys/systm.h> /* just for boothowto */
-#include <sys/exec.h>
+#include <sys/systm.h>
 #include <sys/mutex.h>
 
 #include <uvm/uvm_extern.h>
 
-#include <arm64/db_machdep.h>
+#include <dev/cons.h>
+
+#include <machine/cpufunc.h>
+#include <machine/db_machdep.h>
 #include <machine/pmap.h>
-#include <ddb/db_access.h>
+
+#include <ddb/db_sym.h>
 #include <ddb/db_command.h>
+#include <ddb/db_extern.h>
 #include <ddb/db_output.h>
 #include <ddb/db_run.h>
 #include <ddb/db_variables.h>
-#include <ddb/db_sym.h>
-#include <ddb/db_extern.h>
-#include <ddb/db_interface.h>
-#include <dev/cons.h>
 
-//static long nil;
 
 int db_access_und_sp (struct db_variable *, db_expr_t *, int);
 int db_access_abt_sp (struct db_variable *, db_expr_t *, int);
@@ -230,14 +230,48 @@ db_read_bytes(vaddr_t addr, size_t size, char *data)
        }
 }
 
-#if 0
+/*
+ * Write bytes somewhere in the kernel text.  Make the text
+ * pages writable temporarily.
+ */
 static void
 db_write_text(vaddr_t addr, size_t size, char *data)
 {
-       // Implement
-       return ;
+       vaddr_t pgva;
+       size_t limit;
+       char *dst;
+
+       if (size == 0)
+               return;
+
+       dst = (char *)addr;
+
+       do {
+               /*
+                * Get the VA for the page.
+                */
+               pgva = trunc_page((vaddr_t)dst);
+
+               /*
+                * Compute number of bytes that can be written
+                * with this mapping and subtract it from the
+                * total size.
+                */
+               limit = PAGE_SIZE - ((vaddr_t)dst & PGOFSET);
+               if (limit > size)
+                       limit = size;
+               size -= limit;
+
+               pmap_page_rw(pmap_kernel(), pgva);
+
+               for (; limit > 0; limit--)
+                       *dst++ = *data++;
+
+               /* Restore protection */
+               pmap_page_ro(pmap_kernel(), pgva, PROT_READ|PROT_EXEC);
+
+       } while (size != 0);
 }
-#endif
 
 /*
  * Write bytes to kernel address space for debugger.
@@ -245,14 +279,12 @@ db_write_text(vaddr_t addr, size_t size, char *data)
 void
 db_write_bytes(vaddr_t addr, size_t size, char *data)
 {
-#if 0
        extern char etext[];
-       extern char kernel_text[];
        char *dst;
        size_t loop;
 
        /* If any part is in kernel text, use db_write_text() */
-       if (addr >= (vaddr_t) kernel_text && addr < (vaddr_t) etext) {
+       if (addr >= KERNBASE && addr < (vaddr_t)&etext) {
                db_write_text(addr, size, data);
                return;
        }
@@ -270,9 +302,7 @@ db_write_bytes(vaddr_t addr, size_t size, char *data)
        cpu_icache_sync_range(addr, size);
 
        /* In case the current page tables have been modified ... */
-       cpu_tlb_flushID();
-       cpu_cpwait();
-#endif
+       cpu_tlb_flush();
 }
 
 void
index 49a6308..abe0b61 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: pmap.c,v 1.85 2022/09/10 20:35:28 miod Exp $ */
+/* $OpenBSD: pmap.c,v 1.86 2022/11/07 09:43:04 mpi Exp $ */
 /*
  * Copyright (c) 2008-2009,2014-2016 Dale Rahn <drahn@dalerahn.com>
  *
@@ -1540,6 +1540,26 @@ pmap_page_ro(pmap_t pm, vaddr_t va, vm_prot_t prot)
        ttlb_flush(pm, pted->pted_va & ~PAGE_MASK);
 }
 
+#ifdef DDB
+void
+pmap_page_rw(pmap_t pm, vaddr_t va)
+{
+       struct pte_desc *pted;
+       uint64_t *pl3;
+
+       /* Every VA needs a pted, even unmanaged ones. */
+       pted = pmap_vp_lookup(pm, va, &pl3);
+       if (!pted || !PTED_VALID(pted)) {
+               return;
+       }
+
+       pted->pted_va |= PROT_WRITE;
+       pted->pted_pte |= PROT_WRITE;
+       pmap_pte_update(pted, pl3);
+       ttlb_flush(pm, pted->pted_va & ~PAGE_MASK);
+}
+#endif /* DDB */
+
 /*
  * Lower the protection on the specified physical page.
  *
index 1932e38..4d089fc 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: trap.c,v 1.41 2022/11/06 11:44:30 kettenis Exp $ */
+/* $OpenBSD: trap.c,v 1.42 2022/11/07 09:43:04 mpi Exp $ */
 /*-
  * Copyright (c) 2014 Andrew Turner
  * All rights reserved.
@@ -243,6 +243,7 @@ do_el1h_sync(struct trapframe *frame)
                /* XXX */
                int db_trapper (u_int, u_int, trapframe_t *, int);
                db_trapper(frame->tf_elr, 0/*XXX*/, frame, exception);
+               break;
                }
 #endif
                panic("Unknown kernel exception %x esr_el1 %llx lr %lxpc %lx",
index 5a65528..73ce53b 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: pmap.h,v 1.19 2022/02/04 18:15:40 kettenis Exp $ */
+/* $OpenBSD: pmap.h,v 1.20 2022/11/07 09:43:04 mpi Exp $ */
 /*
  * Copyright (c) 2008,2009,2014 Dale Rahn <drahn@dalerahn.com>
  *
@@ -97,6 +97,7 @@ vaddr_t pmap_bootstrap(long kvo, paddr_t lpt1,  long kernelstart,
     long kernelend, long ram_start, long ram_end);
 void pmap_kenter_cache(vaddr_t va, paddr_t pa, vm_prot_t prot, int cacheable);
 void pmap_page_ro(pmap_t pm, vaddr_t va, vm_prot_t prot);
+void pmap_page_rw(pmap_t pm, vaddr_t va);
 
 paddr_t pmap_steal_avail(size_t size, int align, void **kva);
 void pmap_avail_fixup(void);