Init
This commit is contained in:
168
sys/sun4c/debug/Makefile
Normal file
168
sys/sun4c/debug/Makefile
Normal file
@@ -0,0 +1,168 @@
|
||||
# @(#)Makefile 1.1 92/07/30 SMI
|
||||
#
|
||||
# Sun-4c kernel debugger (kadb) makefile
|
||||
#
|
||||
ARCH= sun4c
|
||||
MACH= sparc
|
||||
CPU= SUN4C_60
|
||||
|
||||
CPP= /lib/cpp -undef
|
||||
|
||||
CPPOPTS= -DKADB -Dsun -D$(ARCH) -D$(MACH) -D$(CPU) -DKERNEL -I.. -I../..
|
||||
COPTS= -O
|
||||
CFLAGS= $(CPPOPTS) $(COPTS)
|
||||
ASFLAGS= -P $(CPPOPTS) -DLOCORE
|
||||
KADBDIR= ../../kadb
|
||||
|
||||
HFILES= ../../sun4c/debug/reg.h
|
||||
|
||||
CFILES= ../../sun4c/debug/machdep.c ../../debug/main.c \
|
||||
../../debug/support.c ../../sun4c/clock.c
|
||||
|
||||
SFILES= locore.s map.s
|
||||
|
||||
SPECIAL= locore.o
|
||||
|
||||
OBJ= $(SPECIAL) machdep.o map.o main.o support.o clock.o
|
||||
|
||||
debug.o: $(OBJ)
|
||||
$(LD) -r -o $@ $(OBJ)
|
||||
|
||||
assym.s: genassym.c
|
||||
$(CC) $(CFLAGS) -I. genassym.c
|
||||
-if [ `/bin/arch -k` = $(ARCH) ] ; \
|
||||
then \
|
||||
./a.out >assym.s; \
|
||||
else \
|
||||
sas -R a.out >assym.s 2>/dev/null; \
|
||||
fi
|
||||
@rm a.out
|
||||
|
||||
main.o: ../../debug/main.c
|
||||
$(CC) $(CFLAGS) -c ../../debug/main.c
|
||||
|
||||
support.o: ../../debug/support.c
|
||||
$(CC) $(CFLAGS) -c ../../debug/support.c
|
||||
|
||||
clock.o: ../clock.c
|
||||
$(CC) $(CFLAGS) -c ../clock.c
|
||||
|
||||
reloc:
|
||||
@echo 'FFC00000'
|
||||
|
||||
tags: $(KADBDIR)/tags
|
||||
@ cd $(KADBDIR); $(MAKE) -e $@
|
||||
ln -s $(KADBDIR)/tags $@
|
||||
|
||||
tags.list: FRC
|
||||
@echo $(HFILES) $(CFILES)
|
||||
|
||||
stags.list: FRC
|
||||
@for i in ${SFILES} ; do \
|
||||
echo ../../sun4c/debug/$$i ; done
|
||||
|
||||
clean:
|
||||
$(RM) a.out *.o assym.s
|
||||
|
||||
makedep: assym.s FRC
|
||||
@cat /dev/null >makedep
|
||||
@-(for i in ${CFILES} ${SFILES} genassym.c ; do \
|
||||
${CPP} -M ${CPPOPTS} $$i >> makedep; done) \
|
||||
2>makedeperrs
|
||||
@sed \
|
||||
-e 's,^.*genassym\.o:,assym.s assym.L:,' \
|
||||
-e 's,^\(.*\)\.o:,\1.o \1.L:,' makedep > makedep1
|
||||
@awk ' { if ($$1 != prev) { print rec; rec = $$0; prev = $$1; } \
|
||||
else { if (length(rec $$3) > 78) { print rec; rec = $$0; } \
|
||||
else rec = rec " " $$3 } } \
|
||||
END { print rec } ' makedep1 > makedep
|
||||
@cat makedeperrs >&- 1>&2
|
||||
@(if [ -s makedeperrs ]; then false; fi)
|
||||
|
||||
|
||||
depend: makedep
|
||||
@echo '/^# DO NOT DELETE THIS LINE/+1,$$d' >eddep
|
||||
@echo '$$r makedep' >>eddep
|
||||
@echo 'w' >>eddep
|
||||
@cp Makefile Makefile.bak
|
||||
@ed - Makefile < eddep
|
||||
@echo '# DEPENDENCIES MUST END AT END OF FILE' >> Makefile
|
||||
@echo '# IF YOU PUT STUFF HERE IT WILL GO AWAY' >> Makefile
|
||||
@echo '# see make depend above' >> Makefile
|
||||
@$(RM) eddep makedep makedep1 makedeperrs
|
||||
|
||||
FRC:
|
||||
|
||||
# DO NOT DELETE THIS LINE -- make depend uses it
|
||||
|
||||
machdep.o machdep.L: ../../sun4c/debug/machdep.c ../../sys/param.h
|
||||
machdep.o machdep.L: ../machine/param.h ../../sys/signal.h ../../vm/faultcode.h
|
||||
machdep.o machdep.L: ../../sys/types.h ../../sys/sysmacros.h ../../sys/errno.h
|
||||
machdep.o machdep.L: ../../sys/vmmac.h ../machine/buserr.h ../machine/enable.h
|
||||
machdep.o machdep.L: ../machine/mmu.h ../../debug/debug.h ../../mon/sunromvec.h
|
||||
machdep.o machdep.L: ../../sys/types.h ../../sys/param.h ../../mon/openprom.h
|
||||
machdep.o machdep.L: ../machine/romvec.h ../machine/cpu.h ../../mon/sunromvec.h
|
||||
machdep.o machdep.L: ../machine/pte.h ../machine/scb.h ../machine/psl.h
|
||||
machdep.o machdep.L: ../machine/trap.h ../machine/clock.h ../machine/intreg.h
|
||||
machdep.o machdep.L: ../machine/eeprom.h ../../mon/eeprom.h
|
||||
machdep.o machdep.L: ../../mon/keyboard.h ../../mon/password.h
|
||||
machdep.o machdep.L: ../../mon/idprom.h ../machine/asm_linkage.h
|
||||
machdep.o machdep.L: ../machine/reg.h ../machine/frame.h
|
||||
machdep.o machdep.L: ../../sun4c/debug/allregs.h ../../debug/debug.h
|
||||
machdep.o machdep.L: ../../debug/debugger.h /usr/include/setjmp.h
|
||||
machdep.o machdep.L: /usr/include/machine/setjmp.h ../../debug/debug.h
|
||||
main.o main.L: ../../debug/main.c ../../sys/param.h ../machine/param.h
|
||||
main.o main.L: ../../sys/signal.h ../../vm/faultcode.h ../../sys/types.h
|
||||
main.o main.L: ../../sys/sysmacros.h ../../sys/reboot.h ../machine/reg.h
|
||||
main.o main.L: ../../debug/debugger.h /usr/include/setjmp.h
|
||||
main.o main.L: /usr/include/machine/setjmp.h ../../debug/debug.h
|
||||
main.o main.L: ../../mon/sunromvec.h ../../sys/types.h ../../sys/param.h
|
||||
main.o main.L: ../../mon/openprom.h ../machine/romvec.h ../a.out.h
|
||||
main.o main.L: ../../sys/exec.h /usr/include/ctype.h
|
||||
support.o support.L: ../../debug/support.c ../../sys/param.h ../machine/param.h
|
||||
support.o support.L: ../../sys/signal.h ../../vm/faultcode.h ../../sys/types.h
|
||||
support.o support.L: ../../sys/sysmacros.h /usr/include/time.h
|
||||
support.o support.L: /usr/include/tzfile.h /usr/include/string.h
|
||||
support.o support.L: ../../sys/errno.h ../../sys/time.h ../machine/mmu.h
|
||||
support.o support.L: ../../debug/debug.h ../../mon/sunromvec.h
|
||||
support.o support.L: ../../sys/types.h ../../sys/param.h ../../mon/openprom.h
|
||||
support.o support.L: ../machine/romvec.h ../machine/pte.h ../machine/reg.h
|
||||
support.o support.L: ../../debug/debugger.h /usr/include/setjmp.h
|
||||
support.o support.L: /usr/include/machine/setjmp.h ../../debug/debug.h
|
||||
support.o support.L: ../../sys/ptrace.h /usr/include/varargs.h
|
||||
support.o support.L: ../machine/debug/allregs.h
|
||||
clock.o clock.L: ../../sun4c/clock.c ../../sys/param.h ../machine/param.h
|
||||
clock.o clock.L: ../../sys/signal.h ../../vm/faultcode.h ../../sys/types.h
|
||||
clock.o clock.L: ../../sys/sysmacros.h ../../sys/time.h ../../sys/kernel.h
|
||||
clock.o clock.L: ../machine/clock.h ../machine/intreg.h ../machine/pte.h
|
||||
locore.o locore.L: locore.s ./assym.s ../../sys/errno.h ../../sys/param.h
|
||||
locore.o locore.L: ../machine/param.h ../../sys/signal.h ../../vm/faultcode.h
|
||||
locore.o locore.L: ../../sys/types.h ../../sys/sysmacros.h
|
||||
locore.o locore.L: ../machine/asm_linkage.h ../machine/reg.h ../machine/mmu.h
|
||||
locore.o locore.L: ../../debug/debug.h ../../mon/sunromvec.h ../../sys/types.h
|
||||
locore.o locore.L: ../../sys/param.h ../../mon/openprom.h ../machine/romvec.h
|
||||
locore.o locore.L: ../machine/psl.h ../machine/pte.h ../machine/enable.h
|
||||
locore.o locore.L: ../machine/cpu.h ../../mon/sunromvec.h ../machine/trap.h
|
||||
locore.o locore.L: ../machine/eeprom.h ../../mon/eeprom.h ../../mon/keyboard.h
|
||||
locore.o locore.L: ../../mon/password.h ../../mon/idprom.h
|
||||
locore.o locore.L: ./../../debug/debug.h
|
||||
map.o map.L: map.s ./assym.s ../../sys/param.h ../machine/param.h
|
||||
map.o map.L: ../../sys/signal.h ../../vm/faultcode.h ../../sys/types.h
|
||||
map.o map.L: ../../sys/sysmacros.h ../machine/mmu.h ../../debug/debug.h
|
||||
map.o map.L: ../../mon/sunromvec.h ../../sys/types.h ../../sys/param.h
|
||||
map.o map.L: ../../mon/openprom.h ../machine/romvec.h ../machine/pte.h
|
||||
map.o map.L: ../machine/enable.h ../machine/cpu.h ../../mon/sunromvec.h
|
||||
map.o map.L: ../machine/eeprom.h ../../mon/eeprom.h ../../mon/keyboard.h
|
||||
map.o map.L: ../../mon/password.h ../../mon/idprom.h ../machine/asm_linkage.h
|
||||
map.o map.L: ../machine/reg.h ../../debug/debug.h
|
||||
assym.s assym.L: genassym.c ../../sys/param.h ../machine/param.h
|
||||
assym.s assym.L: ../../sys/signal.h ../../vm/faultcode.h ../../sys/types.h
|
||||
assym.s assym.L: ../../sys/sysmacros.h ../machine/pte.h ../machine/psl.h
|
||||
assym.s assym.L: ../machine/mmu.h ../../debug/debug.h ../../mon/sunromvec.h
|
||||
assym.s assym.L: ../../sys/types.h ../../sys/param.h ../../mon/openprom.h
|
||||
assym.s assym.L: ../machine/romvec.h ../machine/cpu.h ../../mon/sunromvec.h
|
||||
assym.s assym.L: ../../mon/sunromvec.h ./allregs.h ../machine/reg.h
|
||||
assym.s assym.L: ../../debug/debug.h
|
||||
# DEPENDENCIES MUST END AT END OF FILE
|
||||
# IF YOU PUT STUFF HERE IT WILL GO AWAY
|
||||
# see make depend above
|
||||
56
sys/sun4c/debug/allregs.h
Normal file
56
sys/sun4c/debug/allregs.h
Normal file
@@ -0,0 +1,56 @@
|
||||
/* @(#)allregs.h 1.1 92/07/30 SMI */
|
||||
|
||||
#ifndef _sun4c_debug_allregs_h
|
||||
#define _sun4c_debug_allregs_h
|
||||
|
||||
/*
|
||||
* Copyright (c) 1986 by Sun Microsystems, Inc.
|
||||
*/
|
||||
|
||||
/*
|
||||
* adb keeps its own idea of the current value of most of the
|
||||
* processor registers, in an "adb_regs" structure. This is used
|
||||
* in different ways for kadb, adb -k, and normal adb.
|
||||
*
|
||||
* For kadb, this is really the machine state -- so kadb must
|
||||
* get the current window pointer (CWP) field of the psr and
|
||||
* use it to index into the windows to find the currently
|
||||
* relevant register set.
|
||||
*
|
||||
* For a normal adb, the TBR and WIM registers aren't present in the
|
||||
* struct regs that we get (either within a core file, or from
|
||||
* PTRACE_GETREGS); so I might use those two fields for something.
|
||||
* In this case, we always ignore the "locals" half of register
|
||||
* window zero. Its "ins" half is used to hold the current "outs",
|
||||
* and window one has the current locals and "ins".
|
||||
*
|
||||
* For adb -k (post-mortem examination of kernel crash dumps), there
|
||||
* is no way to find the current globals or outs, but the stack frame
|
||||
* that sp points to will tell us the current locals and ins. Because
|
||||
* we have no current outs, I suppose that we could use window zero for
|
||||
* the locals and ins, but I'd prefer to make it the same as normal adb.
|
||||
* Also, if the kernel crash-dumper is changed to make these available
|
||||
* somehow, I'd have to change things again.
|
||||
*/
|
||||
|
||||
#include <machine/pcb.h>
|
||||
|
||||
#ifndef rw_fp
|
||||
# include <machine/reg.h>
|
||||
#endif
|
||||
|
||||
#ifndef LOCORE
|
||||
|
||||
struct allregs {
|
||||
int r_psr;
|
||||
int r_pc;
|
||||
int r_npc;
|
||||
int r_tbr;
|
||||
int r_wim;
|
||||
int r_y;
|
||||
int r_globals[7];
|
||||
struct rwindow r_window[MAXWIN]; /* locals, then ins */
|
||||
};
|
||||
|
||||
#endif !LOCORE
|
||||
#endif /* !_sun4c_debug_allregs_h */
|
||||
84
sys/sun4c/debug/asm_linkage.h
Normal file
84
sys/sun4c/debug/asm_linkage.h
Normal file
@@ -0,0 +1,84 @@
|
||||
/* @(#)asm_linkage.h 1.1 92/07/30 SMI */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1987 by Sun Microsystems, Inc.
|
||||
*/
|
||||
|
||||
#ifndef _REG_
|
||||
#include "reg.h"
|
||||
#endif
|
||||
|
||||
/*
|
||||
* A stack frame looks like:
|
||||
*
|
||||
* %fp->| |
|
||||
* |-------------------------------|
|
||||
* | Locals, temps, saved floats |
|
||||
* |-------------------------------|
|
||||
* | outgoing parameters past 6 |
|
||||
* |-------------------------------|-\
|
||||
* | 6 words for callee to dump | |
|
||||
* | register arguments | |
|
||||
* |-------------------------------| > minimum stack frame
|
||||
* | One word struct-ret address | |
|
||||
* |-------------------------------| |
|
||||
* | 16 words to save IN and | |
|
||||
* %sp->| LOCAL register on overflow | |
|
||||
* |-------------------------------|-/
|
||||
*/
|
||||
|
||||
/*
|
||||
* constants defining a stack frame.
|
||||
*/
|
||||
#define WINDOWSIZE (16*4)
|
||||
#define ARGPUSHSIZE (6*4) /* size of arg dump area */
|
||||
#define ARGPUSH (WINDOWSIZE+4) /* arg dump area offset */
|
||||
#define MINFRAME (WINDOWSIZE+ARGPUSHSIZE+8) /* min frame */
|
||||
|
||||
/*
|
||||
* Entry macros for assembler subroutines.
|
||||
* NAME prefixes the underscore before a symbol.
|
||||
* ENTRY provides a way to insert the calls to mcount for profiling.
|
||||
* RTENTRY is similar to the above but provided for run-time routines
|
||||
* whose names should not be prefixed with an underscore.
|
||||
*/
|
||||
#define NAME(x) _/**/x
|
||||
|
||||
#ifdef GPROF
|
||||
#define ENTRY(x) \
|
||||
.global NAME(x); \
|
||||
NAME(x): \
|
||||
mov %i7, %g1; \
|
||||
call mcount; \
|
||||
save %sp, -MINFRAME, %sp; \
|
||||
restore ;
|
||||
|
||||
#define ENTRY2(x,y) \
|
||||
.global NAME(x), NAME(y); \
|
||||
NAME(x): ; \
|
||||
NAME(y): \
|
||||
mov %i7, %g1; \
|
||||
call mcount; \
|
||||
save %sp, -MINFRAME, %sp;
|
||||
restore ;
|
||||
|
||||
#define RTENTRY(x) \
|
||||
.global x; x: ; \
|
||||
mov %i7, %g1; \
|
||||
call mcount; \
|
||||
save %sp, -MINFRAME, %sp; \
|
||||
restore ;
|
||||
|
||||
#else GPROF
|
||||
#define ENTRY(x) \
|
||||
.global NAME(x); \
|
||||
NAME(x):
|
||||
|
||||
#define ENTRY2(x,y) \
|
||||
ENTRY(x) \
|
||||
ENTRY(y)
|
||||
|
||||
#define RTENTRY(x) \
|
||||
.global x; x:
|
||||
|
||||
#endif GPROF
|
||||
59
sys/sun4c/debug/genassym.c
Normal file
59
sys/sun4c/debug/genassym.c
Normal file
@@ -0,0 +1,59 @@
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)genassym.c 1.1 92/07/30 SMI";
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Copyright (c) 1986 by Sun Microsystems, Inc.
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <machine/pte.h>
|
||||
#include <machine/psl.h>
|
||||
#include <machine/mmu.h>
|
||||
#include <machine/cpu.h>
|
||||
#include <mon/sunromvec.h>
|
||||
#include "allregs.h"
|
||||
#include <debug/debug.h>
|
||||
|
||||
static struct sunromvec *romp = (struct sunromvec *)0;
|
||||
|
||||
main()
|
||||
{
|
||||
register struct allregs *rp = (struct allregs *)0;
|
||||
|
||||
printf("#define\tR_PSR %d\n", &rp->r_psr);
|
||||
printf("#define\tR_PC %d\n", &rp->r_pc);
|
||||
printf("#define\tR_NPC %d\n", &rp->r_npc);
|
||||
printf("#define\tR_TBR %d\n", &rp->r_tbr);
|
||||
printf("#define\tR_WIM %d\n", &rp->r_wim);
|
||||
printf("#define\tR_Y %d\n", &rp->r_y);
|
||||
printf("#define\tR_G1 %d\n", &rp->r_globals[0]);
|
||||
printf("#define\tR_G2 %d\n", &rp->r_globals[1]);
|
||||
printf("#define\tR_G3 %d\n", &rp->r_globals[2]);
|
||||
printf("#define\tR_G4 %d\n", &rp->r_globals[3]);
|
||||
printf("#define\tR_G5 %d\n", &rp->r_globals[4]);
|
||||
printf("#define\tR_G6 %d\n", &rp->r_globals[5]);
|
||||
printf("#define\tR_G7 %d\n", &rp->r_globals[6]);
|
||||
printf("#define\tR_WINDOW %d\n", rp->r_window);
|
||||
printf("#define\tPSR_PIL_BIT %d\n", bit(PSR_PIL));
|
||||
printf("#define\tPG_S_BIT %d\n", bit(PG_S));
|
||||
printf("#define\tV_MAGIC 0x%x\n", &romp->op_magic);
|
||||
printf("#define\tV_ROMVEC_VERSION 0x%x\n", &romp->op_romvec_version);
|
||||
printf("#define\tV_PLUGIN_VERSION 0x%x\n", &romp->op_plugin_version);
|
||||
printf("#define\tV_MON_ID 0x%x\n", &romp->op_mon_id);
|
||||
printf("#define\tEXIT_TO_MON 0x%x\n", &romp->op_exit);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
bit(mask)
|
||||
register long mask;
|
||||
{
|
||||
register int i;
|
||||
|
||||
for (i = 0; i < 32; i++) {
|
||||
if (mask & 1)
|
||||
return (i);
|
||||
mask >>= 1;
|
||||
}
|
||||
exit (1);
|
||||
}
|
||||
1003
sys/sun4c/debug/locore.s
Normal file
1003
sys/sun4c/debug/locore.s
Normal file
File diff suppressed because it is too large
Load Diff
914
sys/sun4c/debug/machdep.c
Normal file
914
sys/sun4c/debug/machdep.c
Normal file
@@ -0,0 +1,914 @@
|
||||
#ident "@(#)machdep.c 1.1 92/07/30"
|
||||
|
||||
/*
|
||||
* Copyright (c) 1986 by Sun Microsystems, Inc.
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/errno.h>
|
||||
#include <sys/vmmac.h>
|
||||
#include <sun/openprom.h>
|
||||
#include <machine/buserr.h>
|
||||
#include <machine/enable.h>
|
||||
#include <machine/mmu.h>
|
||||
#include <machine/cpu.h>
|
||||
#include <machine/pte.h>
|
||||
#include <machine/scb.h>
|
||||
#include <machine/psl.h>
|
||||
#include <machine/trap.h>
|
||||
#include <machine/clock.h>
|
||||
#include <machine/intreg.h>
|
||||
#include <machine/eeprom.h>
|
||||
#include <machine/asm_linkage.h>
|
||||
#include <machine/reg.h>
|
||||
#include <machine/frame.h>
|
||||
#include "allregs.h"
|
||||
#include <debug/debug.h>
|
||||
#include <debug/debugger.h>
|
||||
|
||||
extern int errno;
|
||||
extern char *malloc();
|
||||
|
||||
int istrap = 0;
|
||||
int scbsyncdone = 0;
|
||||
|
||||
/*
|
||||
* The next group of variables and routines handle the
|
||||
* Open Boot Prom devinfo or property information.
|
||||
*
|
||||
* These machine-dependent quantities are set from the prom properties.
|
||||
* For the time being, set these to "large, safe" values.
|
||||
* XXX - does this all want to be packaged in a header file?
|
||||
*/
|
||||
extern void fiximp();
|
||||
extern int Cpudelay;
|
||||
extern int nwindows;
|
||||
extern u_int npmgrps;
|
||||
extern int vac_size;
|
||||
extern int vac_linesize;
|
||||
extern int segmask;
|
||||
extern int mips_off, mips_on; /* approx. MIPS with cache off/on */
|
||||
/*
|
||||
* properties tchotchkes
|
||||
*/
|
||||
#define GETPROPLEN prom_getproplen
|
||||
#define GETPROP prom_getprop
|
||||
#define NEXT prom_nextnode
|
||||
#define CHILD prom_childnode
|
||||
extern int getprop();
|
||||
|
||||
/*
|
||||
* Open proms give us romp as a variable
|
||||
*/
|
||||
struct sunromvec *romp = (struct sunromvec *)0xFFE81000;
|
||||
|
||||
int fake_bpt; /* place for a fake breakpoint at startup */
|
||||
jmp_buf debugregs; /* context for debugger */
|
||||
jmp_buf mainregs; /* context for debuggee */
|
||||
jmp_buf_ptr curregs; /* pointer to saved context for each process */
|
||||
int cache_on; /* cache is being used */
|
||||
struct allregs regsave; /* temp save area--align to double */
|
||||
struct scb *mon_tbr, *our_tbr; /* storage for %tbr's */
|
||||
|
||||
int use_kern_tbr = 0;
|
||||
|
||||
extern char start[], estack[], etext[], edata[], end[];
|
||||
extern int exit();
|
||||
extern struct scb *gettbr();
|
||||
|
||||
/*
|
||||
* Definitions for registers in jmp_buf
|
||||
*/
|
||||
#define JB_PC 0
|
||||
#define JB_SP 1
|
||||
|
||||
#define CALL(func) (*(int (*)())((int)(func) - (int)start + (int)real))
|
||||
#define RELOC(adr) ((adr) - (char *)start + real)
|
||||
extern setcontext(), getsegmap(), setsegmap(), getpgmap(), setpgmap();
|
||||
extern printf();
|
||||
void Setpgmap();
|
||||
|
||||
/*
|
||||
* This routine is called before we are relocated to the correct address,
|
||||
* so everything is done via funny macros when dealing w/ globals.
|
||||
* Also, we have a candidate for "worst abuse of preprocessor" award:
|
||||
* MONSTART and MONEND are actually defined using romp, but _romp
|
||||
* isn't set yet. Call our sunromvec argument "romp" so that the global
|
||||
* variable is hidden in this function and the correct value is used.
|
||||
*/
|
||||
early_startup(real, romp)
|
||||
register char *real;
|
||||
register struct sunromvec *romp;
|
||||
{
|
||||
register u_int cnt, pg, i;
|
||||
register int *from, *to;
|
||||
register int pm, lopm;
|
||||
register int lastpmsav, lastpgsav;
|
||||
register struct memlist *pmem;
|
||||
caddr_t vstart;
|
||||
int too_big = 0;
|
||||
u_int npmgrps; /* yes, this hides the global too */
|
||||
|
||||
(void) CALL(setcontext)(0);
|
||||
/*
|
||||
* We need to know npmgrps so we can compute PMGRP_INVALID.
|
||||
* We'll do this again later for the real globals.
|
||||
* Alas! We can't just call getprop(), because the global romp
|
||||
* isn't even mapped in yet. We want to do this:
|
||||
* if ((int)CALL(getprop)(0, "mmu-npmg", &npmgrps) <= 0)
|
||||
* npmgrps = NPMGRPS_60;
|
||||
* but we have to do this:
|
||||
*/
|
||||
if ((*romp->op_config_ops->devr_getproplen)
|
||||
(0, RELOC("mmu-npmg")) == sizeof (int))
|
||||
{
|
||||
(*romp->op_config_ops->devr_getprop)
|
||||
(0, RELOC("mmu-npmg"), &npmgrps);
|
||||
} else
|
||||
npmgrps = NPMGRPS_60;
|
||||
|
||||
/*
|
||||
* Find the top of physical memory and take as many pages as we need.
|
||||
* We assume the physmem chunks are in ascending order and the last
|
||||
* chunk is big enough to hold us. (It actually doesn't matter if
|
||||
* the pages are in order; we handle that gracefully.)
|
||||
*/
|
||||
cnt = mmu_btopr(end - start);
|
||||
if (romp->op_romvec_version > 0) {
|
||||
vstart = (caddr_t)(*romp->op2_alloc)((int)start,
|
||||
mmu_ptob(cnt));
|
||||
if ((u_int)vstart != (u_int)start)
|
||||
too_big = 1;
|
||||
} else {
|
||||
pmem = *romp->v_availmemory;
|
||||
while (pmem->next != (struct memlist *)NULL)
|
||||
pmem = pmem->next;
|
||||
pg = mmu_btopr(pmem->address + pmem->size) - cnt;
|
||||
if (mmu_ptob(cnt) > pmem->size) {
|
||||
too_big = 1;
|
||||
} else {
|
||||
too_big = 0;
|
||||
pmem->size -= mmu_ptob(cnt);
|
||||
}
|
||||
|
||||
/*
|
||||
* Look for the lowest pmeg in use in the monitor
|
||||
* and "DVMA" space
|
||||
*/
|
||||
lopm = PMGRP_INVALID;
|
||||
for (i = MONSTART; i != 0; i += PMGRPSIZE)
|
||||
if (((pm = CALL(getsegmap)(i)) < lopm) && pm)
|
||||
lopm = pm;
|
||||
|
||||
/*
|
||||
* Adjust down from there to get our starting pmeg
|
||||
* and save copies of last pmeg and page used.
|
||||
*/
|
||||
lopm -= ((unsigned)(end - start) + PMGRPOFFSET) >> PMGRPSHIFT;
|
||||
lastpmsav = lopm;
|
||||
lastpgsav = pg;
|
||||
|
||||
for (i = (int)start; i < (int)end; i += MMU_PAGESIZE) {
|
||||
if (CALL(getsegmap)(i) == PMGRP_INVALID) {
|
||||
register u_int j = i & ~PMGRPOFFSET;
|
||||
u_int last = j + NPMENTPERPMGRP * MMU_PAGESIZE;
|
||||
|
||||
(void) CALL(setsegmap)(i, lopm++);
|
||||
while (j < last) {
|
||||
(void) CALL(setpgmap)(j, 0);
|
||||
j += MMU_PAGESIZE;
|
||||
}
|
||||
}
|
||||
(void) CALL(setpgmap)(i, PG_V | PG_KW | PG_NC | pg++);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Copy program up to correct address
|
||||
*/
|
||||
for (to = (int *)start, from = (int *)real; to < (int *)edata; )
|
||||
*to++ = *from++;
|
||||
for (to = (int *)edata; to < (int *)end; ++to)
|
||||
*to = 0;
|
||||
|
||||
/*
|
||||
* Now we can reference global variables,
|
||||
* save page count and monitor's nmi routine address.
|
||||
* Don't need this information on OBP.
|
||||
*/
|
||||
if (romp->op_romvec_version > 0) {
|
||||
lastpg = 0;
|
||||
lastpm = 0;
|
||||
pagesused = 0;
|
||||
mon_tbr = gettbr();
|
||||
if (too_big) {
|
||||
CALL(printf)(
|
||||
RELOC("kadb: size %x exceeded available memory\n"),
|
||||
mmu_ptob(cnt));
|
||||
_exit(1);
|
||||
}
|
||||
} else {
|
||||
lastpg = lastpgsav;
|
||||
lastpm = lastpmsav;
|
||||
pagesused = cnt;
|
||||
mon_tbr = gettbr();
|
||||
if (too_big) {
|
||||
CALL(printf)(
|
||||
RELOC(
|
||||
"kadb: size %x exceeded available memory %x\n"),
|
||||
mmu_ptob(cnt), pmem->size);
|
||||
_exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Startup code after relocation.
|
||||
*/
|
||||
startup()
|
||||
{
|
||||
register int i;
|
||||
register int pg;
|
||||
u_char intreg;
|
||||
register int vaddr, pmeg;
|
||||
register int cpu;
|
||||
extern void prom_init();
|
||||
|
||||
|
||||
prom_init("Kadb");
|
||||
|
||||
/*
|
||||
* Set our implementation parameters from the prom properties.
|
||||
*/
|
||||
fiximp();
|
||||
|
||||
if (prom_getversion() > 0) {
|
||||
vaddr = (int)(*romp->op2_map)(COUNTER_ADDR, OBIO,
|
||||
OBIO_COUNTER_ADDR, MMU_PAGESIZE);
|
||||
vaddr = (int)(*romp->op2_map)(INTREG_ADDR, OBIO,
|
||||
OBIO_INTREG_ADDR, MMU_PAGESIZE);
|
||||
} else {
|
||||
/*
|
||||
* We need to get a pmeg for the devices we are mapping in.
|
||||
* Assume the devices lie within the same segment.
|
||||
*/
|
||||
vaddr = EEPROM_ADDR & COUNTER_ADDR & INTREG_ADDR;
|
||||
pmeg = getsegmap(vaddr);
|
||||
if (pmeg == PMGRP_INVALID) {
|
||||
setsegmap(vaddr, --lastpm);
|
||||
}
|
||||
/*
|
||||
* Now map! Remember: on a sun4c, the clock is in the eeprom.
|
||||
*/
|
||||
Setpgmap((caddr_t)EEPROM_ADDR,
|
||||
PG_V|PG_KW|PGT_OBIO|btop(OBIO_EEPROM_ADDR));
|
||||
Setpgmap((caddr_t)COUNTER_ADDR,
|
||||
PG_V|PG_KW|PGT_OBIO|btop(OBIO_COUNTER_ADDR));
|
||||
Setpgmap((caddr_t)INTREG_ADDR,
|
||||
PG_V|PG_KW|PGT_OBIO|btop(OBIO_INTREG_ADDR));
|
||||
}
|
||||
set_clk_mode(IR_ENA_CLK14, 0);
|
||||
|
||||
/*
|
||||
* Fix up old scb.
|
||||
*/
|
||||
kadbscbsync();
|
||||
spl13(); /* we can take nmi's now */
|
||||
|
||||
/*
|
||||
* Now make text (and dvec) read only,
|
||||
* this also sets a stack redzone
|
||||
*/
|
||||
for (i = (int)start; i < (int)etext; i += MMU_PAGESIZE) {
|
||||
pg = getpgmap(i);
|
||||
Setpgmap(i, (pg & ~PG_PROT) | PG_KR);
|
||||
}
|
||||
|
||||
cache_on = getenablereg() & ENA_CACHE;
|
||||
if (cache_on) {
|
||||
setdelay(mips_on);
|
||||
} else {
|
||||
setdelay(mips_off);
|
||||
vac_init(); /* invalidate entire cache */
|
||||
}
|
||||
}
|
||||
|
||||
scbsync()
|
||||
{
|
||||
kadbscbsync();
|
||||
scbsyncdone = 1;
|
||||
}
|
||||
|
||||
kadbscbsync()
|
||||
{
|
||||
register struct scb *tbr;
|
||||
register int otbr_pg;
|
||||
extern trapvec tcode;
|
||||
|
||||
tbr = gettbr();
|
||||
otbr_pg = getpgmap(tbr);
|
||||
Setpgmap(tbr, (otbr_pg & ~PG_PROT) | PG_KW);
|
||||
|
||||
tbr->user_trap[TRAPBRKNO-1] = tcode;
|
||||
tbr->user_trap[TRAPBRKNO] = tcode;
|
||||
Setpgmap(tbr, otbr_pg);
|
||||
if (scbstop) {
|
||||
/*
|
||||
* We're running interactively. Trap into the debugger
|
||||
* so the user can look around before continuing.
|
||||
* We use trap TRAPBRKNO-1: "enter debugger"
|
||||
*/
|
||||
scbstop = 0;
|
||||
asm_trap(TRAPBRKNO-1);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Sys_trap trap handlers.
|
||||
*/
|
||||
|
||||
/*
|
||||
* level15 (memory error) interrupt.
|
||||
*/
|
||||
level15()
|
||||
{
|
||||
/*
|
||||
* For now, the memory error regs are not mapped into the debugger,
|
||||
* so we just print a message.
|
||||
*/
|
||||
printf("memory error\n");
|
||||
}
|
||||
|
||||
/*
|
||||
* Miscellanous fault error handler
|
||||
*/
|
||||
fault(trap, trappc, trapnpc)
|
||||
register int trap;
|
||||
register int trappc;
|
||||
register int trapnpc;
|
||||
{
|
||||
register int ondebug_stack;
|
||||
register u_int *pc;
|
||||
register u_int realpc;
|
||||
|
||||
ondebug_stack = (getsp() > (int)etext && getsp() < (int)estack);
|
||||
if (trap == T_DATA_FAULT && nofault && ondebug_stack) {
|
||||
jmp_buf_ptr sav = nofault;
|
||||
|
||||
nofault = NULL;
|
||||
_longjmp(sav, 1);
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
traceback(getsp());
|
||||
/*
|
||||
* If we are on the debugger stack and
|
||||
* abort_jmp is set, do a longjmp to it.
|
||||
*/
|
||||
if (abort_jmp && ondebug_stack) {
|
||||
printf("abort jump: trap %x sp %x pc %x npc %x\n",
|
||||
trap, getsp(), trappc, trapnpc);
|
||||
printf("etext %x estack %x edata %x nofault %x\n",
|
||||
etext, estack, edata, nofault);
|
||||
_longjmp(abort_jmp, 1);
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
|
||||
/*
|
||||
* Ok, the user faulted while not in the
|
||||
* debugger. Enter the main cmd loop
|
||||
* so that the user can look around...
|
||||
*/
|
||||
/*
|
||||
* There is a problem here since we really need to tell cmd()
|
||||
* the current registers. We would like to call cmd() in locore
|
||||
* but the interface is not really set up to handle this (yet?)
|
||||
*/
|
||||
|
||||
printf("fault and calling cmd: trap %x sp %x pc %x npc %x\n",
|
||||
trap, getsp(), trappc, trapnpc);
|
||||
cmd(); /* error not resolved, enter debugger */
|
||||
}
|
||||
|
||||
long trap_window[25];
|
||||
static jmp_buf_ptr saved_jb;
|
||||
static jmp_buf jb;
|
||||
extern int debugging;
|
||||
|
||||
|
||||
/*
|
||||
* Peekc is so named to avoid a naming conflict
|
||||
* with adb which has a variable named peekc
|
||||
*/
|
||||
int
|
||||
Peekc(addr)
|
||||
char *addr;
|
||||
{
|
||||
u_char val;
|
||||
|
||||
saved_jb = nofault;
|
||||
nofault = jb;
|
||||
errno = 0;
|
||||
if (!_setjmp(jb)) {
|
||||
val = *addr;
|
||||
/* if we get here, it worked */
|
||||
nofault = saved_jb;
|
||||
return ((int)val);
|
||||
}
|
||||
/* a fault occured */
|
||||
nofault = saved_jb;
|
||||
errno = EFAULT;
|
||||
return (-1);
|
||||
}
|
||||
|
||||
short
|
||||
peek(addr)
|
||||
short *addr;
|
||||
{
|
||||
short val;
|
||||
|
||||
saved_jb = nofault;
|
||||
nofault = jb;
|
||||
errno = 0;
|
||||
if (!_setjmp(jb)) {
|
||||
val = *addr;
|
||||
/* if we get here, it worked */
|
||||
nofault = saved_jb;
|
||||
return (val);
|
||||
}
|
||||
/* a fault occured */
|
||||
nofault = saved_jb;
|
||||
errno = EFAULT;
|
||||
return (-1);
|
||||
}
|
||||
long
|
||||
peekl(addr)
|
||||
long *addr;
|
||||
{
|
||||
long val;
|
||||
|
||||
saved_jb = nofault;
|
||||
nofault = jb;
|
||||
errno = 0;
|
||||
if (!_setjmp(jb)) {
|
||||
val = *addr;
|
||||
/* if we get here, it worked */
|
||||
nofault = saved_jb;
|
||||
return (val);
|
||||
}
|
||||
/* a fault occured */
|
||||
nofault = saved_jb;
|
||||
errno = EFAULT;
|
||||
return (-1);
|
||||
}
|
||||
|
||||
int
|
||||
pokec(addr, val)
|
||||
char *addr;
|
||||
char val;
|
||||
{
|
||||
|
||||
saved_jb = nofault;
|
||||
nofault = jb;
|
||||
errno = 0;
|
||||
if (!_setjmp(jb)) {
|
||||
*addr = val;
|
||||
/* if we get here, it worked */
|
||||
nofault = saved_jb;
|
||||
return (0);
|
||||
}
|
||||
/* a fault occured */
|
||||
nofault = saved_jb;
|
||||
errno = EFAULT;
|
||||
return (-1);
|
||||
}
|
||||
|
||||
int
|
||||
pokel(addr, val)
|
||||
long *addr;
|
||||
long val;
|
||||
{
|
||||
|
||||
saved_jb = nofault;
|
||||
nofault = jb;
|
||||
errno = 0;
|
||||
if (!_setjmp(jb)) {
|
||||
*addr = val;
|
||||
/* if we get here, it worked */
|
||||
nofault = saved_jb;
|
||||
return (0);
|
||||
}
|
||||
/* a fault occured */
|
||||
nofault = saved_jb;
|
||||
errno = EFAULT;
|
||||
return (-1);
|
||||
}
|
||||
|
||||
poketext(addr, val)
|
||||
int *addr;
|
||||
int val;
|
||||
{
|
||||
int pg = 0;
|
||||
|
||||
pg = getpgmap((int)addr);
|
||||
if ((pg & PG_V) == 0) {
|
||||
if (debugging > 2)
|
||||
printf("poketext: invalid page map %X at %X\n",
|
||||
pg, addr);
|
||||
goto err;
|
||||
}
|
||||
if ((pg & PGT_MASK) != PGT_OBMEM) {
|
||||
if (debugging > 2)
|
||||
printf("poketext: incorrect page type %X at %X\n",
|
||||
pg, addr);
|
||||
goto err;
|
||||
}
|
||||
|
||||
vac_pageflush(addr);
|
||||
if (btop(addr + sizeof (int) - 1) != btop(addr))
|
||||
vac_pageflush(addr + sizeof (int) - 1);
|
||||
|
||||
if ((pg & PG_PROT) == PG_KR)
|
||||
Setpgmap(addr, (pg & ~PG_PROT) | PG_KW);
|
||||
else if ((pg & PG_PROT) == PG_URKR)
|
||||
Setpgmap(addr, (pg & ~PG_PROT) | PG_UW);
|
||||
/* otherwise it is already writeable */
|
||||
*addr = val; /* should be prepared to catch a fault here? */
|
||||
/*
|
||||
* Reset to page map to previous entry,
|
||||
* but mark as modified
|
||||
*/
|
||||
vac_pageflush(addr);
|
||||
if (btop(addr + sizeof (int) - 1) != btop(addr))
|
||||
vac_pageflush(addr + sizeof (int) - 1);
|
||||
Setpgmap(addr, pg | PG_M);
|
||||
errno = 0;
|
||||
return (0);
|
||||
|
||||
err:
|
||||
errno = EFAULT;
|
||||
return (-1);
|
||||
}
|
||||
|
||||
scopy(from, to, count)
|
||||
register char *from;
|
||||
register char *to;
|
||||
register int count;
|
||||
{
|
||||
register int val;
|
||||
|
||||
for (; count > 0; count--) {
|
||||
if ((val = Peekc(from++)) == -1)
|
||||
goto err;
|
||||
if (pokec(to++, val) == -1)
|
||||
goto err;
|
||||
}
|
||||
return (0);
|
||||
err:
|
||||
errno = EFAULT;
|
||||
return (-1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Setup a new context to run at routine using stack whose
|
||||
* top (end) is at sp. Assumes that the current context
|
||||
* is to be initialized for mainregs and new context is
|
||||
* to be set up in debugregs.
|
||||
*/
|
||||
spawn(sp, routine)
|
||||
char *sp;
|
||||
func_t routine;
|
||||
{
|
||||
char *fp;
|
||||
int res;
|
||||
|
||||
if (curregs != 0) {
|
||||
printf("bad call to spawn\n");
|
||||
exit(1);
|
||||
}
|
||||
if ((res = _setjmp(mainregs)) == 0) {
|
||||
/*
|
||||
* Setup top (null) window.
|
||||
*/
|
||||
sp -= WINDOWSIZE;
|
||||
((struct rwindow *)sp)->rw_rtn = 0;
|
||||
((struct rwindow *)sp)->rw_fp = 0;
|
||||
/*
|
||||
* Setup window for routine with return to exit.
|
||||
*/
|
||||
fp = sp;
|
||||
sp -= WINDOWSIZE;
|
||||
((struct rwindow *)sp)->rw_rtn = (int)exit - 8;
|
||||
((struct rwindow *)sp)->rw_fp = (int)fp;
|
||||
/*
|
||||
* Setup new return window with routine return value.
|
||||
*/
|
||||
fp = sp;
|
||||
sp -= WINDOWSIZE;
|
||||
((struct rwindow *)sp)->rw_rtn = (int)routine - 8;
|
||||
((struct rwindow *)sp)->rw_fp = (int)fp;
|
||||
/* copy entire jump buffer to debugregs */
|
||||
bcopy((caddr_t)mainregs, (caddr_t)debugregs, sizeof (jmp_buf));
|
||||
debugregs[JB_SP] = (int)sp; /* set sp */
|
||||
curregs = debugregs;
|
||||
regsave.r_npc = (int)&fake_bpt;
|
||||
_longjmp(debugregs, 1); /* jump to new context */
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
doswitch()
|
||||
{
|
||||
int res;
|
||||
|
||||
if ((res = _setjmp(curregs)) == 0) {
|
||||
/*
|
||||
* Switch curregs to other descriptor
|
||||
*/
|
||||
if (curregs == mainregs) {
|
||||
curregs = debugregs;
|
||||
} else /* curregs == debugregs */ {
|
||||
curregs = mainregs;
|
||||
}
|
||||
_longjmp(curregs, 1);
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
/*
|
||||
* else continue on in new context
|
||||
*/
|
||||
}
|
||||
|
||||
/*
|
||||
* Main interpreter command loop.
|
||||
*/
|
||||
cmd()
|
||||
{
|
||||
int resetclk = 0;
|
||||
u_char intreg;
|
||||
int addr, t;
|
||||
int i;
|
||||
u_char interreg;
|
||||
int s;
|
||||
|
||||
dorun = 0;
|
||||
i = 0;
|
||||
|
||||
/*
|
||||
* See if the sp says that we are already on the debugger stack
|
||||
*/
|
||||
reg = (struct regs *)®save;
|
||||
addr = getsp();
|
||||
if (addr > (int)etext && addr < (int)estack) {
|
||||
printf("Already in debugger!\n");
|
||||
return;
|
||||
}
|
||||
cache_on = getenablereg() & ENA_CACHE;
|
||||
if (cache_on)
|
||||
setdelay(mips_on);
|
||||
else
|
||||
setdelay(mips_off);
|
||||
do {
|
||||
doswitch();
|
||||
if (dorun == 0)
|
||||
printf("cmd: nothing to do\n");
|
||||
} while (dorun == 0);
|
||||
/* we don't need to splx since we are returning to the caller */
|
||||
/* and will reset his/her state */
|
||||
}
|
||||
|
||||
/*
|
||||
* Return an available physical page number
|
||||
*/
|
||||
int
|
||||
getapage()
|
||||
{
|
||||
register struct memlist *pmem;
|
||||
register caddr_t addr;
|
||||
|
||||
/*
|
||||
* Find the top of physical memory and take the top pages.
|
||||
* We assume the physmem chunks are in ascending order and
|
||||
* the last chunk is non-zero.
|
||||
*/
|
||||
pmem = *romp->v_availmemory;
|
||||
|
||||
for( ; pmem->next != (struct memlist *)NULL; pmem = pmem->next)
|
||||
;
|
||||
if (pmem->size < MMU_PAGESIZE) {
|
||||
printf("panic: getapage: last physmem chunk too small\n");
|
||||
_exit();
|
||||
}
|
||||
pmem->size -= MMU_PAGESIZE;
|
||||
return (mmu_btop(pmem->address + pmem->size));
|
||||
}
|
||||
|
||||
/*
|
||||
* Call into the monitor (hopefully)
|
||||
*/
|
||||
montrap(funcptr)
|
||||
int (*funcptr)();
|
||||
{
|
||||
our_tbr = gettbr();
|
||||
if (use_kern_tbr) {
|
||||
settbr(regsave.r_tbr);
|
||||
} else
|
||||
settbr(mon_tbr);
|
||||
/*
|
||||
* Must do the following because libprom calls
|
||||
* montrap to "enter" and "exit_to" the prom.
|
||||
* Since kadb has this montrap function we
|
||||
* are calling through here. Thus, if an argument
|
||||
* is passed do as libprom's routine does, else
|
||||
* do as before.
|
||||
*/
|
||||
if (funcptr)
|
||||
(*funcptr)();
|
||||
else
|
||||
(*romp->op_exit)();
|
||||
settbr(our_tbr);
|
||||
}
|
||||
|
||||
/*
|
||||
* set delay constant for usec_delay()
|
||||
* delay ~= (usecs * (Cpudelay * 2 + 3) + 8) / mips
|
||||
* => Cpudelay = ceil((mips - 3) / 2)
|
||||
*/
|
||||
static
|
||||
setdelay(mips)
|
||||
int mips;
|
||||
{
|
||||
extern int Cpudelay;
|
||||
|
||||
Cpudelay = 0;
|
||||
if (mips > 3)
|
||||
Cpudelay = (mips - 2) >> 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the pme for address v using the software pte given.
|
||||
* Setpgmap() automatically turns on the ``no cache'' bit
|
||||
* for all mappings between DEBUGSTART and DEBUGEND.
|
||||
*/
|
||||
void
|
||||
Setpgmap(v, pte)
|
||||
caddr_t v;
|
||||
int pte;
|
||||
{
|
||||
if (v >= (caddr_t)DEBUGSTART && v <= (caddr_t)DEBUGEND)
|
||||
pte |= PG_NC;
|
||||
setpgmap(v, pte);
|
||||
}
|
||||
|
||||
traceback(sp)
|
||||
caddr_t sp;
|
||||
{
|
||||
register u_int tospage;
|
||||
register struct frame *fp;
|
||||
static int done = 0;
|
||||
|
||||
#ifdef PARTIAL_ALIGN
|
||||
if (partial_align? ((int)sp & 0x3): ((int)sp & 0x7)) {
|
||||
#else
|
||||
if ((int)sp & (STACK_ALIGN-1)) {
|
||||
#endif PARTIAL_ALIGN
|
||||
printf("traceback: misaligned sp = %x\n", sp);
|
||||
return;
|
||||
}
|
||||
flush_windows();
|
||||
tospage = (u_int)btoc(sp);
|
||||
fp = (struct frame *)sp;
|
||||
printf("Begin traceback... sp = %x\n", sp);
|
||||
while (btoc((u_int)fp) == tospage) {
|
||||
if (fp == fp->fr_savfp) {
|
||||
printf("FP loop at %x", fp);
|
||||
break;
|
||||
}
|
||||
printf("Called from %x, fp=%x, args=%x %x %x %x %x %x\n",
|
||||
fp->fr_savpc, fp->fr_savfp,
|
||||
fp->fr_arg[0], fp->fr_arg[1], fp->fr_arg[2],
|
||||
fp->fr_arg[3], fp->fr_arg[4], fp->fr_arg[5]);
|
||||
#ifdef notdef
|
||||
printf("\tl0-l7: %x, %x, %x, %x, %x, %x, %x, %x\n",
|
||||
fp->fr_local[0], fp->fr_local[1],
|
||||
fp->fr_local[2], fp->fr_local[3],
|
||||
fp->fr_local[4], fp->fr_local[5],
|
||||
fp->fr_local[6], fp->fr_local[7]);
|
||||
#endif
|
||||
fp = fp->fr_savfp;
|
||||
if (fp == 0)
|
||||
break;
|
||||
}
|
||||
printf("End traceback...\n");
|
||||
}
|
||||
|
||||
our_die_routine(retaddr)
|
||||
register caddr_t retaddr;
|
||||
{
|
||||
#ifdef NOTYET
|
||||
(*romp->op_chain)(0, 0, retaddr+8);
|
||||
/* NOTREACHED */
|
||||
#endif
|
||||
;
|
||||
}
|
||||
|
||||
struct memlist *
|
||||
getmemlist(name, prop)
|
||||
char *name, *prop;
|
||||
{
|
||||
int nodeid;
|
||||
int i, j, k, chunks;
|
||||
u_int propsize;
|
||||
struct dev_reg *rp;
|
||||
struct memlist *pmem;
|
||||
static caddr_t bufp = (caddr_t)0;
|
||||
static u_int left;
|
||||
|
||||
if (bufp == (caddr_t) 0) {
|
||||
bufp = (caddr_t)(*romp->op2_alloc)((caddr_t)0, PAGESIZE);
|
||||
left = PAGESIZE;
|
||||
}
|
||||
|
||||
/*
|
||||
* First find the right node.
|
||||
*/
|
||||
nodeid = search(NEXT(0), name, bufp);
|
||||
if (nodeid == 0)
|
||||
return ((struct memlist *)0);
|
||||
|
||||
/*
|
||||
* Allocate memlist elements, one per dev_reg struct.
|
||||
*/
|
||||
propsize = (u_int)GETPROPLEN(nodeid, prop);
|
||||
chunks = propsize / sizeof (struct dev_reg);
|
||||
if (chunks == 0)
|
||||
return ((struct memlist *)0);
|
||||
if (left < (chunks * sizeof (struct memlist))) {
|
||||
printf("memlists too big");
|
||||
return ((struct memlist *)0);
|
||||
}
|
||||
pmem = (struct memlist *)bufp;
|
||||
bzero((caddr_t)pmem, (u_int) chunks * sizeof (struct memlist));
|
||||
left -= (u_int) chunks * sizeof (struct memlist);
|
||||
bufp += (u_int) chunks * sizeof (struct memlist);
|
||||
if (left < propsize) {
|
||||
printf("buffer too small");
|
||||
return ((struct memlist *)0);
|
||||
}
|
||||
/*
|
||||
* Fill in memlist chunks.
|
||||
*/
|
||||
rp = (struct dev_reg *)bufp;
|
||||
bzero((caddr_t)rp, propsize);
|
||||
left -= propsize;
|
||||
bufp += propsize;
|
||||
|
||||
(void)GETPROP(nodeid, prop, rp);
|
||||
for (i = 0; i < chunks; ++i) {
|
||||
if (rp[i].reg_bustype != OBMEM)
|
||||
continue;
|
||||
|
||||
/*
|
||||
* Insert the new element into the array of list nodes
|
||||
* so that the array remains sorted in ascending order.
|
||||
*/
|
||||
|
||||
/* Find the first element with a larger address */
|
||||
for (j = 0; j < i; j++)
|
||||
if (pmem[j].address > (u_int)rp[i].reg_addr)
|
||||
break;
|
||||
|
||||
/* Copy following elements up to make room for the new one */
|
||||
for (k = i; k > j; --k)
|
||||
pmem[k] = pmem[k-1];
|
||||
|
||||
/* Insert the new element */
|
||||
pmem[j].address = (u_int)rp[i].reg_addr;
|
||||
pmem[j].size = rp[i].reg_size;
|
||||
}
|
||||
for (i = 1; i < chunks; ++i) {
|
||||
if (pmem[i].address)
|
||||
pmem[i-1].next = &pmem[i];
|
||||
}
|
||||
return (pmem);
|
||||
}
|
||||
|
||||
search(node, name, buf)
|
||||
int node;
|
||||
char *name;
|
||||
char *buf;
|
||||
{
|
||||
int id;
|
||||
|
||||
*buf = '\0';
|
||||
(void)GETPROP(node, "name", buf);
|
||||
if (strcmp(buf, name) == 0) {
|
||||
return (node);
|
||||
}
|
||||
id = NEXT(node);
|
||||
if (id && (id = search(id, name, buf)))
|
||||
return (id);
|
||||
id = CHILD(node);
|
||||
if (id && (id = search(id, name, buf)))
|
||||
return (id);
|
||||
return (0);
|
||||
}
|
||||
100
sys/sun4c/debug/map.s
Normal file
100
sys/sun4c/debug/map.s
Normal file
@@ -0,0 +1,100 @@
|
||||
/* @(#)map.s 1.1 92/07/30 */
|
||||
|
||||
!
|
||||
! Copyright (c) 1986 by Sun Microsystems, Inc.
|
||||
!
|
||||
|
||||
/*
|
||||
* Additional memory mapping routines for use by standalone debugger,
|
||||
* setpgmap(), getpgmap() are taken from the boot code.
|
||||
*/
|
||||
|
||||
#include "assym.s"
|
||||
#include <sys/param.h>
|
||||
#include <machine/mmu.h>
|
||||
#include <machine/pte.h>
|
||||
#include <machine/enable.h>
|
||||
#include <machine/cpu.h>
|
||||
#include <machine/eeprom.h>
|
||||
#include <machine/asm_linkage.h>
|
||||
#include <machine/reg.h>
|
||||
#include <debug/debug.h>
|
||||
|
||||
.seg "text"
|
||||
.align 4
|
||||
|
||||
/*
|
||||
* get the machine type in the ID prom.
|
||||
*
|
||||
* u_char
|
||||
* getmachinetype()
|
||||
*/
|
||||
ENTRY(getmachinetype)
|
||||
set IDPROM_ADDR+1, %o0
|
||||
retl
|
||||
ldub [%o0], %o0
|
||||
|
||||
/*
|
||||
* Flush a page from the cache.
|
||||
*
|
||||
* vac_pageflush(vaddr)
|
||||
* caddr_t vaddr;
|
||||
*/
|
||||
ENTRY(vac_pageflush)
|
||||
srl %o0, PGSHIFT, %o0 ! mask off low bits
|
||||
sll %o0, PGSHIFT, %o0
|
||||
set MMU_PAGESIZE, %o1 ! compute NLINES=PAGESIZE/LINESIZE
|
||||
set _vac_linesize, %o2 ! ...number of lines to flush
|
||||
ld [%o2], %o2
|
||||
sll %o2, 2, %o5 ! VAC_LINESIZE * 4
|
||||
0:
|
||||
srl %o2, 1, %o2 ! we "know" LINESIZE is a power of 2
|
||||
tst %o2 ! so just shift until LINESIZE
|
||||
bnz,a 0b ! goes to zero
|
||||
srl %o1, 1, %o1
|
||||
mov 16, %o2 ! offsets for by 4 loop unroll
|
||||
mov 32, %o3
|
||||
mov 48, %o4
|
||||
1: ! flush a 4 line chunk of the cache
|
||||
sta %g0, [%o0]ASI_FCP ! offset 0
|
||||
sta %g0, [%o0 + %o2]ASI_FCP ! offset 16
|
||||
sta %g0, [%o0 + %o3]ASI_FCP ! offset 32
|
||||
sta %g0, [%o0 + %o4]ASI_FCP ! offset 48
|
||||
subcc %o1, 4, %o1 ! decrement count
|
||||
bg 1b ! done yet?
|
||||
add %o0, %o5, %o0 ! generate next match address
|
||||
2:
|
||||
retl
|
||||
nop
|
||||
|
||||
/*
|
||||
* Initialize the cache, write all tags to zero
|
||||
*
|
||||
* vac_init()
|
||||
*/
|
||||
ENTRY(vac_init)
|
||||
set CACHE_TAGS, %o0 ! address of cache tags in CTL space
|
||||
set _vac_size, %o1 ! compute NLINES=SIZE/LINESIZE
|
||||
ld [%o1], %o1 ! ...number of lines to initialize
|
||||
set _vac_linesize, %o2
|
||||
ld [%o2], %o2
|
||||
sll %o2, 2, %o5 ! VAC_LINESIZE * 4
|
||||
0:
|
||||
srl %o2, 1, %o2 ! we "know" LINESIZE is a power of 2
|
||||
tst %o2 ! so just shift until LINESIZE
|
||||
bnz,a 0b ! goes to zero
|
||||
srl %o1, 1, %o1
|
||||
mov 16, %o2 ! offsets for by 4 loop unroll
|
||||
mov 32, %o3
|
||||
mov 48, %o4
|
||||
1:
|
||||
sta %g0, [%o0]ASI_CTL ! write tags to zero
|
||||
sta %g0, [%o0 + %o2]ASI_CTL ! offset 16
|
||||
sta %g0, [%o0 + %o3]ASI_CTL ! offset 32
|
||||
sta %g0, [%o0 + %o4]ASI_CTL ! offset 48
|
||||
subcc %o1, 4, %o1 ! done yet?
|
||||
bg 1b
|
||||
add %o0, %o5, %o0 ! next cache tags address
|
||||
|
||||
retl
|
||||
nop
|
||||
4
sys/sun4c/debug/reg.h
Normal file
4
sys/sun4c/debug/reg.h
Normal file
@@ -0,0 +1,4 @@
|
||||
/* @(#)reg.h 1.1 92/07/30 SMI */
|
||||
|
||||
#include "allregs.h"
|
||||
|
||||
19
sys/sun4c/debug/stubs.c
Normal file
19
sys/sun4c/debug/stubs.c
Normal file
@@ -0,0 +1,19 @@
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)stubs.c 1.1 92/07/30";
|
||||
#endif
|
||||
|
||||
#include "reg.h"
|
||||
|
||||
struct allregs regsave;
|
||||
|
||||
int pagesused;
|
||||
int lastpg;
|
||||
int lastpm;
|
||||
|
||||
scbsync(){}
|
||||
startup(){}
|
||||
main(){}
|
||||
fault(){}
|
||||
cmd(){}
|
||||
level14(){}
|
||||
level15(){}
|
||||
Reference in New Issue
Block a user