db_memrw.c revision 1.10 1 /* $NetBSD: db_memrw.c,v 1.10 1996/02/16 23:32:00 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 *data++ = *src++;
81 }
82
83 /*
84 * Write bytes somewhere in kernel text.
85 * Makes text page writable temporarily.
86 */
87 static void
88 db_write_text(addr, size, data)
89 vm_offset_t addr;
90 register size_t size;
91 register char *data;
92 {
93 register char *dst;
94 int ch, oldpte, tmppte;
95 vm_offset_t pgva, prevpg;
96
97 /* Prevent restoring a garbage PTE. */
98 if (size <= 0)
99 return;
100
101 dst = (char*)addr;
102 pgva = sun3_trunc_page((long)dst);
103
104 goto firstpage;
105 do {
106
107 /*
108 * If we are on a new page, restore the PTE
109 * for the previous page, and make the new
110 * page writable.
111 */
112 pgva = sun3_trunc_page((long)dst);
113 if (pgva != prevpg) {
114 /*
115 * Restore old PTE. No cache flush,
116 * because the tmp PTE has no-cache.
117 */
118 set_pte(prevpg, oldpte);
119
120 firstpage:
121 /*
122 * Flush the VAC to prevent a cache hit
123 * on the old, read-only PTE.
124 */
125 #ifdef HAVECACHE
126 if (cache_size)
127 cache_flush_page(pgva);
128 #endif
129 oldpte = get_pte(pgva);
130 if ((oldpte & PG_VALID) == 0) {
131 db_printf(" address 0x%x not a valid page\n", dst);
132 return;
133 }
134 tmppte = oldpte | PG_WRITE | PG_NC;
135 set_pte(pgva, tmppte);
136
137 prevpg = pgva;
138 }
139
140 /* Now we can write in this page of kernel text... */
141 *dst++ = *data++;
142
143 } while (--size > 0);
144
145 /* Restore old PTE for the last page touched. */
146 set_pte(prevpg, oldpte);
147
148 /* Finally, clear the instruction cache. */
149 ICIA();
150 }
151
152 /*
153 * Write bytes to kernel address space for debugger.
154 */
155 extern char kernel_text[], etext[];
156 void
157 db_write_bytes(addr, size, data)
158 vm_offset_t addr;
159 register size_t size;
160 register char *data;
161 {
162 register char *dst = (char *)addr;
163
164 /* If any part is in kernel text, use db_write_text() */
165 if ((dst < etext) && ((dst + size) > kernel_text)) {
166 db_write_text(dst, size, data);
167 return;
168 }
169
170 if (size == 4) {
171 *((int*)dst) = *((int*)data);
172 return;
173 }
174
175 if (size == 2) {
176 *((short*)dst) = *((short*)data);
177 return;
178 }
179
180 while (--size >= 0)
181 *dst++ = *data++;
182 }
183
184