db_memrw.c revision 1.11 1 /* $NetBSD: db_memrw.c,v 1.11 1996/02/20 02:42:55 gwr Exp $ */
2
3 /*
4 * Copyright (c) 1996 Gordon W. Ross
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. The name of the author may not be used to endorse or promote products
16 * derived from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
30 /*
31 * Interface to the debugger for virtual memory read/write.
32 *
33 * To write in the text segment, we have to first make
34 * the page writable, do the write, then restore the PTE.
35 * For writes outside the text segment, and all reads,
36 * just do the access -- if it causes a fault, the debugger
37 * will recover with a longjmp to an appropriate place.
38 *
39 * ALERT! If you want to access device registers with a
40 * specific size, then the read/write functions have to
41 * make sure to do the correct sized pointer access.
42 */
43
44 #include <sys/param.h>
45 #include <sys/proc.h>
46
47 #include <vm/vm.h>
48
49 #include <machine/pte.h>
50 #include <machine/db_machdep.h>
51
52 #include <ddb/db_access.h>
53
54 #include "cache.h"
55
56 /*
57 * Read bytes from kernel address space for debugger.
58 * This used to check for valid PTEs, but now that
59 * traps in DDB work correctly, "Just Do It!"
60 */
61 void
62 db_read_bytes(addr, size, data)
63 vm_offset_t addr;
64 register size_t size;
65 register char *data;
66 {
67 register char *src = (char*)addr;
68
69 if (size == 4) {
70 *((int*)data) = *((int*)src);
71 return;
72 }
73
74 if (size == 2) {
75 *((short*)data) = *((short*)src);
76 return;
77 }
78
79 while (size > 0) {
80 --size;
81 *data++ = *src++;
82 }
83 }
84
85 /*
86 * Write bytes somewhere in kernel text.
87 * Makes text page writable temporarily.
88 */
89 static void
90 db_write_text(addr, size, data)
91 vm_offset_t addr;
92 register size_t size;
93 register char *data;
94 {
95 register char *dst;
96 int ch, oldpte, tmppte;
97 vm_offset_t pgva, prevpg;
98
99 /* Prevent restoring a garbage PTE. */
100 if (size <= 0)
101 return;
102
103 dst = (char*)addr;
104 pgva = sun3_trunc_page((long)dst);
105
106 goto firstpage;
107 do {
108
109 /*
110 * If we are on a new page, restore the PTE
111 * for the previous page, and make the new
112 * page writable.
113 */
114 pgva = sun3_trunc_page((long)dst);
115 if (pgva != prevpg) {
116 /*
117 * Restore old PTE. No cache flush,
118 * because the tmp PTE has no-cache.
119 */
120 set_pte(prevpg, oldpte);
121
122 firstpage:
123 /*
124 * Flush the VAC to prevent a cache hit
125 * on the old, read-only PTE.
126 */
127 #ifdef HAVECACHE
128 if (cache_size)
129 cache_flush_page(pgva);
130 #endif
131 oldpte = get_pte(pgva);
132 if ((oldpte & PG_VALID) == 0) {
133 db_printf(" address 0x%x not a valid page\n", dst);
134 return;
135 }
136 tmppte = oldpte | PG_WRITE | PG_NC;
137 set_pte(pgva, tmppte);
138
139 prevpg = pgva;
140 }
141
142 /* Now we can write in this page of kernel text... */
143 *dst++ = *data++;
144
145 } while (--size > 0);
146
147 /* Restore old PTE for the last page touched. */
148 set_pte(prevpg, oldpte);
149
150 /* Finally, clear the instruction cache. */
151 ICIA();
152 }
153
154 /*
155 * Write bytes to kernel address space for debugger.
156 */
157 extern char kernel_text[], etext[];
158 void
159 db_write_bytes(addr, size, data)
160 vm_offset_t addr;
161 register size_t size;
162 register char *data;
163 {
164 register char *dst = (char *)addr;
165
166 /* If any part is in kernel text, use db_write_text() */
167 if ((dst < etext) && ((dst + size) > kernel_text)) {
168 db_write_text(dst, size, data);
169 return;
170 }
171
172 if (size == 4) {
173 *((int*)dst) = *((int*)data);
174 return;
175 }
176
177 if (size == 2) {
178 *((short*)dst) = *((short*)data);
179 return;
180 }
181
182 while (size > 0) {
183 --size;
184 *dst++ = *data++;
185 }
186 }
187
188