diff options
author | dfr <dfr@FreeBSD.org> | 1998-07-05 12:24:18 +0000 |
---|---|---|
committer | dfr <dfr@FreeBSD.org> | 1998-07-05 12:24:18 +0000 |
commit | 78bd2b16752c288c894293c92497c3d3fcb856c8 (patch) | |
tree | e2b4e85001f2d3f404df0052764d4fab47db3ce0 /sys/alpha | |
parent | 49590d8c5a39306eaccde9fcb31a5b39751410da (diff) | |
download | FreeBSD-src-78bd2b16752c288c894293c92497c3d3fcb856c8.zip FreeBSD-src-78bd2b16752c288c894293c92497c3d3fcb856c8.tar.gz |
Add support for kernel gdb.
Diffstat (limited to 'sys/alpha')
-rw-r--r-- | sys/alpha/alpha/alpha-gdbstub.c | 746 | ||||
-rw-r--r-- | sys/alpha/alpha/db_interface.c | 51 | ||||
-rw-r--r-- | sys/alpha/alpha/machdep.c | 51 | ||||
-rw-r--r-- | sys/alpha/alpha/trap.c | 19 | ||||
-rw-r--r-- | sys/alpha/include/db_machdep.h | 2 |
5 files changed, 829 insertions, 40 deletions
diff --git a/sys/alpha/alpha/alpha-gdbstub.c b/sys/alpha/alpha/alpha-gdbstub.c new file mode 100644 index 0000000..f632e8a --- /dev/null +++ b/sys/alpha/alpha/alpha-gdbstub.c @@ -0,0 +1,746 @@ +/**************************************************************************** + + THIS SOFTWARE IS NOT COPYRIGHTED + + HP offers the following for use in the public domain. HP makes no + warranty with regard to the software or its performance and the + user accepts the software "AS IS" with all faults. + + HP DISCLAIMS ANY WARRANTIES, EXPRESS OR IMPLIED, WITH REGARD + TO THIS SOFTWARE INCLUDING BUT NOT LIMITED TO THE WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + +****************************************************************************/ + +/**************************************************************************** + * Header: remcom.c,v 1.34 91/03/09 12:29:49 glenne Exp $ + * + * Module name: remcom.c $ + * Revision: 1.34 $ + * Date: 91/03/09 12:29:49 $ + * Contributor: Lake Stevens Instrument Division$ + * + * Description: low level support for gdb debugger. $ + * + * Considerations: only works on target hardware $ + * + * Written by: Glenn Engel $ + * ModuleState: Experimental $ + * + * NOTES: See Below $ + * + * Modified for FreeBSD by Stu Grossman. + * + * To enable debugger support, two things need to happen. One, a + * call to set_debug_traps() is necessary in order to allow any breakpoints + * or error conditions to be properly intercepted and reported to gdb. + * Two, a breakpoint needs to be generated to begin communication. This + * is most easily accomplished by a call to breakpoint(). Breakpoint() + * simulates a breakpoint by executing a trap #1. + * + * The external function exceptionHandler() is + * used to attach a specific handler to a specific 386 vector number. + * It should use the same privilege level it runs at. It should + * install it as an interrupt gate so that interrupts are masked + * while the handler runs. + * Also, need to assign exceptionHook and oldExceptionHook. + * + * Because gdb will sometimes write to the stack area to execute function + * calls, this program cannot rely on using the supervisor stack so it + * uses its own stack area reserved in the int array remcomStack. + * + ************* + * + * 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 + * + * s Step one instruction SNN + * sAA..AA Step one instruction from AA..AA SNN + * + * k kill + * + * ? What was the last sigval ? SNN (signal NN) + * + * D detach OK + * + * All commands and responses are sent with a packet which includes a + * checksum. A packet consists of + * + * $<packet info>#<checksum>. + * + * where + * <packet info> :: <characters representing the command or response> + * <checksum> :: < two hex digits computed as modulo 256 sum of <packetinfo>> + * + * 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 <sys/param.h> +#include <sys/reboot.h> +#include <sys/systm.h> +#include <sys/signal.h> + +#include <machine/reg.h> +#include <machine/cons.h> + +#include <ddb/ddb.h> + +#include <setjmp.h> + +/* #include "sio.h" */ +#include "opt_ddb.h" + +#define NSIO 1 + +#if NSIO == 0 +void +gdb_handle_exception (db_regs_t *raw_regs, int type, int code) +{ +} +#else +/************************************************************************/ + +void gdb_handle_exception (db_regs_t *, int, int); + +extern jmp_buf db_jmpbuf; + +/************************************************************************/ +/* BUFMAX defines the maximum number of characters in inbound/outbound buffers*/ +/* at least NUMREGBYTES*2 are needed for register packets */ +#define BUFMAX 1500 + +/* Create private copies of common functions used by the stub. This prevents + nasty interactions between app code and the stub (for instance if user steps + into strlen, etc..) */ +/* XXX this is fairly bogus. strlen() and strcpy() should be reentrant, + and are reentrant under FreeBSD. In any case, our versions should not + be named the same as the standard versions, so that the address `strlen' + is unambiguous... */ + +static int +strlen (const char *s) +{ + const char *s1 = s; + + while (*s1++ != '\000'); + + return s1 - s; +} + +static char * +strcpy (char *dst, const char *src) +{ + char *retval = dst; + + while ((*dst++ = *src++) != '\000'); + + return retval; +} + +/* XXX sio always uses its major with minor 0 no matter what we specify. */ +#define REMOTE_DEV 0 + +static int +putDebugChar (int c) /* write a single character */ +{ + siocnputc (REMOTE_DEV, c); + return 1; +} + +static int +getDebugChar (void) /* read and return a single char */ +{ + return siocngetc (REMOTE_DEV); +} + +static const char hexchars[]="0123456789abcdef"; + +static 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); +} + +/* scan for the sequence $<data>#<checksum> */ +static void +getpacket (char *buffer) +{ + unsigned char checksum; + unsigned char xmitcsum; + int i; + int count; + unsigned char ch; + + do + { + /* 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 (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 (strlen(buffer) >= BUFMAX) + panic("kgdb: buffer overflow"); +} + +/* send the packet in buffer. */ + +static void +putpacket (char *buffer) +{ + unsigned char checksum; + int count; + unsigned char ch; + + if (strlen(buffer) >= BUFMAX) + panic("kgdb: buffer overflow"); + + /* $<packet info>#<checksum>. */ + do + { +/* + * This is a non-standard hack to allow use of the serial console for + * operation as well as debugging. Simply turn on 'remotechat' in gdb. + * + * This extension is not part of the Cygnus protocol, is kinda gross, + * but gets the job done. + */ +#ifdef GDB_REMOTE_CHAT + putDebugChar ('|'); + putDebugChar ('|'); + putDebugChar ('|'); + putDebugChar ('|'); +#endif + putDebugChar ('$'); + checksum = 0; + count = 0; + + while (ch=buffer[count]) + { + putDebugChar (ch); + checksum += ch; + count += 1; + } + + putDebugChar ('#'); + putDebugChar (hexchars[checksum >> 4]); + putDebugChar (hexchars[checksum & 0xf]); + } + while ((getDebugChar () & 0x7f) != '+'); +} + +static char remcomInBuffer[BUFMAX]; +static char remcomOutBuffer[BUFMAX]; + +static int +get_char (vm_offset_t addr) +{ + char data; + + if (setjmp (db_jmpbuf)) + return -1; + + db_read_bytes (addr, 1, &data); + + return data & 0xff; +} + +static int +set_char (vm_offset_t addr, int val) +{ + char data; + + if (setjmp (db_jmpbuf)) + return -1; + + data = val; + + db_write_bytes (addr, 1, &data); + return 0; +} + +/* convert the memory pointed to by mem into hex, placing result in buf */ +/* return a pointer to the last char put in buf (null) */ + +static char * +mem2hex (vm_offset_t mem, char *buf, int count) +{ + int i; + int ch; + + for (i=0;i<count;i++) { + ch = get_char (mem++); + if (ch == -1) + return NULL; + *buf++ = hexchars[ch >> 4]; + *buf++ = hexchars[ch % 16]; + } + *buf = 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 */ +static char * +hex2mem (char *buf, vm_offset_t mem, int count) +{ + int i; + int ch; + int rv; + + for (i=0;i<count;i++) { + ch = hex(*buf++) << 4; + ch = ch + hex(*buf++); + rv = set_char (mem++, ch); + if (rv == -1) + return NULL; + } + return(buf); +} + +/* this function takes the 386 exception vector and attempts to + translate this number into a unix compatible signal value */ +static int +computeSignal (int entry, int code) +{ + switch (entry) { + case ALPHA_KENTRY_INT: + case ALPHA_KENTRY_ARITH: + return SIGILL; /* ? can this happen? */ + case ALPHA_KENTRY_MM: + switch (code) { + case ALPHA_MMCSR_INVALTRANS: + return SIGSEGV; + case ALPHA_MMCSR_ACCESS: + case ALPHA_MMCSR_FOR: + case ALPHA_MMCSR_FOE: + case ALPHA_MMCSR_FOW: + return SIGBUS; + } + case ALPHA_KENTRY_IF: + switch (code) { + case ALPHA_IF_CODE_BUGCHK: + case ALPHA_IF_CODE_BPT: + return SIGTRAP; + case ALPHA_IF_CODE_GENTRAP: + case ALPHA_IF_CODE_FEN: + case ALPHA_IF_CODE_OPDEC: + return SIGILL; + } + case ALPHA_KENTRY_UNA: + return SIGSEGV; + case ALPHA_KENTRY_SYS: + return SIGILL; + } + return SIGILL; +} + +/* + * While we find nice hex chars, build an int. + * Return number of chars processed. + */ + +static int +hexToInt(char **ptr, long *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); +} + +static enum { + NONE, + NORMAL, + BRANCH +} ss_mode = NONE; + +struct ss_bpt { + int active; + vm_offset_t addr; + u_int32_t contents; +}; + +static struct ss_bpt ss_bp1, ss_bp2; + +static int +set_bpt(struct ss_bpt* bp) +{ + u_int32_t bp_ins = BKPT_INST; + if (bp->active) return 0; + if (badaddr((caddr_t)bp->addr, 4)) + return 0; + db_read_bytes(bp->addr, 4, (caddr_t) &bp->contents); + db_write_bytes(bp->addr, 4, (caddr_t) &bp_ins); + bp->active = 1; + return 1; +} + +static void +clear_bpt(struct ss_bpt* bp) +{ + if (!bp->active) return; + if (badaddr((caddr_t) bp->addr, 4)) + return; + db_write_bytes(bp->addr, 4, (caddr_t) &bp->contents); + bp->active = 0; +} + +static int +set_single_step(db_regs_t* regs) +{ + u_int32_t ins; + vm_offset_t pc = regs->tf_regs[FRAME_PC]; + + if (ss_mode != NONE) { + printf("single_step botch\n"); + return 0; + } + + if (badaddr((caddr_t) pc, 4)) + return 0; + db_read_bytes(pc, 4, (caddr_t) &ins); + ss_bp1.addr = pc + 4; + if (db_inst_branch(ins)) { + ss_bp2.addr = db_branch_taken(ins, pc, regs); + if (!set_bpt(&ss_bp1)) + return 0; + if (!set_bpt(&ss_bp2)) { + clear_bpt(&ss_bp1); + return 0; + } + ss_mode = BRANCH; + } else { + if (!set_bpt(&ss_bp1)) + return 0; + ss_mode = NORMAL; + } + + return 1; +} + +static void +clear_single_step(db_regs_t* regs) +{ + /* if we hit one of the step breakpoints, adjust pc */ + if (ss_mode == BRANCH) + { + /* remove in reverse order in case they are at the same address */ + if (regs->tf_regs[FRAME_PC] == ss_bp1.addr + 4 + || regs->tf_regs[FRAME_PC] == ss_bp2.addr + 4) + regs->tf_regs[FRAME_PC] -= 4; + clear_bpt(&ss_bp2); + clear_bpt(&ss_bp1); + } + else if (ss_mode == NORMAL) + { + if (regs->tf_regs[FRAME_PC] == ss_bp1.addr + 4) + regs->tf_regs[FRAME_PC] -= 4; + clear_bpt(&ss_bp1); + } + ss_mode = NONE; +} + +#define NUMREGBYTES (sizeof registers) +#define PC 64 +#define SP 30 +#define FP 15 +#define VFP 65 +#define NUM_REGS 66 + +/* + * Map trapframe indices into gdb (integer) register indices. + * Entries not in integer register set are set to -1. + */ +static int tf2gdb[FRAME_SIZE] = { + R_V0, R_T0, R_T1, R_T2, R_T3, R_T4, R_T5, R_T6, + R_T7, R_S0, R_S1, R_S2, R_S3, R_S4, R_S5, R_S6, + R_A3, R_A4, R_A5, R_T8, R_T9, R_T10, R_T11, R_RA, + R_T12, R_AT, R_SP, -1, -1, R_GP, R_A0, R_A1, + R_A2, +}; + +/* + * Map gdb register indices back to trapframe. + * Entries not in trapframe are set to -1. + */ +static int gdb2tf[NUM_REGS] = { + /* integer registers */ + FRAME_V0, FRAME_T0, FRAME_T1, FRAME_T2, + FRAME_T3, FRAME_T4, FRAME_T5, FRAME_T6, + FRAME_T7, FRAME_S0, FRAME_S1, FRAME_S2, + FRAME_S3, FRAME_S4, FRAME_S5, FRAME_S6, + FRAME_A0, FRAME_A1, FRAME_A2, FRAME_A3, + FRAME_A4, FRAME_A5, FRAME_T8, FRAME_T9, + FRAME_T10, FRAME_T11, FRAME_RA, FRAME_T12, + FRAME_AT, FRAME_GP, FRAME_SP, -1, + /* float registers */ + -1, -1, -1, -1, + -1, -1, -1, -1, + -1, -1, -1, -1, + -1, -1, -1, -1, + -1, -1, -1, -1, + -1, -1, -1, -1, + -1, -1, -1, -1, + -1, -1, -1, -1, + /* misc registers */ + FRAME_PC, -1, +}; + +/* + * This function does all command procesing for interfacing to gdb. + */ +void +gdb_handle_exception (db_regs_t *raw_regs, int type, int code) +{ + int sigval; + long addr, length; + char * ptr; + struct alpharegs { + u_int64_t r[32]; + u_int64_t f[32]; + u_int64_t pc, vfp; + }; + static struct alpharegs registers; + int i; + + clear_single_step(raw_regs); + + bzero(®isters, sizeof registers); + + /* + * Map trapframe to registers. + * Ignore float regs for now. + */ + for (i = 0; i < FRAME_SIZE; i++) + if (tf2gdb[i] > 0) + registers.r[tf2gdb[i]] = raw_regs->tf_regs[i]; + registers.pc = raw_regs->tf_regs[FRAME_PC]; + + /* reply to host that an exception has occurred */ + sigval = computeSignal (type, code); + ptr = remcomOutBuffer; + + *ptr++ = 'T'; + *ptr++ = hexchars[sigval >> 4]; + *ptr++ = hexchars[sigval & 0xf]; + + *ptr++ = hexchars[PC >> 4]; + *ptr++ = hexchars[PC & 0xf]; + *ptr++ = ':'; + ptr = mem2hex ((vm_offset_t)®isters.pc, ptr, 8); + *ptr++ = ';'; + + *ptr++ = hexchars[FP >> 4]; + *ptr++ = hexchars[FP & 0xf]; + *ptr++ = ':'; + ptr = mem2hex ((vm_offset_t)®isters.r[FP], ptr, 8); + *ptr++ = ';'; + + *ptr++ = hexchars[SP >> 4]; + *ptr++ = hexchars[SP & 0xf]; + *ptr++ = ':'; + ptr = mem2hex ((vm_offset_t)®isters.r[SP], ptr, 8); + *ptr++ = ';'; + + *ptr++ = 0; + + putpacket (remcomOutBuffer); + + while (1) + { + remcomOutBuffer[0] = 0; + + getpacket (remcomInBuffer); + switch (remcomInBuffer[0]) + { + case '?': + remcomOutBuffer[0] = 'S'; + remcomOutBuffer[1] = hexchars[sigval >> 4]; + remcomOutBuffer[2] = hexchars[sigval % 16]; + remcomOutBuffer[3] = 0; + break; + + case 'D': /* detach; say OK and turn off gdb */ + putpacket(remcomOutBuffer); + boothowto &= ~RB_GDB; + return; + + case 'k': + prom_halt(); + /*NOTREACHED*/ + break; + + case 'g': /* return the value of the CPU registers */ + mem2hex ((vm_offset_t)®isters, remcomOutBuffer, NUMREGBYTES); + break; + + case 'G': /* set the value of the CPU registers - return OK */ + hex2mem (&remcomInBuffer[1], (vm_offset_t)®isters, NUMREGBYTES); + strcpy (remcomOutBuffer, "OK"); + break; + + case 'P': /* Set the value of one register */ + { + long regno; + + ptr = &remcomInBuffer[1]; + + if (hexToInt (&ptr, ®no) + && *ptr++ == '=' + && regno < NUM_REGS) + { + hex2mem (ptr, (vm_offset_t)®isters + regno * 8, 8); + strcpy(remcomOutBuffer,"OK"); + } + else + strcpy (remcomOutBuffer, "P01"); + break; + } + case 'm': /* mAA..AA,LLLL Read LLLL bytes at address AA..AA */ + /* Try to read %x,%x. */ + + ptr = &remcomInBuffer[1]; + + if (hexToInt (&ptr, &addr) + && *(ptr++) == ',' + && hexToInt (&ptr, &length)) + { + if (mem2hex((vm_offset_t) addr, remcomOutBuffer, length) == NULL) + strcpy (remcomOutBuffer, "E03"); + break; + } + else + strcpy (remcomOutBuffer, "E01"); + break; + + case 'M': /* MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK */ + + /* Try to read '%x,%x:'. */ + + ptr = &remcomInBuffer[1]; + + if (hexToInt(&ptr,&addr) + && *(ptr++) == ',' + && hexToInt(&ptr, &length) + && *(ptr++) == ':') + { + if (hex2mem(ptr, (vm_offset_t) addr, length) == NULL) + strcpy (remcomOutBuffer, "E03"); + else + strcpy (remcomOutBuffer, "OK"); + } + else + strcpy (remcomOutBuffer, "E02"); + break; + + /* cAA..AA Continue at address AA..AA(optional) */ + /* sAA..AA Step one instruction from AA..AA(optional) */ + case 'c' : + case 's' : + /* try to read optional parameter, pc unchanged if no parm */ + + ptr = &remcomInBuffer[1]; + if (hexToInt(&ptr,&addr)) + registers.pc = addr; + + /* + * Map gdb registers back to trapframe (ignoring fp regs). + */ + for (i = 0; i < NUM_REGS; i++) + if (gdb2tf[i] > 0) + raw_regs->tf_regs[gdb2tf[i]] = registers.r[i]; + raw_regs->tf_regs[FRAME_PC] = registers.pc; + + if (remcomInBuffer[0] == 's') + if (!set_single_step(raw_regs)) + printf("Can't set single step breakpoint\n"); + + return; + + } /* switch */ + + /* reply to the request */ + putpacket (remcomOutBuffer); + } +} +#endif /* NSIO > 0 */ diff --git a/sys/alpha/alpha/db_interface.c b/sys/alpha/alpha/db_interface.c index ec42c89..99bae72 100644 --- a/sys/alpha/alpha/db_interface.c +++ b/sys/alpha/alpha/db_interface.c @@ -72,6 +72,12 @@ #include <ddb/db_access.h> #include <ddb/db_sym.h> #include <ddb/db_variables.h> +#include <setjmp.h> + +static jmp_buf *db_nofault = 0; +extern jmp_buf db_jmpbuf; + +extern void gdb_handle_exception __P((db_regs_t *, int, int)); extern label_t *db_recover; @@ -142,10 +148,11 @@ ddbprinttrap(a0, a1, a2, entry) * ddb_trap - field a kernel trap */ int -ddb_trap(a0, a1, a2, entry, regs) +kdb_trap(a0, a1, a2, entry, regs) unsigned long a0, a1, a2, entry; db_regs_t *regs; { + int ddb_mode = !(boothowto & RB_GDB); int s; /* @@ -158,26 +165,21 @@ ddb_trap(a0, a1, a2, entry, regs) if (entry != ALPHA_KENTRY_IF || (a0 != ALPHA_IF_CODE_BUGCHK && a0 != ALPHA_IF_CODE_BPT && a0 != ALPHA_IF_CODE_GENTRAP)) { - db_printf("ddbprinttrap from 0x%lx\n", /* XXX */ - regs->tf_regs[FRAME_PC]); - ddbprinttrap(a0, a1, a2, entry); -#if 0 - if (db_recover != 0) { + if (ddb_mode) { + db_printf("ddbprinttrap from 0x%lx\n", /* XXX */ + regs->tf_regs[FRAME_PC]); + ddbprinttrap(a0, a1, a2, entry); /* - * XXX Sould longjump back into command loop! + * Tell caller "We did NOT handle the trap." + * Caller should panic, or whatever. */ - db_printf("Faulted in DDB; continuing...\n"); - alpha_pal_halt(); /* XXX */ - db_error("Faulted in DDB; continuing...\n"); - /* NOTREACHED */ + return (0); + } + if (db_nofault) { + jmp_buf *no_fault = db_nofault; + db_nofault = 0; + longjmp(*no_fault, 1); } -#endif - - /* - * Tell caller "We did NOT handle the trap." - * Caller should panic, or whatever. - */ - return (0); } /* @@ -191,7 +193,10 @@ ddb_trap(a0, a1, a2, entry, regs) db_active++; cnpollc(TRUE); /* Set polling mode, unblank video */ - db_trap(entry, a0); /* Where the work happens */ + if (ddb_mode) + db_trap(entry, a0); /* Where the work happens */ + else + gdb_handle_exception(&ddb_regs, entry, a0); cnpollc(FALSE); /* Resume interrupt mode */ db_active--; @@ -217,9 +222,13 @@ db_read_bytes(addr, size, data) { register char *src; + db_nofault = &db_jmpbuf; + src = (char *)addr; while (size-- > 0) *data++ = *src++; + + db_nofault = 0; } /* @@ -233,10 +242,14 @@ db_write_bytes(addr, size, data) { register char *dst; + db_nofault = &db_jmpbuf; + dst = (char *)addr; while (size-- > 0) *dst++ = *data++; alpha_pal_imb(); + + db_nofault = 0; } void diff --git a/sys/alpha/alpha/machdep.c b/sys/alpha/alpha/machdep.c index aa4c791..27912cc 100644 --- a/sys/alpha/alpha/machdep.c +++ b/sys/alpha/alpha/machdep.c @@ -23,7 +23,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: machdep.c,v 1.3 1998/06/10 20:35:10 dfr Exp $ + * $Id: machdep.c,v 1.4 1998/06/28 00:45:50 dfr Exp $ */ /*- * Copyright (c) 1998 The NetBSD Foundation, Inc. @@ -524,8 +524,45 @@ alpha_init(pfn, ptb, bim, bip, biv) * information provided by the boot program). */ bootinfo_msg = NULL; - if (0) { - /* bootinfo goes here */ + if (bim == BOOTINFO_MAGIC) { + if (biv == 0) { /* backward compat */ + biv = *(u_long *)bip; + bip += 8; + } + switch (biv) { + case 1: { + struct bootinfo_v1 *v1p = (struct bootinfo_v1 *)bip; + + bootinfo.ssym = v1p->ssym; + bootinfo.esym = v1p->esym; + /* hwrpb may not be provided by boot block in v1 */ + if (v1p->hwrpb != NULL) { + bootinfo.hwrpb_phys = + ((struct rpb *)v1p->hwrpb)->rpb_phys; + bootinfo.hwrpb_size = v1p->hwrpbsize; + } else { + bootinfo.hwrpb_phys = + ((struct rpb *)HWRPB_ADDR)->rpb_phys; + bootinfo.hwrpb_size = + ((struct rpb *)HWRPB_ADDR)->rpb_size; + } + bcopy(v1p->boot_flags, bootinfo.boot_flags, + min(sizeof v1p->boot_flags, + sizeof bootinfo.boot_flags)); + bcopy(v1p->booted_kernel, bootinfo.booted_kernel, + min(sizeof v1p->booted_kernel, + sizeof bootinfo.booted_kernel)); + /* booted dev not provided in bootinfo */ + init_prom_interface((struct rpb *) + ALPHA_PHYS_TO_K0SEG(bootinfo.hwrpb_phys)); + prom_getenv(PROM_E_BOOTED_DEV, bootinfo.booted_dev, + sizeof bootinfo.booted_dev); + break; + } + default: + bootinfo_msg = "unknown bootinfo version"; + goto nobootinfo; + } } else { bootinfo_msg = "boot program did not pass bootinfo"; nobootinfo: @@ -555,6 +592,7 @@ alpha_init(pfn, ptb, bim, bip, biv) prom_getenv(PROM_E_BOOTED_DEV, bootinfo.booted_dev, sizeof bootinfo.booted_dev); } + printf("ssym=%lx, esym=%lx\n", bootinfo.ssym, bootinfo.esym); /* * Initialize the kernel's mapping of the RPB. It's needed for @@ -877,6 +915,7 @@ alpha_init(pfn, ptb, bim, bip, biv) #ifdef KADB boothowto |= RB_KDB; #endif +/* boothowto |= RB_KDB | RB_GDB; */ for (p = bootinfo.boot_flags; p && *p != '\0'; p++) { /* * Note that we'd really like to differentiate case here, @@ -896,11 +935,15 @@ alpha_init(pfn, ptb, bim, bip, biv) break; #endif -#if defined(KGDB) || defined(DDB) +#if defined(DDB) case 'd': /* break into the kernel debugger ASAP */ case 'D': boothowto |= RB_KDB; break; + case 'g': /* use kernel gdb */ + case 'G': + boothowto |= RB_GDB; + break; #endif case 'h': /* always halt, never reboot */ diff --git a/sys/alpha/alpha/trap.c b/sys/alpha/alpha/trap.c index 9fbabbb..c6cd53f 100644 --- a/sys/alpha/alpha/trap.c +++ b/sys/alpha/alpha/trap.c @@ -1,4 +1,4 @@ -/* $Id: trap.c,v 1.2 1998/06/10 20:12:22 dfr Exp $ */ +/* $Id: trap.c,v 1.3 1998/06/28 00:47:20 dfr Exp $ */ /* $NetBSD: trap.c,v 1.31 1998/03/26 02:21:46 thorpej Exp $ */ /* @@ -273,7 +273,7 @@ trap(a0, a1, a2, entry, framep) || a0 == ALPHA_IF_CODE_GENTRAP #endif ) { - if (ddb_trap(a0, a1, a2, entry, framep)) + if (kdb_trap(a0, a1, a2, entry, framep)) goto out; } @@ -467,20 +467,7 @@ dopanic: /* XXX dump registers */ #ifdef DDB - /* XXX - * Really would like to be able to indicate that the - * kernel should _not_ panic, here. However, two problems - * exist: - * - * (a) There is not currently a way for DDB to distinguish - * between "continue and panic" and "continue, and - * don't panic". - * - * (b) panic() will again invoke the debugger, so calling - * it here is silly. - * - * For now, we just do nothing. - */ + kdb_trap(a0, a1, a2, entry, framep); #endif panic("trap"); diff --git a/sys/alpha/include/db_machdep.h b/sys/alpha/include/db_machdep.h index a8c6b1f..1824cd9 100644 --- a/sys/alpha/include/db_machdep.h +++ b/sys/alpha/include/db_machdep.h @@ -100,7 +100,7 @@ db_addr_t db_branch_taken __P((int inst, db_addr_t pc, db_regs_t *regs)); #define next_instr_address(v, b) ((db_addr_t) ((b) ? (v) : ((v) + 4))) u_long db_register_value __P((db_regs_t *, int)); -int ddb_trap __P((unsigned long, unsigned long, unsigned long, +int kdb_trap __P((unsigned long, unsigned long, unsigned long, unsigned long, struct trapframe *)); /* |