1/* $OpenBSD: db_memrw.c,v 1.19 2024/02/23 18:19:03 cheloha Exp $ */ 2/* $NetBSD: db_memrw.c,v 1.6 1999/04/12 20:38:19 pk Exp $ */ 3 4/* 5 * Mach Operating System 6 * Copyright (c) 1991,1990 Carnegie Mellon University 7 * All Rights Reserved. 8 * 9 * Permission to use, copy, modify and distribute this software and its 10 * documentation is hereby granted, provided that both the copyright 11 * notice and this permission notice appear in all copies of the 12 * software, derivative works or modified versions, and any portions 13 * thereof, and that both notices appear in supporting documentation. 14 * 15 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" 16 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR 17 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. 18 * 19 * Carnegie Mellon requests users of this software to return to 20 * 21 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU 22 * School of Computer Science 23 * Carnegie Mellon University 24 * Pittsburgh PA 15213-3890 25 * 26 * any improvements or extensions that they make and grant Carnegie Mellon 27 * the rights to redistribute these changes. 28 * 29 * db_interface.c,v 2.4 1991/02/05 17:11:13 mrt (CMU) 30 */ 31 32/* 33 * Routines to read and write memory on behalf of the debugger, used 34 * by DDB. 35 */ 36 37#include <sys/param.h> 38#include <sys/systm.h> 39 40#include <uvm/uvm_extern.h> 41 42#include <machine/db_machdep.h> 43 44#include <ddb/db_access.h> 45 46#define PG_LGFRAME 0xffc00000 /* large (4M) page frame mask */ 47#define PG_LGFRAME_PAE 0xffe00000 /* large (2M) page frame mask */ 48 49/* 50 * Read bytes from kernel address space for debugger. 51 */ 52void 53db_read_bytes(vaddr_t addr, size_t size, void *datap) 54{ 55 char *data = datap, *src; 56 57 src = (char *)addr; 58 while (size-- > 0) 59 *data++ = *src++; 60} 61 62/* 63 * Write bytes somewhere in the kernel text. Make the text 64 * pages writable temporarily. 65 */ 66static void 67db_write_text(vaddr_t addr, size_t size, char *data) 68{ 69 vaddr_t pgva; 70 size_t limit; 71 uint32_t bits; 72 char *dst; 73 74 if (size == 0) 75 return; 76 77 dst = (char *)addr; 78 79 do { 80 /* 81 * Get the PTE for the page. 82 */ 83 bits = pmap_pte_bits(addr); 84 85 if ((bits & PG_V) == 0) { 86 printf(" address %p not a valid page\n", dst); 87 return; 88 } 89 90 /* 91 * Get the VA for the page. 92 */ 93 if (bits & PG_PS) { 94 if (cpu_pae) 95 pgva = (vaddr_t)dst & PG_LGFRAME_PAE; 96 else 97 pgva = (vaddr_t)dst & PG_LGFRAME; 98 } else 99 pgva = trunc_page((vaddr_t)dst); 100 101 /* 102 * Compute number of bytes that can be written 103 * with this mapping and subtract it from the 104 * total size. 105 */ 106#ifdef NBPD_L2 107 if (bits & PG_PS) 108 limit = NBPD_L2 - ((vaddr_t)dst & (NBPD_L2 - 1)); 109 else 110#endif 111 limit = PAGE_SIZE - ((vaddr_t)dst & PGOFSET); 112 if (limit > size) 113 limit = size; 114 size -= limit; 115 116 pmap_update_pg(pgva); 117 pmap_pte_setbits(addr, PG_RW, 0); 118 119 /* 120 * Page is now writable. Do as much access as we 121 * can in this page. 122 */ 123 for (; limit > 0; limit--) 124 *dst++ = *data++; 125 126 /* 127 * Restore the old PTE. 128 */ 129 pmap_update_pg(pgva); 130 pmap_pte_setbits(addr, bits, PG_RW); 131 132 } while (size != 0); 133} 134 135/* 136 * Write bytes to kernel address space for debugger. 137 */ 138void 139db_write_bytes(vaddr_t addr, size_t size, void *datap) 140{ 141 char *data = datap, *dst; 142 extern char etext; 143 144 if (addr >= VM_MIN_KERNEL_ADDRESS && 145 addr < (vaddr_t)&etext) { 146 db_write_text(addr, size, data); 147 return; 148 } 149 150 dst = (char *)addr; 151 152 while (size-- > 0) 153 *dst++ = *data++; 154} 155