]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/alpha/alpha/db_interface.c
This commit was generated by cvs2svn to compensate for changes in r58653,
[FreeBSD/FreeBSD.git] / sys / alpha / alpha / db_interface.c
1 /* $NetBSD: db_interface.c,v 1.2 1997/09/16 19:07:19 thorpej Exp $ */
2 /* $FreeBSD$ */
3
4 /* 
5  * Mach Operating System
6  * Copyright (c) 1992,1991,1990 Carnegie Mellon University
7  * All Rights Reserved.
8  * 
9  * Permission to use, copy, modify and distribute this software and its
10  * documentation is hereby granted, provided that both the copyright
11  * notice and this permission notice appear in all copies of the
12  * software, derivative works or modified versions, and any portions
13  * thereof, and that both notices appear in supporting documentation.
14  * 
15  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS 
16  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
17  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
18  * 
19  * Carnegie Mellon requests users of this software to return to
20  * 
21  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
22  *  School of Computer Science
23  *  Carnegie Mellon University
24  *  Pittsburgh PA 15213-3890
25  * 
26  * any improvements or extensions that they make and grant Carnegie the
27  * rights to redistribute these changes.
28  *
29  *      db_interface.c,v 2.4 1991/02/05 17:11:13 mrt (CMU)
30  */
31
32 /*
33  * Parts of this file are derived from Mach 3:
34  *
35  *      File: alpha_instruction.c
36  *      Author: Alessandro Forin, Carnegie Mellon University
37  *      Date:   6/92
38  */
39
40 /*
41  * Interface to DDB.
42  *
43  * Modified for NetBSD/alpha by:
44  *
45  *      Christopher G. Demetriou, Carnegie Mellon University
46  *
47  *      Jason R. Thorpe, Numerical Aerospace Simulation Facility,
48  *      NASA Ames Research Center
49  */
50
51 #include <sys/cdefs.h>                  /* RCS ID & Copyright macro defns */
52
53 /* __KERNEL_RCSID(0, "$NetBSD: db_interface.c,v 1.2 1997/09/16 19:07:19 thorpej Exp $"); */
54
55 #include <sys/param.h>
56 #include <sys/proc.h>
57 #include <sys/reboot.h>
58 #include <sys/systm.h>
59 #include <sys/kernel.h>
60 #include <sys/cons.h>
61
62 #include <vm/vm.h>
63
64 #include <machine/db_machdep.h>
65 #include <machine/pal.h>
66 #include <machine/prom.h>
67
68 #include <alpha/alpha/db_instruction.h>
69
70 #include <ddb/ddb.h>
71
72 #include <ddb/db_access.h>
73 #include <ddb/db_sym.h>
74 #include <ddb/db_variables.h>
75 #include <setjmp.h>
76
77 static jmp_buf *db_nofault = 0;
78 extern jmp_buf  db_jmpbuf;
79
80 extern void     gdb_handle_exception __P((db_regs_t *, int, int));
81
82 #if 0
83 extern char *trap_type[];
84 extern int trap_types;
85 #endif
86
87 int     db_active;
88
89 void    ddbprinttrap __P((unsigned long, unsigned long, unsigned long,
90             unsigned long));
91
92 struct db_variable db_regs[] = {
93         {       "v0",   &ddb_regs.tf_regs[FRAME_V0],    FCN_NULL        },
94         {       "t0",   &ddb_regs.tf_regs[FRAME_T0],    FCN_NULL        },
95         {       "t1",   &ddb_regs.tf_regs[FRAME_T1],    FCN_NULL        },
96         {       "t2",   &ddb_regs.tf_regs[FRAME_T2],    FCN_NULL        },
97         {       "t3",   &ddb_regs.tf_regs[FRAME_T3],    FCN_NULL        },
98         {       "t4",   &ddb_regs.tf_regs[FRAME_T4],    FCN_NULL        },
99         {       "t5",   &ddb_regs.tf_regs[FRAME_T5],    FCN_NULL        },
100         {       "t6",   &ddb_regs.tf_regs[FRAME_T6],    FCN_NULL        },
101         {       "t7",   &ddb_regs.tf_regs[FRAME_T7],    FCN_NULL        },
102         {       "s0",   &ddb_regs.tf_regs[FRAME_S0],    FCN_NULL        },
103         {       "s1",   &ddb_regs.tf_regs[FRAME_S1],    FCN_NULL        },
104         {       "s2",   &ddb_regs.tf_regs[FRAME_S2],    FCN_NULL        },
105         {       "s3",   &ddb_regs.tf_regs[FRAME_S3],    FCN_NULL        },
106         {       "s4",   &ddb_regs.tf_regs[FRAME_S4],    FCN_NULL        },
107         {       "s5",   &ddb_regs.tf_regs[FRAME_S5],    FCN_NULL        },
108         {       "s6",   &ddb_regs.tf_regs[FRAME_S6],    FCN_NULL        },
109         {       "a0",   &ddb_regs.tf_regs[FRAME_A0],    FCN_NULL        },
110         {       "a1",   &ddb_regs.tf_regs[FRAME_A1],    FCN_NULL        },
111         {       "a2",   &ddb_regs.tf_regs[FRAME_A2],    FCN_NULL        },
112         {       "a3",   &ddb_regs.tf_regs[FRAME_A3],    FCN_NULL        },
113         {       "a4",   &ddb_regs.tf_regs[FRAME_A4],    FCN_NULL        },
114         {       "a5",   &ddb_regs.tf_regs[FRAME_A5],    FCN_NULL        },
115         {       "t8",   &ddb_regs.tf_regs[FRAME_T8],    FCN_NULL        },
116         {       "t9",   &ddb_regs.tf_regs[FRAME_T9],    FCN_NULL        },
117         {       "t10",  &ddb_regs.tf_regs[FRAME_T10],   FCN_NULL        },
118         {       "t11",  &ddb_regs.tf_regs[FRAME_T11],   FCN_NULL        },
119         {       "ra",   &ddb_regs.tf_regs[FRAME_RA],    FCN_NULL        },
120         {       "t12",  &ddb_regs.tf_regs[FRAME_T12],   FCN_NULL        },
121         {       "at",   &ddb_regs.tf_regs[FRAME_AT],    FCN_NULL        },
122         {       "gp",   &ddb_regs.tf_regs[FRAME_GP],    FCN_NULL        },
123         {       "sp",   &ddb_regs.tf_regs[FRAME_SP],    FCN_NULL        },
124         {       "pc",   &ddb_regs.tf_regs[FRAME_PC],    FCN_NULL        },
125         {       "ps",   &ddb_regs.tf_regs[FRAME_PS],    FCN_NULL        },
126         {       "ai",   &ddb_regs.tf_regs[FRAME_T11],   FCN_NULL        },
127         {       "pv",   &ddb_regs.tf_regs[FRAME_T12],   FCN_NULL        },
128 };
129 struct db_variable *db_eregs = db_regs + sizeof(db_regs)/sizeof(db_regs[0]);
130
131 /*
132  * Print trap reason.
133  */
134 void
135 ddbprinttrap(a0, a1, a2, entry)
136         unsigned long a0, a1, a2, entry;
137 {
138
139         /* XXX Implement. */
140
141         printf("ddbprinttrap(0x%lx, 0x%lx, 0x%lx, 0x%lx)\n", a0, a1, a2,
142             entry);
143 }
144
145 /*
146  *  ddb_trap - field a kernel trap
147  */
148 int
149 kdb_trap(a0, a1, a2, entry, regs)
150         unsigned long a0, a1, a2, entry;
151         db_regs_t *regs;
152 {
153         int ddb_mode = !(boothowto & RB_GDB);
154         int s;
155
156         /*
157          * Don't bother checking for usermode, since a benign entry
158          * by the kernel (call to Debugger() or a breakpoint) has
159          * already checked for usermode.  If neither of those
160          * conditions exist, something Bad has happened.
161          */
162
163         if (entry != ALPHA_KENTRY_IF ||
164             (a0 != ALPHA_IF_CODE_BUGCHK && a0 != ALPHA_IF_CODE_BPT
165                 && a0 != ALPHA_IF_CODE_GENTRAP)) {
166                 if (ddb_mode) {
167                         db_printf("ddbprinttrap from 0x%lx\n",  /* XXX */
168                                   regs->tf_regs[FRAME_PC]);
169                         ddbprinttrap(a0, a1, a2, entry);
170                         /*
171                          * Tell caller "We did NOT handle the trap."
172                          * Caller should panic, or whatever.
173                          */
174                         return (0);
175                 }
176                 if (db_nofault) {
177                         jmp_buf *no_fault = db_nofault;
178                         db_nofault = 0;
179                         longjmp(*no_fault, 1);
180                 }
181         }
182
183         /*
184          * XXX Should switch to DDB's own stack, here.
185          */
186
187         ddb_regs = *regs;
188
189         s = splhigh();
190
191         db_active++;
192
193         if (ddb_mode) {
194             cndbctl(TRUE);      /* DDB active, unblank video */
195             db_trap(entry, a0); /* Where the work happens */
196             cndbctl(FALSE);     /* DDB inactive */
197         } else
198             gdb_handle_exception(&ddb_regs, entry, a0);
199
200         db_active--;
201
202         splx(s);
203
204         *regs = ddb_regs;
205
206         /*
207          * Tell caller "We HAVE handled the trap."
208          */
209         return (1);
210 }
211
212 /*
213  * Read bytes from kernel address space for debugger.
214  */
215 void
216 db_read_bytes(addr, size, data)
217         vm_offset_t     addr;
218         register size_t size;
219         register char   *data;
220 {
221         register char   *src;
222
223         db_nofault = &db_jmpbuf;
224
225         src = (char *)addr;
226         while (size-- > 0)
227                 *data++ = *src++;
228
229         db_nofault = 0;
230 }
231
232 /*
233  * Write bytes to kernel address space for debugger.
234  */
235 void
236 db_write_bytes(addr, size, data)
237         vm_offset_t     addr;
238         register size_t size;
239         register char   *data;
240 {
241         register char   *dst;
242
243         db_nofault = &db_jmpbuf;
244
245         dst = (char *)addr;
246         while (size-- > 0)
247                 *dst++ = *data++;
248         alpha_pal_imb();
249
250         db_nofault = 0;
251 }
252
253 void
254 Debugger(const char* msg)
255 {
256         printf("%s\n", msg);
257         __asm("call_pal 0x81");         /* XXX bugchk */
258 }
259
260 /*
261  * Alpha-specific ddb commands:
262  *
263  *      halt            set halt bit in rpb and halt
264  *      reboot          set reboot bit in rpb and halt
265  */
266
267 DB_COMMAND(halt, db_mach_halt)
268 {
269
270         prom_halt(1);
271 }
272
273 DB_COMMAND(reboot, db_mach_reboot)
274 {
275         prom_halt(0);
276 }
277
278 /*
279  * Map Alpha register numbers to trapframe/db_regs_t offsets.
280  */
281 static int reg_to_frame[32] = {
282         FRAME_V0,
283         FRAME_T0,
284         FRAME_T1,
285         FRAME_T2,
286         FRAME_T3,
287         FRAME_T4,
288         FRAME_T5,
289         FRAME_T6,
290         FRAME_T7,
291
292         FRAME_S0,
293         FRAME_S1,
294         FRAME_S2,
295         FRAME_S3,
296         FRAME_S4,
297         FRAME_S5,
298         FRAME_S6,
299
300         FRAME_A0,
301         FRAME_A1,
302         FRAME_A2,
303         FRAME_A3,
304         FRAME_A4,
305         FRAME_A5,
306
307         FRAME_T8,
308         FRAME_T9,
309         FRAME_T10,
310         FRAME_T11,
311         FRAME_RA,
312         FRAME_T12,
313         FRAME_AT,
314         FRAME_GP,
315         FRAME_SP,
316         -1,             /* zero */
317 };
318
319 u_long
320 db_register_value(regs, regno)
321         db_regs_t *regs;
322         int regno;
323 {
324
325         if (regno > 31 || regno < 0) {
326                 db_printf(" **** STRANGE REGISTER NUMBER %d **** ", regno);
327                 return (0);
328         }
329
330         if (regno == 31)
331                 return (0);
332
333         return (regs->tf_regs[reg_to_frame[regno]]);
334 }
335
336 /*
337  * Support functions for software single-step.
338  */
339
340 boolean_t
341 db_inst_call(ins)
342         int ins;
343 {
344         alpha_instruction insn;
345
346         insn.bits = ins;
347         return ((insn.branch_format.opcode == op_bsr) ||
348             ((insn.jump_format.opcode == op_j) &&
349              (insn.jump_format.action & 1)));
350 }
351
352 boolean_t
353 db_inst_return(ins)
354         int ins;
355 {
356         alpha_instruction insn;
357
358         insn.bits = ins;
359         return ((insn.jump_format.opcode == op_j) &&
360             (insn.jump_format.action == op_ret));
361 }
362
363 boolean_t
364 db_inst_trap_return(ins)
365         int ins;
366 {
367         alpha_instruction insn;
368
369         insn.bits = ins;
370         return ((insn.pal_format.opcode == op_pal) &&
371             (insn.pal_format.function == PAL_OSF1_rti));
372 }
373
374 boolean_t
375 db_inst_branch(ins)
376         int ins;
377 {
378         alpha_instruction insn;
379
380         insn.bits = ins;
381         switch (insn.branch_format.opcode) {
382         case op_j:
383         case op_br:
384         case op_fbeq:
385         case op_fblt:
386         case op_fble:
387         case op_fbne:
388         case op_fbge:
389         case op_fbgt:
390         case op_blbc:
391         case op_beq:
392         case op_blt:
393         case op_ble:
394         case op_blbs:
395         case op_bne:
396         case op_bge:
397         case op_bgt:
398                 return (TRUE);
399         }
400
401         return (FALSE);
402 }
403
404 boolean_t
405 db_inst_unconditional_flow_transfer(ins)
406         int ins;
407 {
408         alpha_instruction insn;
409
410         insn.bits = ins;
411         switch (insn.branch_format.opcode) {
412         case op_j:
413         case op_br:
414                 return (TRUE);
415
416         case op_pal:
417                 switch (insn.pal_format.function) {
418                 case PAL_OSF1_retsys:
419                 case PAL_OSF1_rti:
420                 case PAL_OSF1_callsys:
421                         return (TRUE);
422                 }
423         }
424
425         return (FALSE);
426 }
427
428 #if 0
429 boolean_t
430 db_inst_spill(ins, regn)
431         int ins, regn;
432 {
433         alpha_instruction insn;
434
435         insn.bits = ins;
436         return ((insn.mem_format.opcode == op_stq) &&
437             (insn.mem_format.rd == regn));
438 }
439 #endif
440
441 boolean_t
442 db_inst_load(ins)
443         int ins;
444 {
445         alpha_instruction insn;
446
447         insn.bits = ins;
448         
449         /* Loads. */
450         if (insn.mem_format.opcode == op_ldbu ||
451             insn.mem_format.opcode == op_ldq_u ||
452             insn.mem_format.opcode == op_ldwu)
453                 return (TRUE);
454         if ((insn.mem_format.opcode >= op_ldf) &&
455             (insn.mem_format.opcode <= op_ldt))
456                 return (TRUE);
457         if ((insn.mem_format.opcode >= op_ldl) &&
458             (insn.mem_format.opcode <= op_ldq_l))
459                 return (TRUE);
460
461         /* Prefetches. */
462         if (insn.mem_format.opcode == op_special) {
463                 /* Note: MB is treated as a store. */
464                 if ((insn.mem_format.displacement == (short)op_fetch) ||
465                     (insn.mem_format.displacement == (short)op_fetch_m))
466                         return (TRUE);
467         }
468
469         return (FALSE);
470 }
471
472 boolean_t
473 db_inst_store(ins)
474         int ins;
475 {
476         alpha_instruction insn;
477
478         insn.bits = ins;
479
480         /* Stores. */
481         if (insn.mem_format.opcode == op_stw ||
482             insn.mem_format.opcode == op_stb ||
483             insn.mem_format.opcode == op_stq_u)
484                 return (TRUE);
485         if ((insn.mem_format.opcode >= op_stf) &&
486             (insn.mem_format.opcode <= op_stt))
487                 return (TRUE);
488         if ((insn.mem_format.opcode >= op_stl) &&
489             (insn.mem_format.opcode <= op_stq_c))
490                 return (TRUE);
491
492         /* Barriers. */
493         if (insn.mem_format.opcode == op_special) {
494                 if (insn.mem_format.displacement == op_mb)
495                         return (TRUE);
496         }
497
498         return (FALSE);
499 }
500
501 db_addr_t
502 db_branch_taken(ins, pc, regs)
503         int ins;
504         db_addr_t pc;
505         db_regs_t *regs;
506 {
507         alpha_instruction insn;
508         db_addr_t newpc;
509
510         insn.bits = ins;
511         switch (insn.branch_format.opcode) {
512         /*
513          * Jump format: target PC is (contents of instruction's "RB") & ~3.
514          */
515         case op_j:
516                 newpc = db_register_value(regs, insn.jump_format.rs) & ~3;
517                 break;
518
519         /*
520          * Branch format: target PC is
521          *      (new PC) + (4 * sign-ext(displacement)).
522          */
523         case op_br:
524         case op_fbeq:
525         case op_fblt:
526         case op_fble:
527         case op_bsr:
528         case op_fbne:
529         case op_fbge:
530         case op_fbgt:
531         case op_blbc:
532         case op_beq:
533         case op_blt:
534         case op_ble:
535         case op_blbs:
536         case op_bne:
537         case op_bge:
538         case op_bgt:
539                 newpc = (insn.branch_format.displacement << 2) + (pc + 4);
540                 break;
541
542         default:
543                 printf("DDB: db_inst_branch_taken on non-branch!\n");
544                 newpc = pc;     /* XXX */
545         }
546
547         return (newpc);
548 }