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