[xtensa-cvscommit] linux/arch/xtensa/kernel Makefile,1.1.1.1,1.2 gdb-stub.c,1.1.1.1,1.2 handlers.S,1
Brought to you by:
zankel
|
From: <sfo...@us...> - 2002-09-19 07:06:15
|
Update of /cvsroot/xtensa/linux/arch/xtensa/kernel
In directory usw-pr-cvs1:/tmp/cvs-serv975/arch/xtensa/kernel
Modified Files:
Makefile gdb-stub.c handlers.S ptrace.c traps.c
Log Message:
First functional checkin of kgdb. Reading AR registers does not work yet. (Reading A registers works.)
Currently uses ttyS1 at 9600 8N1. Serial port and baud rate to become paramterized.
To use, must have CONFIGURE_KGDB. Must also pass the parameter "gdb" to the kernel to tell it to stop on boot and wait for a connection from gdb.
Index: Makefile
===================================================================
RCS file: /cvsroot/xtensa/linux/arch/xtensa/kernel/Makefile,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -C2 -d -r1.1.1.1 -r1.2
*** Makefile 28 Aug 2002 16:10:14 -0000 1.1.1.1
--- Makefile 19 Sep 2002 07:06:11 -0000 1.2
***************
*** 19,23 ****
# obj-$(CONFIG_BOOTSTRAP) += bootstrap.o
! obj-$(CONFIG_XTENSA_REMOTE_DEBUG) += gdb-stub.o
obj-$(CONFIG_PCI) += pci-dma.o pcibios.o
obj-$(CONFIG_PROC_FS) += proc.o
--- 19,23 ----
# obj-$(CONFIG_BOOTSTRAP) += bootstrap.o
! obj-$(CONFIG_KGDB) += gdb-stub.o
obj-$(CONFIG_PCI) += pci-dma.o pcibios.o
obj-$(CONFIG_PROC_FS) += proc.o
Index: gdb-stub.c
===================================================================
RCS file: /cvsroot/xtensa/linux/arch/xtensa/kernel/gdb-stub.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -C2 -d -r1.1.1.1 -r1.2
*** gdb-stub.c 28 Aug 2002 16:10:14 -0000 1.1.1.1
--- gdb-stub.c 19 Sep 2002 07:06:11 -0000 1.2
***************
*** 1,17 ****
/*
! * arch/mips/kernel/gdb-stub.c
! *
! * Originally written by Glenn Engel, Lake Stevens Instrument Division
! *
! * Contributed by HP Systems
! *
! * Modified for SPARC by Stu Grossman, Cygnus Support.
*
! * Modified for Linux/MIPS (and MIPS in general) by Andreas Busse
! * Send complaints, suggestions etc. to <an...@wa...>
*
! * Copyright (C) 1995 Andreas Busse
*
! * Modified for Linux/Xtensa by Scott Foehner <sfo...@te...>
*/
--- 1,13 ----
/*
! * arch/xtensa/gdb-stub.c
*
! * Derived from MIPS.
*
! * This file is subject to the terms and conditions of the GNU General Public
! * License. See the file "COPYING" in the main directory of this archive
! * for more details.
*
! * Copyright (C) 2001 Tensilica Inc.
! * Authors: Scott Foehner <sfo...@te...>
*/
***************
*** 29,32 ****
--- 25,32 ----
* command function Return value
*
+ * pNN..NN return the value of register hex data or ENN
+ * number NN..NN
+ * PNN..NN:V..V set the value of register number OK or ENN
+ * NN..NN to value V..V
* g return the value of the CPU registers hex data or ENN
* G set the value of the CPU registers OK or ENN
***************
*** 41,50 ****
* sAA..AA Step one instruction from AA..AA SNN
*
! * k kill
*
* ? What was the last sigval ? SNN (signal NN)
*
- * bBB..BB Set baud rate to BB..BB OK or BNN, then sets
- * baud rate
*
* All commands and responses are sent with a packet which includes a
--- 41,50 ----
* sAA..AA Step one instruction from AA..AA SNN
*
! * k kill -- ignored
! *
! * D detach -- resume execution
*
* ? What was the last sigval ? SNN (signal NN)
*
*
* All commands and responses are sent with a packet which includes a
***************
*** 65,123 ****
* $m0,10#2a +$00010203040506070809101112131415#42
*
- *
- * ==============
- * MORE EXAMPLES:
- * ==============
- *
- * For reference -- the following are the steps that one
- * company took (RidgeRun Inc) to get remote gdb debugging
- * going. In this scenario the host machine was a PC and the
- * target platform was a Galileo EVB64120A MIPS evaluation
- * board.
- *
- * Step 1:
- * First download gdb-5.0.tar.gz from the internet.
- * and then build/install the package.
- *
- * Example:
- * $ tar zxf gdb-5.0.tar.gz
- * $ cd gdb-5.0
- * $ ./configure --target=mips-linux-elf
- * $ make
- * $ install
- * $ which mips-linux-elf-gdb
- * /usr/local/bin/mips-linux-elf-gdb
- *
- * Step 2:
- * Configure linux for remote debugging and build it.
- *
- * Example:
- * $ cd ~/linux
- * $ make menuconfig <go to "Kernel Hacking" and turn on remote debugging>
- * $ make dep; make vmlinux
- *
- * Step 3:
- * Download the kernel to the remote target and start
- * the kernel running. It will promptly halt and wait
- * for the host gdb session to connect. It does this
- * since the "Kernel Hacking" option has defined
- * CONFIG_REMOTE_DEBUG which in turn enables your calls
- * to:
- * set_debug_traps();
- * breakpoint();
- *
- * Step 4:
- * Start the gdb session on the host.
- *
- * Example:
- * $ mips-linux-elf-gdb vmlinux
- * (gdb) set remotebaud 115200
- * (gdb) target remote /dev/ttyS1
- * ...at this point you are connected to
- * the remote target and can use gdb
- * in the normal fasion. Setting
- * breakpoints, single stepping,
- * printing variables, etc.
- *
*/
--- 65,68 ----
***************
*** 133,136 ****
--- 78,82 ----
#include <asm/pgtable.h>
#include <asm/system.h>
+ #include <asm/ptrace.h>
/*
***************
*** 140,144 ****
extern int putDebugChar(char c); /* write a single character */
extern char getDebugChar(void); /* read and return a single char */
- extern void trap_low(void);
/*
--- 86,89 ----
***************
*** 147,151 ****
extern void breakpoint(void);
extern void breakinst(void);
- extern void adel(void);
/*
--- 92,95 ----
***************
*** 172,175 ****
--- 116,130 ----
static const char hexchars[]="0123456789abcdef";
+ int gdb_enter = 0; /* when set, kernel waits for connection from gdb on boot */
+
+ int kernel_single_step = 0; /* when set, kernel should single step */
+
+ /* saved_ar_regs provide a buffer to save the ar registers on debug
+ * exceptions. */
+ int saved_ar_regs[XCHAL_NUM_AREGS];
+ /* return_from_debug_flag is used to signal the exception handler to restore
+ * the ar registers from saved_ar_regs on return. */
+ int return_from_debug_flag = 0;
+
/* Used to prevent crashes in memory access. Note that they'll crash anyway if
we haven't set up fault handlers yet... */
***************
*** 316,321 ****
* Return a pointer to the last char put in buf (null), in case of mem fault,
* return 0.
! * may_fault is non-zero if we are reading from arbitrary memory, but is currently
! * not used.
*/
static unsigned char *mem2hex(char *mem, char *buf, int count, int may_fault)
--- 271,276 ----
* Return a pointer to the last char put in buf (null), in case of mem fault,
* return 0.
! * may_fault is non-zero if we are reading from arbitrary memory, but is
! * currently not used.
*/
static unsigned char *mem2hex(char *mem, char *buf, int count, int may_fault)
***************
*** 337,343 ****
/*
* convert the hex array pointed to by buf into binary to be placed in mem
! * return a pointer to the character AFTER the last byte written
! * may_fault is non-zero if we are reading from arbitrary memory, but is currently
! * not used.
*/
static char *hex2mem(char *buf, char *mem, int count, int may_fault)
--- 292,298 ----
/*
* convert the hex array pointed to by buf into binary to be placed in mem
! * Return a pointer to the character AFTER the last byte written
! * may_fault is non-zero if we are reading from arbitrary memory, but is
! * currently not used.
*/
static char *hex2mem(char *buf, char *mem, int count, int may_fault)
***************
*** 380,401 ****
};
- /* Save the normal trap handlers for user-mode traps. */
- void *saved_vectors[32];
/*
* Set up exception handlers for tracing and breakpoints
*/
void set_debug_traps(void)
{
- struct hard_trap_info *ht;
unsigned long flags;
unsigned char c;
- save_and_cli(flags);
#if 0
! for (ht = hard_trap_info; ht->tt && ht->signo; ht++)
! saved_vectors[ht->tt] = set_except_vector(ht->tt, trap_low);
#endif
!
putDebugChar('+'); /* 'hello world' */
/*
--- 335,355 ----
};
/*
* Set up exception handlers for tracing and breakpoints
+ *
+ * Linux/Xtensa has a dedicated debug handler that is always there, so we don't
+ * have to set up a handler here.
*/
void set_debug_traps(void)
{
unsigned long flags;
unsigned char c;
#if 0
! printk("in set_debug_traps\n");
#endif
! save_and_cli(flags);
!
putDebugChar('+'); /* 'hello world' */
/*
***************
*** 403,406 ****
--- 357,361 ----
* (presumably "$?#xx") sitting there.
*/
+ #if 0
while((c = getDebugChar()) != '$');
while((c = getDebugChar()) != '#');
***************
*** 408,411 ****
--- 363,367 ----
c = getDebugChar(); /* eat second csum byte */
putDebugChar('+'); /* ack it */
+ #endif
initialized = 1;
***************
*** 453,487 ****
- #if 0
- /*
- * Print registers (on target console)
- * Used only to debug the stub...
- */
- void show_gdbregs(struct gdb_regs * regs)
- {
- /*
- * Saved main processor registers
- */
- printk("$0 : %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n",
- regs->reg0, regs->reg1, regs->reg2, regs->reg3,
- regs->reg4, regs->reg5, regs->reg6, regs->reg7);
- printk("$8 : %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n",
- regs->reg8, regs->reg9, regs->reg10, regs->reg11,
- regs->reg12, regs->reg13, regs->reg14, regs->reg15);
- printk("$16: %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n",
- regs->reg16, regs->reg17, regs->reg18, regs->reg19,
- regs->reg20, regs->reg21, regs->reg22, regs->reg23);
- printk("$24: %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n",
- regs->reg24, regs->reg25, regs->reg26, regs->reg27,
- regs->reg28, regs->reg29, regs->reg30, regs->reg31);
-
- /*
- * Saved cp0 registers
- */
- printk("epc : %08lx\nStatus: %08lx\nCause : %08lx\n",
- regs->cp0_epc, regs->cp0_status, regs->cp0_cause);
- }
- #endif /* dead code */
-
/*
* We single-step by setting breakpoints. When an exception
--- 409,412 ----
***************
*** 616,624 ****
char *ptr;
unsigned long *stack;
- printk("in handle_exception()\n");
#if 0
! show_gdbregs(regs);
#endif
#if 0
--- 541,567 ----
char *ptr;
unsigned long *stack;
+ unsigned regno;
+ int value;
+ int ar_reg, a_reg, first_pane;
+ extern int find_first_pane(int, int);
+
+ kernel_single_step = 0;
#if 0
! putDebugChar('S');
! putDebugChar('C');
! putDebugChar('O');
! putDebugChar('T');
! putDebugChar('T');
! putDebugChar('\n');
! #endif
! #if 0
! printk("in gdb_handle_exception()\n");
#endif
+ /*
+ * If we're in breakpoint() increment the PC
+ */
+ if (regs->pc == (unsigned long)breakinst)
+ regs->pc += 3; /* breakpoint() uses a 3-byte break insn */
#if 0
***************
*** 714,717 ****
--- 657,671 ----
putpacket(output_buffer); /* send it off... */
+ #endif
+
+ sigval = 5;
+ ptr = output_buffer;
+
+ *ptr++ = 'S';
+ *ptr++ = hexchars[sigval >> 4];
+ *ptr++ = hexchars[sigval & 0xf];
+ *ptr++ = 0;
+ putpacket(output_buffer); /* send it off... */
+
/*
* Wait for input from remote GDB
***************
*** 738,741 ****
--- 692,696 ----
*/
case 'g':
+ #if 0
ptr = output_buffer;
ptr = mem2hex((char *)®s->reg0, ptr, 32*4, 0); /* r0...r31 */
***************
*** 745,748 ****
--- 700,704 ----
ptr = mem2hex((char *)®s->frame_ptr, ptr, 2*4, 0); /* frp */
ptr = mem2hex((char *)®s->cp0_index, ptr, 16*4, 0); /* cp0 */
+ #endif
break;
***************
*** 806,809 ****
--- 762,775 ----
else
strcpy(output_buffer, "E02");
+
+ /* We need to write back any data in the writeback
+ * cache, and invalidate the instruction cache, in
+ * case we are writing instructions to memory. */
+ /* For now, writeback/invalidate the whole cache,
+ * although we should probably only do the appropriate
+ * line (or lines). */
+ xthal_dcache_all_writeback();
+ xthal_icache_all_invalidate();
+
break;
***************
*** 814,820 ****
--- 780,788 ----
/* try to read optional parameter, pc unchanged if no parm */
+ #if 0
ptr = &input_buffer[1];
if (hexToInt(&ptr, &addr))
regs->cp0_epc = addr;
+ #endif
/*
***************
*** 832,848 ****
break;
-
/*
! * kill the program
*/
! case 'k' :
! break; /* do nothing */
/*
! * Reset the whole machine (FIXME: system dependent)
*/
! case 'r':
! break;
--- 800,816 ----
break;
/*
! * Detach and continue running
*/
! case 'D':
! return; /* resume execution */
+ /* NOTREACHED */
/*
! * kill the program
*/
! case 'k':
! break; /* do nothing */
***************
*** 855,907 ****
* use breakpoints and continue, instead.
*/
! single_step(regs);
! flush_cache_all();
return;
/* NOTREACHED */
- /*
- * Set baud rate (bBB)
- * FIXME: Needs to be written
- */
- case 'b':
- {
- #if 0
- int baudrate;
- extern void set_timer_3();
! ptr = &input_buffer[1];
! if (!hexToInt(&ptr, &baudrate))
! {
! strcpy(output_buffer,"B01");
! break;
! }
! /* Convert baud rate to uart clock divider */
! switch (baudrate)
! {
! case 38400:
! baudrate = 16;
! break;
! case 19200:
! baudrate = 33;
! break;
! case 9600:
! baudrate = 65;
! break;
! default:
! baudrate = 0;
! strcpy(output_buffer,"B02");
! goto x1;
! }
! if (baudrate) {
! putpacket("OK"); /* Ack before changing speed */
! set_timer_3(baudrate); /* Set it */
! }
#endif
! }
break;
} /* switch */
--- 823,1031 ----
* use breakpoints and continue, instead.
*/
!
! kernel_single_step = 1;
return;
+
/* NOTREACHED */
! case 'H':
! output_buffer[0] = 'O';
! output_buffer[1] = 'K';
! output_buffer[2] = 0;
! break;
! case 'p':
! ptr = &input_buffer[1];
! hexToInt(&ptr, ®no);
! #if 0
! printk("p regno: 0x%x\n", regno);
! #endif
! switch(regno) {
! case REG_A_BASE ... REG_A_BASE + 15:
! mem2hex((char *)&(regs->aregs[regno - REG_A_BASE]),
! output_buffer, 4, 0);
! break;
! case REG_AR_BASE ... REG_AR_BASE + XCHAL_NUM_AREGS - 1:
! /* If we want one of the AR regs that falls within
! * the register window, we should get the
! * corresponding A reg. */
! ar_reg = regno - REG_AR_BASE;
! a_reg = AR_REGNO_TO_A_REGNO(ar_reg, regs->wb);
! first_pane = find_first_pane(regs->wb, regs->ws);
! if (a_reg < 16) {
! mem2hex((char *)&(regs->aregs[a_reg]),
! output_buffer, 4, 0);
! }
! #if 1
! else
! strcpy(output_buffer, "E01");
! #else
! else if(a_reg >= first_pane*4) {
! if(first_pane < 0)
! strcpy(output_buffer, "E01");
! else
! #endif
! #if 0
! mem2hex((char *)&(regs->aregs[regno - REG_AR_BASE - regs->wb]), output_buffer, 4, 0);
! #endif
! break;
!
! case REG_PC:
! mem2hex((char *)&(regs->pc), output_buffer, 4, 0);
! break;
! case REG_PS:
! mem2hex((char *)&(regs->ps), output_buffer, 4, 0);
! break;
!
! case REG_WB:
! mem2hex((char *)&(regs->wb), output_buffer, 4, 0);
! break;
!
! case REG_WS:
! mem2hex((char *)&(regs->ws), output_buffer, 4, 0);
! break;
!
! case REG_LBEG:
! mem2hex((char *)&(regs->lbeg), output_buffer, 4, 0);
! break;
!
! case REG_LEND:
! mem2hex((char *)&(regs->lend), output_buffer, 4, 0);
! break;
!
! case REG_LCOUNT:
! mem2hex((char *)&(regs->lcount), output_buffer, 4, 0);
! break;
!
! case REG_SAR:
! mem2hex((char *)&(regs->sar), output_buffer, 4, 0);
! break;
!
! case REG_DEPC:
! mem2hex((char *)&(regs->depc), output_buffer, 4, 0);
! break;
!
! case REG_EXCCAUSE:
! mem2hex((char *)&(regs->exccause), output_buffer, 4, 0);
! break;
!
! case REG_EXCVADDR:
! mem2hex((char *)&(regs->excvaddr), output_buffer, 4, 0);
! break;
!
! default:
! strcpy(output_buffer,"ffffffff");
! break;
! }
! break;
!
! case 'P':
! ptr = &input_buffer[1];
! #if 0
! printk("P %s\n", input_buffer);
#endif
! if (hexToInt(&ptr, ®no) && *ptr++ == '='
! && hexToInt(&ptr, &value)) {
! strcpy(output_buffer, "OK");
! } else {
! strcpy(output_buffer, "E01");
! break;
! }
!
! ptr = &input_buffer[1];
! hexToInt(&ptr, ®no);
! printk("P regno: 0x%x\n", regno);
! switch(regno) {
! case REG_A_BASE ... REG_A_BASE + 15:
! mem2hex((char *)&(regs->aregs[regno - REG_A_BASE]),
! output_buffer, 4, 0);
! break;
!
! case REG_AR_BASE ... REG_AR_BASE + XCHAL_NUM_AREGS - 1:
! mem2hex((char *)&(regs->aregs[regno - REG_AR_BASE - regs->wb]), output_buffer, 4, 0);
! break;
!
! case REG_PC:
! regs->pc = value;
! break;
!
! case REG_PS:
! mem2hex((char *)&(regs->ps), output_buffer, 4, 0);
! break;
!
! case REG_WB:
! mem2hex((char *)&(regs->wb), output_buffer, 4, 0);
! break;
!
! case REG_WS:
! mem2hex((char *)&(regs->ws), output_buffer, 4, 0);
! break;
!
! case REG_LBEG:
! mem2hex((char *)&(regs->lbeg), output_buffer, 4, 0);
! break;
!
! case REG_LEND:
! mem2hex((char *)&(regs->lend), output_buffer, 4, 0);
! break;
!
! case REG_LCOUNT:
! mem2hex((char *)&(regs->lcount), output_buffer, 4, 0);
! break;
!
! case REG_SAR:
! mem2hex((char *)&(regs->sar), output_buffer, 4, 0);
! break;
!
! case REG_DEPC:
! mem2hex((char *)&(regs->depc), output_buffer, 4, 0);
! break;
!
! case REG_EXCCAUSE:
! mem2hex((char *)&(regs->exccause), output_buffer, 4, 0);
! break;
!
! case REG_EXCVADDR:
! mem2hex((char *)&(regs->excvaddr), output_buffer, 4, 0);
! break;
!
! default:
! strcpy(output_buffer,"E01");
! break;
! }
! break;
!
! case 'q':
! if (!strncmp(input_buffer, "qxtn", 4)) {
! #if 0
! output_buffer[0] = 'L';
! output_buffer[1] = 'i';
! output_buffer[2] = 'n';
! output_buffer[3] = 'u';
! output_buffer[4] = 'x';
! output_buffer[5] = 0;
! #else
! output_buffer[0] = 'I';
! output_buffer[1] = 'S';
! output_buffer[2] = 'S';
! output_buffer[3] = '3';
! output_buffer[4] = 0;
! #endif
! strcpy(output_buffer, "XMON2.5");
! }
break;
+ case 'Q':
+ if (!strncmp(input_buffer, "Qxtcs", 4)) {
+ /* We just ignore the toggle save command. Linux
+ * always saves its registers. */
+ output_buffer[0] = 'O';
+ output_buffer[1] = 'K';
+ output_buffer[2] = 0;
+ }
+ break;
} /* switch */
***************
*** 913,917 ****
} /* while */
- #endif
}
--- 1037,1040 ----
***************
*** 926,995 ****
if (!initialized)
return;
-
- printk("In breakpoint() function\n");
#if 0
! __asm__ __volatile__("
! .globl breakinst
! .set noreorder
! nop
! breakinst: break
! nop
! .set reorder
! ");
#endif
! }
!
! #if 0
! void adel(void)
! {
! __asm__ __volatile__("
! .globl adel
! la $8,0x80000001
! lw $9,0($8)
");
}
- #endif
-
- #ifdef CONFIG_GDB_CONSOLE
-
- void gdb_puts(const char *str)
- {
- int l = strlen(str);
- char outbuf[18];
-
- outbuf[0]='O';
-
- while(l) {
- int i = (l>8)?8:l;
- mem2hex((char *)str, &outbuf[1], i, 0);
- outbuf[(i*2)+1]=0;
- putpacket(outbuf);
- str += i;
- l -= i;
- }
- }
- static kdev_t gdb_console_dev(struct console *con)
- {
- return MKDEV(1, 3); /* /dev/null */
- }
! static void gdb_console_write(struct console *con, const char *s, unsigned n)
{
! gdb_puts(s);
}
! static struct console gdb_console = {
! name: "gdb",
! write: gdb_console_write,
! device: gdb_console_dev,
! flags: CON_PRINTBUFFER,
! index: -1
! };
- __init void register_gdb_console(void)
- {
- register_console(&gdb_console);
- }
-
- #endif
--- 1049,1067 ----
if (!initialized)
return;
#if 0
! printk("In breakpoint() function\n");
#endif
! __asm__ __volatile__(" \
! breakinst: break 0, 0\n \
");
}
! static int __init kgdb_opt_gdb(void)
{
! gdb_enter = 1;
! return 1;
}
! __setup("gdb", kgdb_opt_gdb);
Index: handlers.S
===================================================================
RCS file: /cvsroot/xtensa/linux/arch/xtensa/kernel/handlers.S,v
retrieving revision 1.2
retrieving revision 1.3
diff -C2 -d -r1.2 -r1.3
*** handlers.S 29 Aug 2002 21:45:01 -0000 1.2
--- handlers.S 19 Sep 2002 07:06:11 -0000 1.3
***************
*** 16,19 ****
--- 16,20 ----
* Authors: Marc Gauthier
* Joe Taylor <jo...@te..., jo...@ya...>
+ * Scott Foehner <sfo...@te...> (debug handler)
*/
***************
*** 83,86 ****
--- 84,88 ----
.comm kernelsp,4,4 /* kernel stack pointer */
+ .comm kernel_single_step,4,4
***************
*** 584,591 ****
* and natively debugging is not allowed.)
*/
_GET_CURRENT a2
l32i a3, a2, TASK_PTRACE
extui a3, a3, 16, 1 // extract PT_SINGLESTEP flag
! beqz a3, 1f // flag not set
movi a2, 0
wsr a2, ICOUNTLEVEL // turn off instruction counting
--- 586,602 ----
* and natively debugging is not allowed.)
*/
+
+ #if 1
+ rsr a2, DEBUGCAUSE
+ s32i a2, a1, PT_RESERVED1
+ #endif
+
_GET_CURRENT a2
l32i a3, a2, TASK_PTRACE
extui a3, a3, 16, 1 // extract PT_SINGLESTEP flag
! movi a2, kernel_single_step // get kernel stepping flag
! l32i a2, a2, 0
! or a3, a3, a2 // if either set, turn of icounting
! beqz a3, 1f // flags not set
movi a2, 0
wsr a2, ICOUNTLEVEL // turn off instruction counting
***************
*** 1400,1404 ****
// PT_SINGLESTEP is set by sys_ptrace (ptrace.c)
! // Only enable single stepping if returning from a user exception
#if EXCTYPE_USER
bnei a0, EXCTYPE_USER, 4f // Hack around lack of bnei relaxation
--- 1411,1417 ----
// PT_SINGLESTEP is set by sys_ptrace (ptrace.c)
! // Only enable single stepping if returning from a user exception,
! // or it's a kernel exception, and kernel_single_step is set.
! beqi a0, EXCTYPE_KERNEL, 1f // returning from kernel exception?
#if EXCTYPE_USER
bnei a0, EXCTYPE_USER, 4f // Hack around lack of bnei relaxation
***************
*** 1409,1414 ****
l32i a3, a2, TASK_PTRACE
extui a3, a3, 16, 1 // extract PT_SINGLESTEP flag
! beqz a3, 4f // flag not set
movi a3, -2 // PT_SINGLESTEP flag is set,
wsr a3, ICOUNT // so setup icount & icountlevel.
--- 1422,1436 ----
l32i a3, a2, TASK_PTRACE
extui a3, a3, 16, 1 // extract PT_SINGLESTEP flag
! bnez a3, 2f // flag set
! 1:
! movi a3, kernel_single_step // see if kernel should single step
! l32i a3, a3, 0
! beqz a3, 4f // nope
! #if 0
! mov a1, a3
! j CriticalExc
! #endif
+ 2:
movi a3, -2 // PT_SINGLESTEP flag is set,
wsr a3, ICOUNT // so setup icount & icountlevel.
***************
*** 1971,1978 ****
--- 1993,2012 ----
wsr a0, EPC_1 // generic exception code.
rsr a0, EPS + XCHAL_DEBUGLEVEL // Put PS wth EXCM on into PS
+
+ #if 1
+ s32i a0, a1, PT_RESERVED0
+ #endif
+
addi a0, a0, XCHAL_PS_EXCM_MASK // for the generic exception
wsr a0, PS // code.
isync
+ #ifdef CONFIG_KGDB
+ // Save all the ar registers on a debug exception.
+ j debug_save_ar_regs
+
+ dsar_ret:
+ #endif
+
movi a0, handle_debug // re-setup handler and
xsr a0, EXCSAVE + XCHAL_DEBUGLEVEL // restore a0
***************
*** 1984,1987 ****
--- 2018,2028 ----
j _excCommonException // jump to common exception code
+
+ #ifdef CONFIG_KGDB
+ // This just saves all the ar registers sequentially on debug exceptions.
+ debug_save_ar_regs:
+
+ j dsar_ret
+ #endif // CONFIG_KGDB
/* Only if coprocessors exist to we include handlers for Coprocessor
Index: ptrace.c
===================================================================
RCS file: /cvsroot/xtensa/linux/arch/xtensa/kernel/ptrace.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -C2 -d -r1.1.1.1 -r1.2
*** ptrace.c 28 Aug 2002 16:10:14 -0000 1.1.1.1
--- ptrace.c 19 Sep 2002 07:06:12 -0000 1.2
***************
*** 30,39 ****
#define PT_SINGLESTEP 0x10000
- /* Note: can return illegal A reg numbers, i.e. > 15 */
- #define AR_REGNO_TO_A_REGNO(ar_regno, wb) \
- ((ar_regno - wb*4) >= 0 ? \
- ar_regno - wb*4 : \
- XCHAL_NUM_AREGS + ar_regno - wb*4)
-
/* Given a valid wb and ws, find the first valid "pane" */
/* Pane is given as the distance from pane 0, which is wb */
--- 30,33 ----
Index: traps.c
===================================================================
RCS file: /cvsroot/xtensa/linux/arch/xtensa/kernel/traps.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -C2 -d -r1.1.1.1 -r1.2
*** traps.c 28 Aug 2002 16:10:14 -0000 1.1.1.1
--- traps.c 19 Sep 2002 07:06:12 -0000 1.2
***************
*** 10,14 ****
* Complete output from die() by Ulf Carlsson, 1998
* Copyright (C) 1999 Silicon Graphics, Inc.
! * Copyright (C) 2001 Tensilica Inc., by Joe Taylor, Kevin Chea, Marc Gauthier
*/
--- 10,15 ----
* Complete output from die() by Ulf Carlsson, 1998
* Copyright (C) 1999 Silicon Graphics, Inc.
! * Copyright (C) 2001 Tensilica Inc., by Joe Taylor, Kevin Chea, Marc Gauthier,
! * Scott Foehner
*/
***************
*** 24,27 ****
--- 25,32 ----
#include <asm/xtutil.h>
+ #ifdef CONFIG_KGDB
+ extern int gdb_enter;
+ extern int return_from_debug_flag;
+ #endif
/*
***************
*** 256,295 ****
{
int i;
- #if 0
- printk("\nKERNEL: DO DEBUG\n\n");
- #endif
#if 0
! printk("DEBUGCAUSE: 0x%x ", regs->reserved1);
if(regs->reserved1 & DEBUGCAUSE_DEBUGINT_MASK)
! printk("debug interrupt\n");
if(regs->reserved1 & DEBUGCAUSE_BREAKN_MASK)
! printk("break.n\n");
if(regs->reserved1 & DEBUGCAUSE_BREAK_MASK)
! printk("break\n");
if(regs->reserved1 & DEBUGCAUSE_DBREAK_MASK)
! printk("dbreak\n");
if(regs->reserved1 & DEBUGCAUSE_IBREAK_MASK)
! printk("ibreak\n");
if(regs->reserved1 & DEBUGCAUSE_ICOUNT_MASK)
! printk("icount\n");
! printk("PS: 0x%x\n", regs->ps);
! printk("PTRACE: 0x%x\n", current->ptrace);
#endif
if (user_mode(regs)) {
- /* KGDB: Probably want to put a hook here to kgdb if it is
- * enabled */
/* If in user mode, send SIGTRAP signal to current process */
#if 0
! printk("KERNEL: Breakpoint at '%s' (pid = %d, pc = %#010x)\n",
current->comm, current->pid, regs->pc);
#endif
#if 0
for (i = 0; i < 16; i++) {
! printk("KERNEL: a%02d: 0x%08x\n", i, regs->aregs[i]);
}
#endif
--- 261,314 ----
{
int i;
#if 0
! printk("\nDEBUGCAUSE: 0x%x ", regs->reserved1);
if(regs->reserved1 & DEBUGCAUSE_DEBUGINT_MASK)
! printk("debug interrupt ");
if(regs->reserved1 & DEBUGCAUSE_BREAKN_MASK)
! printk("break.n ");
if(regs->reserved1 & DEBUGCAUSE_BREAK_MASK)
! printk("break ");
if(regs->reserved1 & DEBUGCAUSE_DBREAK_MASK)
! printk("dbreak ");
if(regs->reserved1 & DEBUGCAUSE_IBREAK_MASK)
! printk("ibreak ");
if(regs->reserved1 & DEBUGCAUSE_ICOUNT_MASK)
! printk("icount ");
! printk("PS: 0x%x ", regs->ps);
! printk("ORIG_PS: 0x%x ", regs->reserved0);
! printk("PTRACE: 0x%x ", current->ptrace);
!
! printk("\n");
! #endif
!
! /* If remote debugging is configured AND enabled, we give control to
! * kgdb. Otherwise, we fall through, perhaps giving control to the
! * native debugger. */
! #ifdef CONFIG_KGDB
! if (gdb_enter) {
! extern void gdb_handle_exception(struct pt_regs *);
! gdb_handle_exception(regs);
! return_from_debug_flag = 1;
! return;
! }
#endif
if (user_mode(regs)) {
/* If in user mode, send SIGTRAP signal to current process */
#if 0
! printk("KERNEL: User break at '%s' (pid = %d, pc = %#010x)\n",
current->comm, current->pid, regs->pc);
#endif
#if 0
for (i = 0; i < 16; i++) {
! if ((i % 4) == 0)
! printk("KERNEL: ");
! printk("a%02d: 0x%08x ", i, regs->aregs[i]);
! if ((i % 4) == 3)
! printk("\n");
}
#endif
***************
*** 297,306 ****
} else {
- /* KGDB: Probably want to put a hook here to kgdb if it is
- * enabled */
-
/* If in kernel mode, we're in trouble,
* unless kgdb is enabled */
! #if 0
panic("Breakpoint in kernel (pc = %#010x)", regs->pc);
#else
--- 316,322 ----
} else {
/* If in kernel mode, we're in trouble,
* unless kgdb is enabled */
! #if 1
panic("Breakpoint in kernel (pc = %#010x)", regs->pc);
#else
|