]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/mips/mips/db_interface.c
Update OpenZFS to 2.0.0-rc3-gfc5966
[FreeBSD/FreeBSD.git] / sys / mips / mips / db_interface.c
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  *      Decode instruction and figure out type.
249  */
250 int
251 db_inst_type(int ins)
252 {
253         InstFmt inst;
254         int     ityp = 0;
255
256         inst.word = ins;
257         switch ((int)inst.JType.op) {
258         case OP_SPECIAL:
259                 switch ((int)inst.RType.func) {
260                 case OP_JR:
261                         ityp = IT_BRANCH;
262                         break;
263                 case OP_JALR:
264                 case OP_SYSCALL:
265                         ityp = IT_CALL;
266                         break;
267                 }
268                 break;
269
270         case OP_BCOND:
271                 switch ((int)inst.IType.rt) {
272                 case OP_BLTZ:
273                 case OP_BLTZL:
274                 case OP_BGEZ:
275                 case OP_BGEZL:
276                         ityp = IT_BRANCH;
277                         break;
278
279                 case OP_BLTZAL:
280                 case OP_BLTZALL:
281                 case OP_BGEZAL:
282                 case OP_BGEZALL:
283                         ityp = IT_CALL;
284                         break;
285                 }
286                 break;
287
288         case OP_JAL:
289                 ityp = IT_CALL;
290                 break;
291
292         case OP_J:
293         case OP_BEQ:
294         case OP_BEQL:
295         case OP_BNE:
296         case OP_BNEL:
297         case OP_BLEZ:
298         case OP_BLEZL:
299         case OP_BGTZ:
300         case OP_BGTZL:
301                 ityp = IT_BRANCH;
302                 break;
303
304         case OP_COP1:
305                 switch (inst.RType.rs) {
306                 case OP_BCx:
307                 case OP_BCy:
308                         ityp = IT_BRANCH;
309                         break;
310                 }
311                 break;
312
313         case OP_LB:
314         case OP_LH:
315         case OP_LW:
316         case OP_LD:
317         case OP_LBU:
318         case OP_LHU:
319         case OP_LWU:
320         case OP_LWC1:
321                 ityp = IT_LOAD;
322                 break;
323
324         case OP_SB:
325         case OP_SH:
326         case OP_SW:
327         case OP_SD:  
328         case OP_SWC1:
329                 ityp = IT_STORE;
330                 break;
331         }
332         return (ityp);
333 }
334
335 /*
336  * Return the next pc if the given branch is taken.
337  * MachEmulateBranch() runs analysis for branch delay slot.
338  */
339 db_addr_t
340 branch_taken(int inst, db_addr_t pc)
341 {
342         db_addr_t ra;
343         register_t fpucsr;
344
345         /* TBD: when is fsr set */
346         fpucsr = (curthread) ? curthread->td_pcb->pcb_regs.fsr : 0;
347         ra = (db_addr_t)MipsEmulateBranch(kdb_frame, pc, fpucsr, 0);
348         return (ra);
349 }