db_memrw.c revision 1.12 1 /* $NetBSD: db_memrw.c,v 1.12 1996/06/17 15:40:48 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 * This file is shared by DDB and KGDB, and must work even
33 * when only KGDB is included (thus no db_printf calls).
34 *
35 * To write in the text segment, we have to first make
36 * the page writable, do the write, then restore the PTE.
37 * For writes outside the text segment, and all reads,
38 * just do the access -- if it causes a fault, the debugger
39 * will recover with a longjmp to an appropriate place.
40 *
41 * ALERT! If you want to access device registers with a
42 * specific size, then the read/write functions have to
43 * make sure to do the correct sized pointer access.
44 */
45
46 #include <sys/param.h>
47 #include <sys/proc.h>
48
49 #include <vm/vm.h>
50
51 #include <machine/pte.h>
52 #include <machine/db_machdep.h>
53
54 #include <ddb/db_access.h>
55
56 #include "cache.h"
57
58 /*
59 * Read bytes from kernel address space for debugger.
60 * This used to check for valid PTEs, but now that
61 * traps in DDB work correctly, "Just Do It!"
62 */
63 void
64 db_read_bytes(addr, size, data)
65 vm_offset_t addr;
66 register size_t size;
67 register char *data;
68 {
69 register char *src = (char*)addr;
70
71 if (size == 4) {
72 *((int*)data) = *((int*)src);
73 return;
74 }
75
76 if (size == 2) {
77 *((short*)data) = *((short*)src);
78 return;
79 }
80
81 while (size > 0) {
82 --size;
83 *data++ = *src++;
84 }
85 }
86
87 /*
88 * Write bytes somewhere in kernel text.
89 * Makes text page writable temporarily.
90 */
91 static void
92 db_write_text(addr, size, data)
93 vm_offset_t addr;
94 register size_t size;
95 register char *data;
96 {
97 register char *dst;
98 int ch, oldpte, tmppte;
99 vm_offset_t pgva, prevpg;
100
101 /* Prevent restoring a garbage PTE. */
102 if (size <= 0)
103 return;
104
105 dst = (char*)addr;
106 pgva = sun3_trunc_page((long)dst);
107
108 goto firstpage;
109 do {
110
111 /*
112 * If we are on a new page, restore the PTE
113 * for the previous page, and make the new
114 * page writable.
115 */
116 pgva = sun3_trunc_page((long)dst);
117 if (pgva != prevpg) {
118 /*
119 * Restore old PTE. No cache flush,
120 * because the tmp PTE has no-cache.
121 */
122 set_pte(prevpg, oldpte);
123
124 firstpage:
125 /*
126 * Flush the VAC to prevent a cache hit
127 * on the old, read-only PTE.
128 */
129 #ifdef HAVECACHE
130 if (cache_size)
131 cache_flush_page(pgva);
132 #endif
133 oldpte = get_pte(pgva);
134 if ((oldpte & PG_VALID) == 0) {
135 printf(" address 0x%x not a valid page\n", dst);
136 return;
137 }
138 tmppte = oldpte | PG_WRITE | PG_NC;
139 set_pte(pgva, tmppte);
140
141 prevpg = pgva;
142 }
143
144 /* Now we can write in this page of kernel text... */
145 *dst++ = *data++;
146
147 } while (--size > 0);
148
149 /* Restore old PTE for the last page touched. */
150 set_pte(prevpg, oldpte);
151
152 /* Finally, clear the instruction cache. */
153 ICIA();
154 }
155
156 /*
157 * Write bytes to kernel address space for debugger.
158 */
159 extern char kernel_text[], etext[];
160 void
161 db_write_bytes(addr, size, data)
162 vm_offset_t addr;
163 register size_t size;
164 register char *data;
165 {
166 register char *dst = (char *)addr;
167
168 /* If any part is in kernel text, use db_write_text() */
169 if ((dst < etext) && ((dst + size) > kernel_text)) {
170 db_write_text(dst, size, data);
171 return;
172 }
173
174 if (size == 4) {
175 *((int*)dst) = *((int*)data);
176 return;
177 }
178
179 if (size == 2) {
180 *((short*)dst) = *((short*)data);
181 return;
182 }
183
184 while (size > 0) {
185 --size;
186 *dst++ = *data++;
187 }
188 }
189
190