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