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