db_memrw.c revision 1.14
1/* $OpenBSD: db_memrw.c,v 1.14 2014/09/14 14:17:23 jsg 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 and KGDB. 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/* 47 * Read bytes from kernel address space for debugger. 48 */ 49void 50db_read_bytes(vaddr_t addr, size_t size, char *data) 51{ 52 char *src; 53 54 src = (char *)addr; 55 while (size-- > 0) 56 *data++ = *src++; 57} 58 59/* 60 * Write bytes somewhere in the kernel text. Make the text 61 * pages writable temporarily. 62 */ 63static void 64db_write_text(vaddr_t addr, size_t size, char *data) 65{ 66 pt_entry_t *pte, oldpte, tmppte; 67 vaddr_t pgva; 68 size_t limit; 69 char *dst; 70 71 if (size == 0) 72 return; 73 74 dst = (char *)addr; 75 76 do { 77 /* 78 * Get the PTE for the page. 79 */ 80 pte = kvtopte(addr); 81 oldpte = *pte; 82 83 if ((oldpte & PG_V) == 0) { 84 printf(" address %p not a valid page\n", dst); 85 return; 86 } 87 88 /* 89 * Get the VA for the page. 90 */ 91 if (oldpte & PG_PS) 92 pgva = (vaddr_t)dst & PG_LGFRAME; 93 else 94 pgva = trunc_page((vaddr_t)dst); 95 96 /* 97 * Compute number of bytes that can be written 98 * with this mapping and subtract it from the 99 * total size. 100 */ 101#ifdef NBPD_L2 102 if (oldpte & PG_PS) 103 limit = NBPD_L2 - ((vaddr_t)dst & (NBPD_L2 - 1)); 104 else 105#endif 106 limit = PAGE_SIZE - ((vaddr_t)dst & PGOFSET); 107 if (limit > size) 108 limit = size; 109 size -= limit; 110 111 tmppte = (oldpte & ~PG_KR) | PG_KW; 112 *pte = tmppte; 113 pmap_update_pg(pgva); 114 115 /* 116 * Page is now writable. Do as much access as we 117 * can in this page. 118 */ 119 for (; limit > 0; limit--) 120 *dst++ = *data++; 121 122 /* 123 * Restore the old PTE. 124 */ 125 *pte = oldpte; 126 127 pmap_update_pg(pgva); 128 129 } while (size != 0); 130} 131 132/* 133 * Write bytes to kernel address space for debugger. 134 */ 135void 136db_write_bytes(vaddr_t addr, size_t size, char *data) 137{ 138 char *dst; 139 extern char etext; 140 141 if (addr >= VM_MIN_KERNEL_ADDRESS && 142 addr < (vaddr_t)&etext) { 143 db_write_text(addr, size, data); 144 return; 145 } 146 147 dst = (char *)addr; 148 149 while (size-- > 0) 150 *dst++ = *data++; 151} 152