1 /* $NetBSD: db_memrw.c,v 1.8 2023/09/26 12:46:30 tsutsui Exp $ */
2
3 /*-
4 * Copyright (c) 1996 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Gordon W. Ross and Jason R. Thorpe.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 */
31 /*
32 * Mach Operating System
33 * Copyright (c) 1992 Carnegie Mellon University
34 * All Rights Reserved.
35 *
36 * Permission to use, copy, modify and distribute this software and its
37 * documentation is hereby granted, provided that both the copyright
38 * notice and this permission notice appear in all copies of the
39 * software, derivative works or modified versions, and any portions
40 * thereof, and that both notices appear in supporting documentation.
41 *
42 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
43 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
44 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
45 *
46 * Carnegie Mellon requests users of this software to return to
47 *
48 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
49 * School of Computer Science
50 * Carnegie Mellon University
51 * Pittsburgh PA 15213-3890
52 *
53 * any improvements or extensions that they make and grant Carnegie Mellon
54 * the rights to redistribute these changes.
55 */
56
57 /*
58 * Interface to the debugger for virtual memory read/write.
59 * This file is shared by DDB and KGDB, and must work even
60 * when only KGDB is included (thus no db_printf calls).
61 *
62 * To write in the text segment, we have to first make
63 * the page writable, do the write, then restore the PTE.
64 * For writes outside the text segment, and all reads,
65 * just do the access -- if it causes a fault, the debugger
66 * will recover with a longjmp to an appropriate place.
67 *
68 * ALERT! If you want to access device registers with a
69 * specific size, then the read/write functions have to
70 * make sure to do the correct sized pointer access.
71 */
72
73 #include <sys/cdefs.h>
74 __KERNEL_RCSID(0, "$NetBSD: db_memrw.c,v 1.8 2023/09/26 12:46:30 tsutsui Exp $");
75
76 #include <sys/param.h>
77
78 #include <machine/cpu.h>
79 #include <m68k/cacheops.h>
80 #include <uvm/uvm_extern.h>
81
82 #include <machine/db_machdep.h>
83 #include <ddb/db_access.h>
84
85 /*
86 * Read bytes from kernel address space for debugger.
87 */
88 void
db_read_bytes(db_addr_t addr,size_t size,char * data)89 db_read_bytes(db_addr_t addr, size_t size, char *data)
90 {
91 char *src = (char *)addr;
92
93 if (size == 4) {
94 *((uint32_t *)data) = *((uint32_t *)src);
95 return;
96 }
97
98 if (size == 2) {
99 *((uint16_t *)data) = *((uint16_t *)src);
100 return;
101 }
102
103 while (size-- > 0) {
104 *data++ = *src++;
105 }
106 }
107
108 static void
db_write_text(db_addr_t addr,size_t size,const char * data)109 db_write_text(db_addr_t addr, size_t size, const char *data)
110 {
111 char *dst, *odst;
112 pt_entry_t *pte, oldpte, tmppte;
113 vaddr_t pgva;
114 int limit;
115
116 dst = (char *)addr;
117 while (size > 0) {
118
119 /*
120 * Get the VA for the page.
121 */
122 pgva = trunc_page((vaddr_t)dst);
123
124 /*
125 * Save this destination address, for TLB flush.
126 */
127 odst = dst;
128
129 /*
130 * Compute number of bytes that can be written
131 * with this mapping and subtract it from the total size.
132 */
133 limit = round_page((vaddr_t)dst + 1) - (vaddr_t)dst;
134 if (limit > size)
135 limit = size;
136 size -= limit;
137
138 #ifdef M68K_MMU_HP
139 /*
140 * Flush the supervisor side of the VAC to
141 * prevent a cache hit on the old, read-only PTE.
142 */
143 if (ectype == EC_VIRT)
144 DCIS();
145 #endif
146
147 /*
148 * Make the page writable. Note the mapping is
149 * cache-inhibited to save hair.
150 */
151 pte = kvtopte(pgva);
152 oldpte = *pte;
153 if ((oldpte & PG_V) == 0) {
154 printf(" address %p not a valid page\n", dst);
155 return;
156 }
157 tmppte = (oldpte & ~PG_RO) | PG_RW | PG_CI;
158 *pte = tmppte;
159 TBIS((vaddr_t)odst);
160
161 /*
162 * Page is now writable. Do as much access as we can.
163 */
164 for (; limit > 0; limit--)
165 *dst++ = *data++;
166
167 /*
168 * Restore the old PTE.
169 */
170 *pte = oldpte;
171 TBIS((vaddr_t)odst);
172 }
173
174 /*
175 * Invalidate the instruction cache so our changes take effect.
176 */
177 ICIA();
178 }
179
180 /*
181 * Write bytes to kernel address space for debugger.
182 */
183 void
db_write_bytes(db_addr_t addr,size_t size,const char * data)184 db_write_bytes(db_addr_t addr, size_t size, const char *data)
185 {
186 char *dst = (char *)addr;
187 extern char kernel_text[], etext[];
188
189 /* If any part is in kernel text, use db_write_text() */
190 if (dst + size > kernel_text && dst < etext) {
191 db_write_text(addr, size, data);
192 return;
193 }
194
195 if (size == 4) {
196 *((uint32_t *)dst) = *((const uint32_t *)data);
197 return;
198 }
199
200 if (size == 2) {
201 *((uint16_t *)dst) = *((const uint16_t *)data);
202 return;
203 }
204
205 while (size-- > 0) {
206 *dst++ = *data++;
207 }
208 }
209