patch-2.4.4 linux/arch/cris/kernel/traps.c

Next file: linux/arch/cris/lib/checksum.S
Previous file: linux/arch/cris/kernel/sys_cris.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.4.3/linux/arch/cris/kernel/traps.c linux/arch/cris/kernel/traps.c
@@ -1,16 +1,19 @@
-/* $Id: traps.c,v 1.3 2000/10/04 16:50:06 bjornw Exp $
+/* $Id: traps.c,v 1.8 2001/02/23 13:45:20 bjornw Exp $
  *
  *  linux/arch/cris/traps.c
  *
- *  Etrax100 does not have any hardware traps, only IRQ's, which we setup
- *  in irq.c instead. Here we just define the die_if_kernel Oops'er.
- *
- *  Copyright (C) 2000 Axis Communications AB
+ *  Here we handle the break vectors not used by the system call 
+ *  mechanism, as well as some general stack/register dumping 
+ *  things.
+ * 
+ *  Copyright (C) 2000,2001 Axis Communications AB
  *
  *  Authors:   Bjorn Wesen
+ *             Orjan Friberg
  *
  */
 
+#include <linux/config.h>
 #include <linux/init.h>
 #include <linux/sched.h>
 #include <linux/kernel.h>
@@ -35,7 +38,8 @@
 
 #define MODULE_RANGE (8*1024*1024)
 
-void show_stack(unsigned long *sp)
+void 
+show_stack(unsigned long *sp)
 {
         unsigned long *stack, addr, module_start, module_end;
         int i;
@@ -86,7 +90,8 @@
 #if 0
 /* displays a short stack trace */
 
-int show_stack()
+int 
+show_stack()
 {
 	unsigned long *sp = (unsigned long *)rdusp();
 	int i;
@@ -97,7 +102,8 @@
 }
 #endif
 
-void show_registers(struct pt_regs * regs)
+void 
+show_registers(struct pt_regs * regs)
 {
 	unsigned long usp = rdusp();
 
@@ -145,9 +151,8 @@
 #endif
 }
 
-
-
-void die_if_kernel(const char * str, struct pt_regs * regs, long err)
+void 
+die_if_kernel(const char * str, struct pt_regs * regs, long err)
 {
 	if(user_mode(regs))
 		return;
@@ -160,8 +165,68 @@
 	do_exit(SIGSEGV);
 }
 
-void __init trap_init(void)
+void __init 
+trap_init(void)
 {
-  
 
 }
+
+/* Use static variables instead of the stack for temporary storage.  */
+static int saved_r0 = 0;
+static int saved_dccr = 0;
+
+asm ("
+  .global _gdb_handle_breakpoint
+  .global _do_sigtrap
+_gdb_handle_breakpoint:
+;;
+;; This handles a break instruction for entering a debug session.
+;;
+  move     dccr,[_saved_dccr]       ; Save dccr.
+  move.d   r0,[_saved_r0]           ; Save r0. "
+#ifdef CONFIG_KGDB
+" 
+  move     ccr,r0                   
+  btstq    8,r0                     ; Test the U-flag.
+  bmi      _ugdb_handle_breakpoint  ; Go to user mode debugging.
+  nop                               ; Delay slot.
+  move.d   [_saved_r0],r0           ; Restore r0.
+  move     [_saved_dccr],dccr       ; Restore dccr.
+  ba       _kgdb_handle_breakpoint  ; Go to kernel debugging.
+  nop                               ; Delay slot. "
+#endif
+" 
+_ugdb_handle_breakpoint:
+;;
+;; Yes, we could do a 'push brp' here and let gdb adjust the pc once it
+;; starts talking to the target again, but this way we avoid a 'P' packet.
+;;
+  move     brp,r0               ; Use r0 temporarily for calculation.
+  subq     2,r0                 ; Set to address of previous instruction.
+  move     r0,brp               ; Restore new brp.
+  move.d   [_saved_r0],r0       ; Restore r0.
+  move     [_saved_dccr],dccr   ; Restore dccr.
+
+_do_sigtrap:
+;; 
+;; SIGTRAP the process that executed the break instruction.
+;; Make a frame that Rexit in entry.S expects.
+;;
+  push     brp                  ; Push breakpoint return pointer.
+  push     srp                  ; Push subroutine return pointer.
+  push     dccr                 ; Push condition codes.
+  push     mof                  ; Push multiply overflow reg.
+  di                            ; Need to disable irq's at this point.
+  subq     14*4,sp              ; Make room for r0-r13.
+  movem    r13,[sp]             ; Push the r0-r13 registers.
+  push     r10                  ; Push orig_r10.
+  clear.d  [sp=sp-4]            ; Frametype - this is a normal stackframe.
+
+  movs.w   -8192,r9             ; THREAD_SIZE == 8192
+  and.d    sp,r9
+  move.d   [r9+LTASK_PID],r10   ; current->pid as arg1.
+  moveq    5,r11                ; SIGTRAP as arg2.
+  jsr      _sys_kill       
+
+  jump     _ret_from_intr       ; Use the return routine for interrupts.
+");

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)