1 /* $OpenBSD: db_machdep.c,v 1.2 1998/09/15 10:50:13 pefo Exp $ */
2
3 /*-
4 * SPDX-License-Identifier: BSD-4-Clause
5 *
6 * Copyright (c) 1998 Per Fogelstrom, Opsycon AB
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 * must display the following acknowledgement:
18 * This product includes software developed under OpenBSD by
19 * Per Fogelstrom, Opsycon AB, Sweden.
20 * 4. The name of the author may not be used to endorse or promote products
21 * derived from this software without specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
24 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
25 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
27 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE.
34 *
35 * JNPR: db_interface.c,v 1.6.2.1 2007/08/29 12:24:49 girish
36 */
37
38 #include <sys/cdefs.h>
39 __FBSDID("$FreeBSD$");
40
41 #include <sys/types.h>
42 #include <sys/param.h>
43 #include <sys/systm.h>
44 #include <sys/cons.h>
45 #include <sys/lock.h>
46 #include <vm/vm.h>
47 #include <vm/vm_object.h>
48 #include <vm/vm_page.h>
49 #include <vm/pmap.h>
50 #include <vm/vm_map.h>
51 #include <sys/user.h>
52 #include <sys/proc.h>
53 #include <sys/reboot.h>
54
55 #include <machine/cache.h>
56 #include <machine/db_machdep.h>
57 #include <machine/mips_opcode.h>
58 #include <machine/vmparam.h>
59 #include <machine/md_var.h>
60 #include <machine/setjmp.h>
61
62 #include <ddb/ddb.h>
63 #include <ddb/db_sym.h>
64 #include <ddb/db_access.h>
65 #include <ddb/db_output.h>
66 #include <ddb/db_variables.h>
67 #include <sys/kdb.h>
68
69 static db_varfcn_t db_frame;
70
71 #define DB_OFFSET(x) (db_expr_t *)offsetof(struct trapframe, x)
72 struct db_variable db_regs[] = {
73 { "at", DB_OFFSET(ast), db_frame },
74 { "v0", DB_OFFSET(v0), db_frame },
75 { "v1", DB_OFFSET(v1), db_frame },
76 { "a0", DB_OFFSET(a0), db_frame },
77 { "a1", DB_OFFSET(a1), db_frame },
78 { "a2", DB_OFFSET(a2), db_frame },
79 { "a3", DB_OFFSET(a3), db_frame },
80 #if defined(__mips_n32) || defined(__mips_n64)
81 { "a4", DB_OFFSET(a4), db_frame },
82 { "a5", DB_OFFSET(a5), db_frame },
83 { "a6", DB_OFFSET(a6), db_frame },
84 { "a7", DB_OFFSET(a7), db_frame },
85 { "t0", DB_OFFSET(t0), db_frame },
86 { "t1", DB_OFFSET(t1), db_frame },
87 { "t2", DB_OFFSET(t2), db_frame },
88 { "t3", DB_OFFSET(t3), db_frame },
89 #else
90 { "t0", DB_OFFSET(t0), db_frame },
91 { "t1", DB_OFFSET(t1), db_frame },
92 { "t2", DB_OFFSET(t2), db_frame },
93 { "t3", DB_OFFSET(t3), db_frame },
94 { "t4", DB_OFFSET(t4), db_frame },
95 { "t5", DB_OFFSET(t5), db_frame },
96 { "t6", DB_OFFSET(t6), db_frame },
97 { "t7", DB_OFFSET(t7), db_frame },
98 #endif
99 { "s0", DB_OFFSET(s0), db_frame },
100 { "s1", DB_OFFSET(s1), db_frame },
101 { "s2", DB_OFFSET(s2), db_frame },
102 { "s3", DB_OFFSET(s3), db_frame },
103 { "s4", DB_OFFSET(s4), db_frame },
104 { "s5", DB_OFFSET(s5), db_frame },
105 { "s6", DB_OFFSET(s6), db_frame },
106 { "s7", DB_OFFSET(s7), db_frame },
107 { "t8", DB_OFFSET(t8), db_frame },
108 { "t9", DB_OFFSET(t9), db_frame },
109 { "k0", DB_OFFSET(k0), db_frame },
110 { "k1", DB_OFFSET(k1), db_frame },
111 { "gp", DB_OFFSET(gp), db_frame },
112 { "sp", DB_OFFSET(sp), db_frame },
113 { "s8", DB_OFFSET(s8), db_frame },
114 { "ra", DB_OFFSET(ra), db_frame },
115 { "sr", DB_OFFSET(sr), db_frame },
116 { "lo", DB_OFFSET(mullo), db_frame },
117 { "hi", DB_OFFSET(mulhi), db_frame },
118 { "bad", DB_OFFSET(badvaddr), db_frame },
119 { "cs", DB_OFFSET(cause), db_frame },
120 { "pc", DB_OFFSET(pc), db_frame },
121 };
122 struct db_variable *db_eregs = db_regs + nitems(db_regs);
123
124 int (*do_db_log_stack_trace_cmd)(char *);
125
126 static int
127 db_frame(struct db_variable *vp, db_expr_t *valuep, int op)
128 {
129 register_t *reg;
130
131 if (kdb_frame == NULL)
132 return (0);
133
134 reg = (register_t *)((uintptr_t)kdb_frame + (size_t)(intptr_t)vp->valuep);
135 if (op == DB_VAR_GET)
136 *valuep = *reg;
137 else
138 *reg = *valuep;
139 return (1);
140 }
141
142 int
143 db_read_bytes(vm_offset_t addr, size_t size, char *data)
144 {
145 jmp_buf jb;
146 void *prev_jb;
147 int ret;
148
149 prev_jb = kdb_jmpbuf(jb);
150 ret = setjmp(jb);
151 if (ret == 0) {
152 /*
153 * 'addr' could be a memory-mapped I/O address. Try to
154 * do atomic load/store in unit of size requested.
155 * size == 8 is only atomic on 64bit or n32 kernel.
156 */
157 if ((size == 2 || size == 4 || size == 8) &&
158 ((addr & (size -1)) == 0) &&
159 (((vm_offset_t)data & (size -1)) == 0)) {
160 switch (size) {
161 case 2:
162 *(uint16_t *)data = *(uint16_t *)addr;
163 break;
164 case 4:
165 *(uint32_t *)data = *(uint32_t *)addr;
166 break;
167 case 8:
168 *(uint64_t *)data = *(uint64_t *)addr;
169 break;
170 }
171 } else {
172 char *src;
173
174 src = (char *)addr;
175 while (size-- > 0)
176 *data++ = *src++;
177 }
178 }
179
180 (void)kdb_jmpbuf(prev_jb);
181 return (ret);
182 }
183
184 int
185 db_write_bytes(vm_offset_t addr, size_t size, char *data)
186 {
187 int ret;
188 jmp_buf jb;
189 void *prev_jb;
190
191 prev_jb = kdb_jmpbuf(jb);
192 ret = setjmp(jb);
193
194 if (ret == 0) {
195 /*
196 * 'addr' could be a memory-mapped I/O address. Try to
197 * do atomic load/store in unit of size requested.
198 * size == 8 is only atomic on 64bit or n32 kernel.
199 */
200 if ((size == 2 || size == 4 || size == 8) &&
201 ((addr & (size -1)) == 0) &&
202 (((vm_offset_t)data & (size -1)) == 0)) {
203 switch (size) {
204 case 2:
205 *(uint16_t *)addr = *(uint16_t *)data;
206 break;
207 case 4:
208 *(uint32_t *)addr = *(uint32_t *)data;
209 break;
210 case 8:
211 *(uint64_t *)addr = *(uint64_t *)data;
212 break;
213 }
214 } else {
215 char *dst;
216 size_t len = size;
217
218 dst = (char *)addr;
219 while (len-- > 0)
220 *dst++ = *data++;
221 }
222
223 mips_icache_sync_range((db_addr_t) addr, size);
224 mips_dcache_wbinv_range((db_addr_t) addr, size);
225 }
226 (void)kdb_jmpbuf(prev_jb);
227 return (ret);
228 }
229
230 /*
231 * To do a single step ddb needs to know the next address
232 * that we will get to. It means that we need to find out
233 * both the address for a branch taken and for not taken, NOT! :-)
234 * MipsEmulateBranch will do the job to find out _exactly_ which
235 * address we will end up at so the 'dual bp' method is not
236 * requiered.
237 */
238 db_addr_t
239 next_instr_address(db_addr_t pc, boolean_t bd)
240 {
241 db_addr_t next;
242
243 next = (db_addr_t)MipsEmulateBranch(kdb_frame, pc, 0, 0);
244 return (next);
245 }
246
247
248 /*
249 * Decode instruction and figure out type.
250 */
251 int
252 db_inst_type(int ins)
253 {
254 InstFmt inst;
255 int ityp = 0;
256
257 inst.word = ins;
258 switch ((int)inst.JType.op) {
259 case OP_SPECIAL:
260 switch ((int)inst.RType.func) {
261 case OP_JR:
262 ityp = IT_BRANCH;
263 break;
264 case OP_JALR:
265 case OP_SYSCALL:
266 ityp = IT_CALL;
267 break;
268 }
269 break;
270
271 case OP_BCOND:
272 switch ((int)inst.IType.rt) {
273 case OP_BLTZ:
274 case OP_BLTZL:
275 case OP_BGEZ:
276 case OP_BGEZL:
277 ityp = IT_BRANCH;
278 break;
279
280 case OP_BLTZAL:
281 case OP_BLTZALL:
282 case OP_BGEZAL:
283 case OP_BGEZALL:
284 ityp = IT_CALL;
285 break;
286 }
287 break;
288
289 case OP_JAL:
290 ityp = IT_CALL;
291 break;
292
293 case OP_J:
294 case OP_BEQ:
295 case OP_BEQL:
296 case OP_BNE:
297 case OP_BNEL:
298 case OP_BLEZ:
299 case OP_BLEZL:
300 case OP_BGTZ:
301 case OP_BGTZL:
302 ityp = IT_BRANCH;
303 break;
304
305 case OP_COP1:
306 switch (inst.RType.rs) {
307 case OP_BCx:
308 case OP_BCy:
309 ityp = IT_BRANCH;
310 break;
311 }
312 break;
313
314 case OP_LB:
315 case OP_LH:
316 case OP_LW:
317 case OP_LD:
318 case OP_LBU:
319 case OP_LHU:
320 case OP_LWU:
321 case OP_LWC1:
322 ityp = IT_LOAD;
323 break;
324
325 case OP_SB:
326 case OP_SH:
327 case OP_SW:
328 case OP_SD:
329 case OP_SWC1:
330 ityp = IT_STORE;
331 break;
332 }
333 return (ityp);
334 }
335
336 /*
337 * Return the next pc if the given branch is taken.
338 * MachEmulateBranch() runs analysis for branch delay slot.
339 */
340 db_addr_t
341 branch_taken(int inst, db_addr_t pc)
342 {
343 db_addr_t ra;
344 register_t fpucsr;
345
346 /* TBD: when is fsr set */
347 fpucsr = (curthread) ? curthread->td_pcb->pcb_regs.fsr : 0;
348 ra = (db_addr_t)MipsEmulateBranch(kdb_frame, pc, fpucsr, 0);
349 return (ra);
350 }
Cache object: c67bc8c214a72f2e1373dcbab8132997
|