diff -rbuN -X exclude-list linux-cb26.orig/arch/arm/Makefile linux-cb26/arch/arm/Makefile --- linux-cb26.orig/arch/arm/Makefile Mon Aug 7 15:28:10 2000 +++ linux-cb26/arch/arm/Makefile Tue Aug 22 18:38:09 2000 @@ -153,6 +153,13 @@ CFLAGS += -g endif +ifeq ($(CONFIG_KGDB),y) +# If configured for kgdb support, don't mix function prologue code +# with body code so gdb's arm-tdep.c:arm_scan_prologue function +# can find frame pointers correctly... +CFLAGS += -fno-schedule-insns -fno-schedule-insns2 +endif + HEAD := arch/arm/kernel/head-$(PROCESSOR).o arch/arm/kernel/init_task.o SUBDIRS := arch/arm/special $(SUBDIRS) arch/arm/lib arch/arm/kernel arch/arm/mm CORE_FILES := arch/arm/kernel/kernel.o arch/arm/mm/mm.o $(CORE_FILES) diff -rbuN -X exclude-list linux-cb26.orig/arch/arm/config.in linux-cb26/arch/arm/config.in --- linux-cb26.orig/arch/arm/config.in Mon Aug 7 15:28:10 2000 +++ linux-cb26/arch/arm/config.in Mon Aug 14 15:55:18 2000 @@ -253,10 +253,16 @@ mainmenu_option next_comment comment 'Kernel hacking' -bool 'Compile kernel with frame pointer (for useful debugging)' CONFIG_FRAME_POINTER +bool 'Remote debugging support' CONFIG_KGDB +if [ "$CONFIG_KGDB" = "y" ]; then + define_bool CONFIG_FRAME_POINTER y + define_bool CONFIG_DEBUG_INFO y +else + bool 'Compile kernel with frame pointer (for useful debugging)' CONFIG_FRAME_POINTER + bool 'Include debugging information in kernel binary' CONFIG_DEBUG_INFO +fi bool 'Verbose kernel error messages' CONFIG_DEBUG_ERRORS bool 'Verbose user fault messages' CONFIG_DEBUG_USER -bool 'Include debugging information in kernel binary' CONFIG_DEBUG_INFO #bool 'Debug kmalloc/kfree' CONFIG_DEBUG_MALLOC bool 'Magic SysRq key' CONFIG_MAGIC_SYSRQ if [ "$CONFIG_CPU_26" = "y" -a "$CONFIG_EXPERIMENTAL" = "y" ]; then diff -rbuN -X exclude-list linux-cb26.orig/arch/arm/kernel/Makefile linux-cb26/arch/arm/kernel/Makefile --- linux-cb26.orig/arch/arm/kernel/Makefile Mon Aug 7 15:28:10 2000 +++ linux-cb26/arch/arm/kernel/Makefile Mon Aug 14 15:59:19 2000 @@ -84,6 +84,10 @@ endif endif +ifeq ($(CONFIG_KGDB),y) + O_OBJS += arm32-stub.o +endif + $(HEAD_OBJ): $(HEAD_OBJ:.o=.S) $(CC) -D__ASSEMBLY__ -DTEXTADDR=$(TEXTADDR) -traditional -c $(HEAD_OBJ:.o=.S) -o $@ diff -rbuN -X exclude-list linux-cb26.orig/arch/arm/kernel/arm32-stub.c linux-cb26/arch/arm/kernel/arm32-stub.c --- linux-cb26.orig/arch/arm/kernel/arm32-stub.c Wed Dec 31 16:00:00 1969 +++ linux-cb26/arch/arm/kernel/arm32-stub.c Mon Aug 28 19:55:17 2000 @@ -0,0 +1,667 @@ +/* + * arch/arm/kernel/arm32-stub.c -- stub for GDB remote debugging protocol + * + * Originally written by Glenn Engel, Lake Stevens Instrumental Division, HP + * Contributed by HP Systems + * + * Modified for usermode ARM debugging by Steve Longerbeam, Communica Inc. + * + * Modified for ARMlinux on Psion Series 5 machines by Noel Cragg + * + * + * The following gdb commands are supported: + * + * command function Return value + * + * g return the value of the CPU registers hex data or ENN + * G set the value of the CPU registers OK or ENN + * + * mAA..AA,LLLL Read LLLL bytes at address AA..AA hex data or ENN + * MAA..AA,LLLL Write LLLL bytes at address AA.AA OK or ENN + * + * c Resume at current address SNN (signal NN) + * cAA..AA Continue at address AA..AA SNN + * + * ? What was the last sigval ? SNN (signal NN) + * + * All commands and responses are sent with a packet which includes a + * checksum. A packet consists of + * + * $#. + * + * where + * :: + * :: > + * + * When a packet is received, it is first acknowledged with either '+' or '-'. + * '+' indicates a successful transfer. '-' indicates a failed transfer. + * + * Example: + * + * Host: Reply: + * $m0,10#2a +$00010203040506070809101112131415#42 + */ + +#include +#include +#include +#include +#include +#include +#if 0 +#include /* for I_BIT -- wrong somehow? */ +#else +#undef I_BIT +#define I_BIT (1 << 27) +#undef F_BIT +#define F_BIT (1 << 26) +#endif + +/* write and read single characters (this code currently lives in + drivers/char/serial_7110.c) */ +extern int putDebugChar (char c); +extern int getDebugChar (void); + +/* BUFMAX defines the maximum number of characters in inbound/outbound + buffers -- at least NUMREGBYTES*2 are needed for register packets */ +#define BUFMAX 400 + +static char initialized; /* nonzero means we've been initialized */ + +static int remote_debug = 0; /* nonzero shows protocol debug messages */ + +static int check_fault = 0; /* flag to check for a memory fault */ + +static volatile int mem_err = 0; /* indicate mem error for mem2hex/hex2mem */ + +static const char hexchars[] = "0123456789abcdef"; + +/* saved user-mode registers, in the order GDB expects them */ +struct +{ + int r0; + int r1; + int r2; + int r3; + int r4; + int r5; + int r6; + int r7; + int r8; + int r9; + int sl; + int fp; + int ip; + int sp; + int lr; + int pc; + unsigned char f[8][12]; + int fps; + int ps; +} +__attribute__ ((packed)) user_regs; + +#define NUMREGBYTES sizeof(user_regs) + +#define flush_i_cache() asm(" mcr p15, 0, r0, c7, c5, 0") +#define BREAKPOINT() asm(" .word 0xe7ffdefe") + + +/**********************************************************************/ +/**********************************************************************/ + + +/* return the int value of a hex character */ + +int +hex (char ch) +{ + if ((ch >= 'a') && (ch <= 'f')) + return (ch - 'a' + 10); + if ((ch >= '0') && (ch <= '9')) + return (ch - '0'); + if ((ch >= 'A') && (ch <= 'F')) + return (ch - 'A' + 10); + return (-1); +} + + +/* get a packet */ + +void +getpacket (char *buffer) +{ + unsigned char checksum; + unsigned char xmitcsum; + int i; + int count; + char ch; + + if (remote_debug) + printk ("getpacket"); + + do + { + /* scan for the sequence $# */ + + if (remote_debug) + printk (":"); + /* wait around for the start character, ignore all other characters */ + while ((ch = (getDebugChar () & 0x7f)) != '$'); + checksum = 0; + xmitcsum = -1; + + count = 0; + + /* now, read until a # or end of buffer is found */ + while (count < BUFMAX) + { + ch = getDebugChar () & 0x7f; + if (ch == '#') + break; + checksum = checksum + ch; + buffer[count] = ch; + count = count + 1; + } + buffer[count] = 0; + + if (ch == '#') + { + xmitcsum = hex (getDebugChar () & 0x7f) << 4; + xmitcsum += hex (getDebugChar () & 0x7f); +#if 0 + if (remote_debug && (checksum != xmitcsum)) + { + printk ("bad checksum. My count = 0x%x, sent=0x%x. buf=%s\n", + checksum, xmitcsum, buffer); + } +#endif + + if (checksum != xmitcsum) + putDebugChar ('-'); /* failed checksum */ + else + { + putDebugChar ('+'); /* successful transfer */ + /* if a sequence char is present, reply the sequence ID */ + if (buffer[2] == ':') + { + putDebugChar (buffer[0]); + putDebugChar (buffer[1]); + /* remove sequence chars from buffer */ + count = strlen (buffer); + for (i = 3; i <= count; i++) + buffer[i - 3] = buffer[i]; + } + } + } + } + while (checksum != xmitcsum); + + if (remote_debug) + printk (" $%s#%c%c\n", + buffer, hexchars[checksum >> 4], hexchars[checksum % 16]); +} + + +/* send a packet */ + +void +putpacket (char *buffer) +{ + unsigned char checksum; + int count; + char ch; + + /* $# */ + do + { + putDebugChar ('$'); + checksum = 0; + count = 0; + + while ((ch = buffer[count])) + { + putDebugChar (ch); + checksum += ch; + count += 1; + } + + putDebugChar ('#'); + putDebugChar (hexchars[checksum >> 4]); + putDebugChar (hexchars[checksum % 16]); + + if (remote_debug) + printk ("putpacket: $%s#%c%c\n", + buffer, hexchars[checksum >> 4], hexchars[checksum % 16]); + + } + while ((getDebugChar () & 0x7f) != '+'); +} + +static char remcomInBuffer[BUFMAX]; +static char remcomOutBuffer[BUFMAX]; +static short error; + + +/* Convert the memory pointed to by mem into hex, placing result in + buf. Return a pointer to the last char put in buf (null). If + MAY_FAULT is non-zero, then we should set mem_err in response to a + fault; if zero treat a fault like any other fault in the stub. */ + +char * +mem2hex (char *mem, char *buf, int count, int may_fault) +{ + int i; + unsigned char ch; + + if (may_fault) + check_fault = 1; + for (i = 0; i < count; i++) + { + ch = *mem++; /* this may cause a fault */ + if (may_fault && mem_err) + return (buf); + *buf++ = hexchars[ch >> 4]; + *buf++ = hexchars[ch % 16]; + } + *buf = 0; + if (may_fault) + check_fault = 0; + return (buf); +} + + +/* 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. */ + +char * +hex2mem (char *buf, char *mem, int count, int may_fault) +{ + int i; + unsigned char ch; + + if (may_fault) + check_fault = 1; + for (i = 0; i < count; i++) + { + ch = hex (*buf++) << 4; + ch = ch + hex (*buf++); + *mem++ = ch; /* this may cause a fault */ + if (may_fault && mem_err) + return (mem); + } + if (may_fault) + check_fault = 0; + return (mem); +} + + +/* convert an ascii hex representation to an int */ + +int +hexToInt (char **ptr, int *intValue) +{ + int numChars = 0; + int hexValue; + + *intValue = 0; + + while (**ptr) + { + hexValue = hex (**ptr); + if (hexValue >= 0) + { + *intValue = (*intValue << 4) | hexValue; + numChars++; + } + else + break; + + (*ptr)++; + } + + return (numChars); +} + + +/* Functions to tweak the SPSR. */ + +static inline int +get_psr (void) +{ + int psr; + asm volatile ("mrs %0, cpsr" + : "=r" (psr) + : /* no inputs */ ); + return psr; +} + +static inline void +set_psr (int psr) +{ + asm volatile ("msr cpsr, %0" + : /* no outputs */ + : "r" (psr)); +} + + +/* This function does all command processing for interfacing to gdb. */ + +void +handle_exception (int sigval, struct pt_regs *regs) +{ + static int in_gdb = 0; + int addr, length; + unsigned long psr; + char *ptr; + + if (remote_debug) + printk ("handle_exception(%d)\n", sigval); + + if (check_fault) + { + /* We must have tried to set or get a memory location that + triggered a fault. Set the error flag, increment the PC past + the bad instruction, and return to the stub. */ + + mem_err = 1; + + /* Speaking of incrementing the PC here, I'm not quite sure why + I should have to do it, since the processor is supposed to + set the R14_svc to the bad instruction + 4. I guess there's + something going on here which I haven't tracked down yet. + + For example, if I examine a memory location which isn't + mapped by the MMU, a data access exception is raised and this + function gets called. The PC is at the instruction which is + trying to dereference the memory location. I expect that + there's some other code somewhere which munges the PC before + we see it, because in most cases you'll want to get the + fault, swap in the memory, and try again, no? */ + + regs->ARM_pc += 4; + return; + } + + if (in_gdb++) + { + printk ("handle_exception called recursively -- returning...\n"); + return; + } + + /* By default, the processor will increment the PC by 4 when an + exception occurs. Most of the time we don't want that, since we + want the PC to point to the location of the breakpoint (or we'll + confuse GDB). */ + regs->ARM_pc -= 4; + + if (remote_debug) + show_regs (regs); + + /* disable interrupts */ + psr = get_psr (); + set_psr (psr | I_BIT | F_BIT); + + if (remote_debug) + printk ("psr before=%08lx after=%08lx\n", psr, psr | I_BIT | F_BIT); + + /* Copy the stuff in REGS to USER_REGS (that is, the registers + stored in the order in which GDB expects for the 'g' command). + (In supervisor mode we don't care about floating point registers + since the kernel doesn't use floating point math. We're skipping + those registers, therefore.) */ + + user_regs.r0 = (int) regs->ARM_r0; + user_regs.r1 = (int) regs->ARM_r1; + user_regs.r2 = (int) regs->ARM_r2; + user_regs.r3 = (int) regs->ARM_r3; + user_regs.r4 = (int) regs->ARM_r4; + user_regs.r5 = (int) regs->ARM_r5; + user_regs.r6 = (int) regs->ARM_r6; + user_regs.r7 = (int) regs->ARM_r7; + user_regs.r8 = (int) regs->ARM_r8; + user_regs.r9 = (int) regs->ARM_r9; + user_regs.sl = (int) regs->ARM_r10; + user_regs.fp = (int) regs->ARM_fp; + user_regs.ip = (int) regs->ARM_ip; + user_regs.sp = (int) regs->ARM_sp; + user_regs.lr = (int) regs->ARM_lr; + user_regs.pc = (int) regs->ARM_pc; + user_regs.ps = (int) regs->ARM_cpsr; + + /* reply to host that an exception has occurred */ +#if 0 + /* old style */ + remcomOutBuffer[0] = 'S'; + remcomOutBuffer[1] = hexchars[sigval >> 4]; + remcomOutBuffer[2] = hexchars[sigval % 16]; + remcomOutBuffer[3] = 0; + putpacket (remcomOutBuffer); +#else + /* new style -- faster because GDB doesn't have to ask for + additional registers when stepping */ + ptr = remcomOutBuffer; + + /* Send trap type (converted to signal) */ + *ptr++ = 'T'; + *ptr++ = hexchars[sigval >> 4]; + *ptr++ = hexchars[sigval & 0xf]; + + /* order of registers sent to GDB... */ +#define GDBREG_FP (11) +#define GDBREG_IP (12) +#define GDBREG_SP (13) +#define GDBREG_LR (14) +#define GDBREG_PC (15) +#define GDBREG_PS (25) + + /* PC */ + *ptr++ = hexchars[GDBREG_PC >> 4]; + *ptr++ = hexchars[GDBREG_PC & 0xf]; + *ptr++ = ':'; + ptr = mem2hex ((char *) &user_regs.pc, ptr, 4, 0); + *ptr++ = ';'; + + /* FP */ + *ptr++ = hexchars[GDBREG_FP >> 4]; + *ptr++ = hexchars[GDBREG_FP & 0xf]; + *ptr++ = ':'; + ptr = mem2hex ((char *) &user_regs.fp, ptr, 4, 0); + *ptr++ = ';'; + + /* SP */ + *ptr++ = hexchars[GDBREG_SP >> 4]; + *ptr++ = hexchars[GDBREG_SP & 0xf]; + *ptr++ = ':'; + ptr = mem2hex ((char *) &user_regs.sp, ptr, 4, 0); + *ptr++ = ';'; + + /* PS */ + *ptr++ = hexchars[GDBREG_PS >> 4]; + *ptr++ = hexchars[GDBREG_PS & 0xf]; + *ptr++ = ':'; + ptr = mem2hex ((char *) &user_regs.ps, ptr, 4, 0); + *ptr++ = ';'; + + *ptr++ = 0; + + putpacket (remcomOutBuffer); /* send it off... */ +#endif + + while (1) + { + error = 0; + remcomOutBuffer[0] = 0; + getpacket (remcomInBuffer); + + switch (remcomInBuffer[0]) + { + case '?': + /* print last signal */ + remcomOutBuffer[0] = 'S'; + remcomOutBuffer[1] = hexchars[sigval >> 4]; + remcomOutBuffer[2] = hexchars[sigval % 16]; + remcomOutBuffer[3] = 0; + break; + + case 'd': + /* toggle debug */ + remote_debug = !(remote_debug); + break; + + case 'g': + /* read registers */ + mem2hex ((char *) &user_regs, remcomOutBuffer, NUMREGBYTES, 0); + break; + + case 'G': + /* set registers */ + hex2mem (&remcomInBuffer[1], (char *) &user_regs, NUMREGBYTES, 0); + + regs->ARM_r0 = (unsigned long) user_regs.r0; + regs->ARM_r1 = (unsigned long) user_regs.r1; + regs->ARM_r2 = (unsigned long) user_regs.r2; + regs->ARM_r3 = (unsigned long) user_regs.r3; + regs->ARM_r4 = (unsigned long) user_regs.r4; + regs->ARM_r5 = (unsigned long) user_regs.r5; + regs->ARM_r6 = (unsigned long) user_regs.r6; + regs->ARM_r7 = (unsigned long) user_regs.r7; + regs->ARM_r8 = (unsigned long) user_regs.r8; + regs->ARM_r9 = (unsigned long) user_regs.r9; + regs->ARM_r10 = (unsigned long) user_regs.sl; + regs->ARM_fp = (unsigned long) user_regs.fp; + regs->ARM_ip = (unsigned long) user_regs.ip; + regs->ARM_sp = (unsigned long) user_regs.sp; + regs->ARM_lr = (unsigned long) user_regs.lr; + regs->ARM_pc = (unsigned long) user_regs.pc; + regs->ARM_cpsr = (unsigned long) user_regs.ps; + + strcpy (remcomOutBuffer, "OK"); + break; + + case 'm': + /* mAA..AA,LLLL Read LLLL bytes at address AA..AA */ + /* TRY TO READ %x,%x. IF SUCCEED, SET PTR = 0 */ + ptr = &remcomInBuffer[1]; + if (hexToInt (&ptr, &addr)) + if (*(ptr++) == ',') + if (hexToInt (&ptr, &length)) + { + ptr = 0; + mem_err = 0; + mem2hex ((char *) addr, remcomOutBuffer, length, 1); + if (mem_err) + { + strcpy (remcomOutBuffer, "E03"); + if (remote_debug) + printk ("memory fault"); + } + } + + if (ptr) + { + strcpy (remcomOutBuffer, "E01"); + if (remote_debug) + printk ("malformed read memory command: %s", remcomInBuffer); + } + break; + + case 'M': + /* MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK */ + /* TRY TO READ '%x,%x:'. IF SUCCEED, SET PTR = 0 */ + ptr = &remcomInBuffer[1]; + if (hexToInt (&ptr, &addr)) + if (*(ptr++) == ',') + if (hexToInt (&ptr, &length)) + if (*(ptr++) == ':') + { + mem_err = 0; + hex2mem (ptr, (char *) addr, length, 1); + + if (mem_err) + { + strcpy (remcomOutBuffer, "E03"); + if (remote_debug) + printk ("memory fault"); + } + else + { + strcpy (remcomOutBuffer, "OK"); + } + + ptr = 0; + } + if (ptr) + { + strcpy (remcomOutBuffer, "E02"); + if (remote_debug) + printk ("malformed write memory command: %s", remcomInBuffer); + } + break; + + case 'k': /* 'kill' just makes the program continue */ + case 'c': + /* cAA..AA Continue from address AA..AA(optional) */ + /* try to read optional parameter, pc unchanged if no parm */ + ptr = &remcomInBuffer[1]; + if (hexToInt (&ptr, &addr)) + user_regs.pc = addr; + + /* Need to flush the instruction cache here, as we may + have deposited a breakpoint, and the icache probably + has no way of knowing that a data ref to some location + may have changed something that is in the instruction + cache. */ + asm (" mcr p15, 0, r0, c7, c5, 0"); + + /* re-enable interrupts (possibly) */ + set_psr (psr); + + in_gdb--; + return; + break; + + default: + /* all other commands are unrecognized and return an empty + packet as per the protocol */ + break; + + } /* switch */ + + /* reply to the request */ + putpacket (remcomOutBuffer); + } +} + + +/* This function is used to set up exception handlers for tracing and + breakpoints. In this version of the stub, there's not much here, + since alternate code has been compiled in when the CONFIG_KGDB + symbol is defined. */ + +void +set_debug_traps (void) +{ + if (initialized) + return; + + /* In case GDB is started before us, ack any packets (presumably + "$?#xx") sitting there. */ + putDebugChar ('+'); + + initialized = 1; +} + + +/* This function will generate a breakpoint exception. It is used at the + beginning of a program to sync up with a debugger and can be used + otherwise as a quick means to stop program execution and "break" into + the debugger. */ + +void +breakpoint (void) +{ + if (initialized) + BREAKPOINT (); +} diff -rbuN -X exclude-list linux-cb26.orig/arch/arm/kernel/entry-armv.S linux-cb26/arch/arm/kernel/entry-armv.S --- linux-cb26.orig/arch/arm/kernel/entry-armv.S Mon Aug 7 15:28:10 2000 +++ linux-cb26/arch/arm/kernel/entry-armv.S Mon Aug 28 19:02:03 2000 @@ -506,8 +506,12 @@ add r4, sp, #S_SP stmia r4, {r5 - r9} @ save sp_SVC, lr_SVC, pc, cpsr, old_ro +/* I don't believe that the kernel can use the floating point emulator. */ +#if 0 adrsvc al, r9, 1f @ r9 = normal FP return +/* expands to: adral r9, 1f */ bl call_fpe @ lr = undefined instr return +#endif mov r0, r5 @ unsigned long pc mov r1, sp @ struct pt_regs *regs diff -rbuN -X exclude-list linux-cb26.orig/arch/arm/kernel/process.c linux-cb26/arch/arm/kernel/process.c --- linux-cb26.orig/arch/arm/kernel/process.c Mon Aug 7 15:27:52 2000 +++ linux-cb26/arch/arm/kernel/process.c Sat Aug 19 00:37:14 2000 @@ -102,21 +102,16 @@ flags = condition_codes(regs); - printk( "pc : [<%08lx>] lr : [<%08lx>]\n" - "sp : %08lx ip : %08lx fp : %08lx\n", - instruction_pointer(regs), - regs->ARM_lr, regs->ARM_sp, - regs->ARM_ip, regs->ARM_fp); - printk( "r10: %08lx r9 : %08lx r8 : %08lx\n", - regs->ARM_r10, regs->ARM_r9, - regs->ARM_r8); - printk( "r7 : %08lx r6 : %08lx r5 : %08lx r4 : %08lx\n", - regs->ARM_r7, regs->ARM_r6, + printk( "pc:%08lx lr:%08lx sp:%08lx ip:%08lx fp:%08lx r10:%08lx\n", + instruction_pointer(regs), regs->ARM_lr, regs->ARM_sp, + regs->ARM_ip, regs->ARM_fp, regs->ARM_r10); + printk( "r9:%08lx r8:%08lx r7:%08lx r6:%08lx r5:%08lx r4:%08lx\n", + regs->ARM_r9, regs->ARM_r8, regs->ARM_r7, regs->ARM_r6, regs->ARM_r5, regs->ARM_r4); - printk( "r3 : %08lx r2 : %08lx r1 : %08lx r0 : %08lx\n", - regs->ARM_r3, regs->ARM_r2, - regs->ARM_r1, regs->ARM_r0); - printk("Flags: %c%c%c%c", + printk( "r3:%08lx r2:%08lx r1:%08lx r0:%08lx\n", + regs->ARM_r3, regs->ARM_r2, regs->ARM_r1, + regs->ARM_r0); + printk("Flags %c%c%c%c", flags & CC_N_BIT ? 'N' : 'n', flags & CC_Z_BIT ? 'Z' : 'z', flags & CC_C_BIT ? 'C' : 'c', diff -rbuN -X exclude-list linux-cb26.orig/arch/arm/kernel/traps.c linux-cb26/arch/arm/kernel/traps.c --- linux-cb26.orig/arch/arm/kernel/traps.c Mon Aug 7 15:27:52 2000 +++ linux-cb26/arch/arm/kernel/traps.c Mon Aug 28 17:13:26 2000 @@ -24,6 +24,10 @@ #include #include +#ifdef CONFIG_KGDB +extern void handle_exception(int sigval, struct pt_regs *regs); +#endif + extern void die_if_kernel(char *str, struct pt_regs *regs, int err, int ret); extern void c_backtrace (unsigned long fp, int pmode); extern int ptrace_cancel_bpt (struct task_struct *); @@ -193,7 +197,11 @@ do_exit (ret); else { cli (); +#ifdef CONFIG_KGDB + handle_exception (err, regs); +#else while (1); +#endif } } @@ -209,6 +217,15 @@ asmlinkage void do_undefinstr (int address, struct pt_regs *regs, int mode) { +#ifdef CONFIG_KGDB + /* If we're here in supervisor mode, we've hit a breakpoint -- + invoke the debugging stub */ + if (! user_mode (regs)) + { + handle_exception (SIGTRAP, regs); + return; + } +#endif #ifdef CONFIG_DEBUG_USER printk(KERN_INFO "%s (%d): undefined instruction: pc=%08lx\n", current->comm, current->pid, instruction_pointer(regs)); @@ -225,6 +242,13 @@ printk(KERN_INFO "%s (%d): address exception: pc=%08lx\n", current->comm, current->pid, instruction_pointer(regs)); #endif +#ifdef CONFIG_KGDB + if (! user_mode (regs)) + { + printk ("do_excpt ()\n"); + handle_exception (SIGBUS, regs); + } +#endif current->tss.error_code = 0; current->tss.trap_no = 11; force_sig (SIGBUS, current); @@ -244,6 +268,13 @@ printk (KERN_CRIT "Bad mode in %s handler detected: mode %s\n", handler[reason], processor_modes[proc_mode]); +#ifdef CONFIG_KGDB + if (! user_mode (regs)) + { + printk ("bad_mode ()\n"); + handle_exception (-1, regs); + } +#endif die_if_kernel ("Oops", regs, 0, -1); } @@ -263,6 +294,13 @@ { switch (no) { case 0: /* branch through 0 */ +#ifdef CONFIG_KGDB + if (! user_mode (regs)) + { + printk ("arm_syscall (0)\n"); + handle_exception (-1, regs); + } +#endif force_sig(SIGSEGV, current); die_if_kernel ("branch through zero", regs, 0, SIGSEGV); break; @@ -299,6 +337,13 @@ c_backtrace (regs->ARM_fp, processor_mode(regs)); } #endif +#ifdef CONFIG_KGDB + if (! user_mode (regs)) + { + printk ("arm_syscall (%d)\n", no); + handle_exception (SIGILL, regs); + } +#endif force_sig (SIGILL, current); die_if_kernel ("Oops", regs, no, SIGILL); break; @@ -308,6 +353,15 @@ asmlinkage void deferred(int n, struct pt_regs *regs) { +#ifdef CONFIG_KGDB + if (! user_mode (regs)) + { + printk ("deferred (%d)\n", n); + handle_exception (SIGSTOP, regs); + } + else +#endif + { /* You might think just testing `handler' would be enough, but PER_LINUX points it to no_lcall7 to catch undercover SVr4 binaries. Gutted. */ if (current->personality != PER_LINUX && current->exec_domain->handler) { @@ -322,6 +376,7 @@ current->comm); #endif force_sig (SIGILL, current); + } } asmlinkage void arm_malalignedptr(const char *str, void *pc, volatile void *ptr) diff -rbuN -X exclude-list linux-cb26.orig/arch/arm/mm/fault-common.c linux-cb26/arch/arm/mm/fault-common.c --- linux-cb26.orig/arch/arm/mm/fault-common.c Mon Aug 7 15:28:03 2000 +++ linux-cb26/arch/arm/mm/fault-common.c Mon Aug 28 17:14:08 2000 @@ -131,6 +131,10 @@ } no_context: +#ifdef CONFIG_KGDB + handle_exception (SIGSEGV, regs); + up(&mm->mmap_sem); +#else /* Are we prepared to handle this kernel fault? */ if ((fixup = search_exception_table(instruction_pointer(regs))) != 0) { #ifdef DEBUG @@ -142,6 +146,7 @@ } kernel_page_fault(addr, mode, regs, tsk, mm); +#endif return; do_sigbus: diff -rbuN -X exclude-list linux-cb26.orig/arch/arm/nwfpe/fpa11_cprt.c linux-cb26/arch/arm/nwfpe/fpa11_cprt.c --- linux-cb26.orig/arch/arm/nwfpe/fpa11_cprt.c Mon Aug 7 15:27:52 2000 +++ linux-cb26/arch/arm/nwfpe/fpa11_cprt.c Thu Aug 17 14:34:22 2000 @@ -72,7 +72,7 @@ case WFC_CODE >> 20: { int mode = 0; - __asm__ volatile ("mrs %0, cpsr; and %0, %0, #0x1f;" : : "g" (mode)); + __asm__ volatile ("mrs %0, cpsr; and %0, %0, #0x1f;" : : "r" (mode)); nRc = (0x13 == mode) ? 1 : 0; /* in SVC processor mode? */ if (nRc) writeFPCR(readRegister(getRd(opcode))); } @@ -81,7 +81,7 @@ case RFC_CODE >> 20: { int mode = 0; - __asm__ volatile ("mrs %0, cpsr; and %0, %0, #0x1f;" : : "g" (mode)); + __asm__ volatile ("mrs %0, cpsr; and %0, %0, #0x1f;" : : "r" (mode)); nRc = (0x13 == mode) ? 1 : 0; /* in SVC processor mode? */ if (nRc) writeRegister(getRd(opcode),readFPCR()); break; } diff -rbuN -X exclude-list linux-cb26.orig/drivers/char/serial_7110.c linux-cb26/drivers/char/serial_7110.c --- linux-cb26.orig/drivers/char/serial_7110.c Mon Aug 7 15:28:10 2000 +++ linux-cb26/drivers/char/serial_7110.c Mon Aug 28 19:12:57 2000 @@ -370,9 +370,52 @@ printk(KERN_ERR "Couldn't register CL-PS7110 serial driver\n"); return -1; } + +#ifdef CONFIG_KGDB + /* @@NJC */ + set_debug_traps (); + printk ("connect GDB now...\n"); + breakpoint (); +#endif + return 0; +} + +#ifdef CONFIG_KGDB +int putDebugChar (char c) +{ +#if 0 + printk ("put "); +#endif + udelay (5); + disable_irq(IRQ_UTXINT); + while(IO_SYSFLG & UTXFF) + ; + IO_UARTDR=c; + enable_irq(IRQ_UTXINT); +#if 0 + printk ("`%c' (%d)\n", c, (int) c); +#endif return 0; } +int getDebugChar (void) +{ + int c; +#if 0 + printk ("get "); +#endif + disable_irq(IRQ_URXINT); + while(IO_SYSFLG & URXFE) + pm_change(&rs_pm_dev,1); + c=IO_UARTDR; + enable_irq(IRQ_URXINT); +#if 0 + printk (" `%c' (%d)\n", (char) c, (c & (int) 0xFF)); +#endif + return c; +} +#endif + #ifdef CONFIG_SERIAL_7110_CONSOLE /************** console driver *****************/ diff -rbuN -X exclude-list linux-cb26.orig/gdbconfig linux-cb26/gdbconfig --- linux-cb26.orig/gdbconfig Wed Dec 31 16:00:00 1969 +++ linux-cb26/gdbconfig Mon Aug 28 19:22:26 2000 @@ -0,0 +1,333 @@ +# +# Automatically generated make config: don't edit +# +CONFIG_ARM=y + +# +# System and processor type +# +# CONFIG_ARCH_ARC is not set +# CONFIG_ARCH_A5K is not set +# CONFIG_ARCH_RPC is not set +# CONFIG_ARCH_EBSA110 is not set +# CONFIG_FOOTBRIDGE is not set +CONFIG_ARCH_CLPS7110=y +CONFIG_ARCH_PSION=y +# CONFIG_ARCH_GEOFOX is not set +CONFIG_CPU_ARM7=y +CONFIG_KERNEL_PCMCIA=y +# CONFIG_ARCH_ACORN is not set +# CONFIG_ISA_DMA is not set +CONFIG_CPU_32=y +# CONFIG_CPU_26 is not set + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y +# CONFIG_ALIGNMENT_TRAP is not set +# CONFIG_TEXT_SECTIONS is not set + +# +# Loadable module support +# +# CONFIG_MODULES is not set + +# +# General setup +# +CONFIG_NET=y +# CONFIG_SYSVIPC is not set +# CONFIG_BSD_PROCESS_ACCT is not set +CONFIG_SYSCTL=y +CONFIG_NWFPE=y +CONFIG_BINFMT_AOUT=y +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_MISC is not set +# CONFIG_PARPORT is not set + +# +# Plug and Play support +# +# CONFIG_PNP is not set + +# +# Block devices +# +# CONFIG_BLK_DEV_FD is not set +CONFIG_BLK_DEV_IDE=y + +# +# Please see Documentation/ide.txt for help/info on IDE drives +# +# CONFIG_BLK_DEV_HD_IDE is not set +CONFIG_BLK_DEV_IDEDISK=y +# CONFIG_BLK_DEV_IDECD is not set +# CONFIG_BLK_DEV_IDETAPE is not set +# CONFIG_BLK_DEV_IDEFLOPPY is not set +# CONFIG_BLK_DEV_IDESCSI is not set +# CONFIG_BLK_DEV_CMD640 is not set +# CONFIG_IDE_CHIPSETS is not set + +# +# Additional Block Devices +# +CONFIG_BLK_DEV_LOOP=y +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_MD is not set +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_INITRD=y +# CONFIG_BLK_DEV_XD is not set +CONFIG_PARIDE_PARPORT=y +# CONFIG_PARIDE is not set +# CONFIG_BLK_DEV_HD is not set + +# +# Character devices +# +CONFIG_VT=y +CONFIG_VT_CONSOLE=y +CONFIG_SMART_SLOCK=y +# CONFIG_SERIAL is not set +# CONFIG_SERIAL_EXTENDED is not set +CONFIG_SERIAL_NONSTANDARD=y +# CONFIG_ROCKETPORT is not set +# CONFIG_DIGIEPCA is not set +# CONFIG_DIGI is not set +# CONFIG_CYCLADES is not set +# CONFIG_STALDRV is not set +# CONFIG_RISCOM8 is not set +# CONFIG_SPECIALIX is not set +# CONFIG_ESPSERIAL is not set +CONFIG_SERIAL_7110=y +CONFIG_SERIAL_7110_CONSOLE=y +# CONFIG_UNIX98_PTYS is not set +CONFIG_AUDIO_7110=y +CONFIG_PSION_KBD_US=y +CONFIG_TOUCH_PSION=y +# CONFIG_MOUSE is not set +# CONFIG_QIC02_TAPE is not set +# CONFIG_WATCHDOG is not set +# CONFIG_NVRAM is not set +# CONFIG_RTC is not set + +# +# Video For Linux +# +# CONFIG_VIDEO_DEV is not set + +# +# Joystick support +# +# CONFIG_JOYSTICK is not set + +# +# Ftape, the floppy tape device driver +# +# CONFIG_FTAPE is not set + +# +# Console drivers +# +# CONFIG_VGA_CONSOLE is not set +CONFIG_FB=y +CONFIG_DUMMY_CONSOLE=y +CONFIG_FB_CLPS7110=y +# CONFIG_FB_MATROX is not set +# CONFIG_FB_ATY is not set +# CONFIG_FB_VIRTUAL is not set +CONFIG_FBCON_ADVANCED=y +CONFIG_FBCON_MFB=y +# CONFIG_FBCON_CFB2 is not set +# CONFIG_FBCON_CFB4 is not set +# CONFIG_FBCON_CFB8 is not set +# CONFIG_FBCON_CFB16 is not set +# CONFIG_FBCON_CFB24 is not set +# CONFIG_FBCON_CFB32 is not set +# CONFIG_FBCON_AFB is not set +# CONFIG_FBCON_ILBM is not set +# CONFIG_FBCON_IPLAN2P2 is not set +# CONFIG_FBCON_IPLAN2P4 is not set +# CONFIG_FBCON_IPLAN2P8 is not set +# CONFIG_FBCON_MAC is not set +# CONFIG_FBCON_VGA is not set +# CONFIG_FBCON_FONTWIDTH8_ONLY is not set +# CONFIG_FBCON_FONTS is not set +CONFIG_FONT_8x8=y +CONFIG_FONT_8x16=y + +# +# Networking options +# +# CONFIG_PACKET is not set +# CONFIG_NETLINK is not set +# CONFIG_FIREWALL is not set +# CONFIG_NET_ALIAS is not set +# CONFIG_FILTER is not set +# CONFIG_UNIX is not set +CONFIG_INET=y +# CONFIG_IP_MULTICAST is not set +# CONFIG_IP_ADVANCED_ROUTER is not set +# CONFIG_IP_PNP is not set +# CONFIG_IP_ROUTER is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_IP_ALIAS is not set +# CONFIG_SYN_COOKIES is not set + +# +# (it is safe to leave these untouched) +# +# CONFIG_INET_RARP is not set +# CONFIG_IP_NOSR is not set +# CONFIG_SKB_LARGE is not set +# CONFIG_IPV6 is not set + +# +# +# +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_BRIDGE is not set +# CONFIG_LLC is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_NET_FASTROUTE is not set +# CONFIG_NET_HW_FLOWCONTROL is not set +# CONFIG_CPU_IS_SLOW is not set + +# +# QoS and/or fair queueing +# +# CONFIG_NET_SCHED is not set + +# +# Amateur Radio support +# +# CONFIG_HAMRADIO is not set + +# +# IrDA subsystem support +# +# CONFIG_IRDA is not set + +# +# Network device support +# +CONFIG_NETDEVICES=y +# CONFIG_ARCNET is not set +# CONFIG_DUMMY is not set +# CONFIG_EQUALIZER is not set +# CONFIG_NET_ETHERNET is not set +# CONFIG_FDDI is not set +# CONFIG_HIPPI is not set +# CONFIG_DLCI is not set +CONFIG_PPP=y + +# +# CCP compressors for PPP are only built as modules. +# +CONFIG_SLIP=y +CONFIG_SLIP_COMPRESSED=y +# CONFIG_SLIP_SMART is not set +# CONFIG_SLIP_MODE_SLIP6 is not set +# CONFIG_NET_RADIO is not set +# CONFIG_TR is not set +# CONFIG_SHAPER is not set +# CONFIG_RCPCI is not set + +# +# SCSI support +# +# CONFIG_SCSI is not set + +# +# Filesystems +# +# CONFIG_QUOTA is not set +# CONFIG_AUTOFS_FS is not set +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +CONFIG_FAT_FS=y +# CONFIG_MSDOS_FS is not set +# CONFIG_UMSDOS_FS is not set +CONFIG_VFAT_FS=y +# CONFIG_ISO9660_FS is not set +# CONFIG_JOLIET is not set +# CONFIG_MINIX_FS is not set +# CONFIG_NTFS_FS is not set +# CONFIG_HPFS_FS is not set +CONFIG_PROC_FS=y +# CONFIG_QNX4FS_FS is not set +# CONFIG_ROMFS_FS is not set +CONFIG_EXT2_FS=y +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set + +# +# Network File Systems +# +# CONFIG_CODA_FS is not set +CONFIG_NFS_FS=y +# CONFIG_NFSD is not set +CONFIG_SUNRPC=y +CONFIG_LOCKD=y +# CONFIG_SMB_FS is not set +# CONFIG_NCP_FS is not set + +# +# Partition Types +# +# CONFIG_OSF_PARTITION is not set +# CONFIG_MAC_PARTITION is not set +CONFIG_MSDOS_PARTITION=y +# CONFIG_SGI_PARTITION is not set +# CONFIG_SUN_PARTITION is not set +# CONFIG_AMIGA_PARTITION is not set +# CONFIG_ACORN_PARTITION is not set +CONFIG_NLS=y + +# +# Native Language Support +# +# CONFIG_NLS_CODEPAGE_437 is not set +# CONFIG_NLS_CODEPAGE_737 is not set +# CONFIG_NLS_CODEPAGE_775 is not set +# CONFIG_NLS_CODEPAGE_850 is not set +# CONFIG_NLS_CODEPAGE_852 is not set +# CONFIG_NLS_CODEPAGE_855 is not set +# CONFIG_NLS_CODEPAGE_857 is not set +# CONFIG_NLS_CODEPAGE_860 is not set +# CONFIG_NLS_CODEPAGE_861 is not set +# CONFIG_NLS_CODEPAGE_862 is not set +# CONFIG_NLS_CODEPAGE_863 is not set +# CONFIG_NLS_CODEPAGE_864 is not set +# CONFIG_NLS_CODEPAGE_865 is not set +# CONFIG_NLS_CODEPAGE_866 is not set +# CONFIG_NLS_CODEPAGE_869 is not set +# CONFIG_NLS_CODEPAGE_874 is not set +# CONFIG_NLS_ISO8859_1 is not set +# CONFIG_NLS_ISO8859_2 is not set +# CONFIG_NLS_ISO8859_3 is not set +# CONFIG_NLS_ISO8859_4 is not set +# CONFIG_NLS_ISO8859_5 is not set +# CONFIG_NLS_ISO8859_6 is not set +# CONFIG_NLS_ISO8859_7 is not set +# CONFIG_NLS_ISO8859_8 is not set +# CONFIG_NLS_ISO8859_9 is not set +# CONFIG_NLS_ISO8859_15 is not set +# CONFIG_NLS_KOI8_R is not set + +# +# Kernel hacking +# +CONFIG_KGDB=y +CONFIG_FRAME_POINTER=y +CONFIG_DEBUG_INFO=y +CONFIG_DEBUG_ERRORS=y +CONFIG_DEBUG_USER=y +CONFIG_MAGIC_SYSRQ=y +# CONFIG_ARTHUR is not set