This commit is contained in:
seta75D
2021-10-11 18:20:23 -03:00
commit 2e8a93c394
13448 changed files with 2891753 additions and 0 deletions

168
sys/sun4c/debug/Makefile Normal file
View 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
View 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 */

View 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

View 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

File diff suppressed because it is too large Load Diff

914
sys/sun4c/debug/machdep.c Normal file
View 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 *)&regsave;
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
View 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
View File

@@ -0,0 +1,4 @@
/* @(#)reg.h 1.1 92/07/30 SMI */
#include "allregs.h"

19
sys/sun4c/debug/stubs.c Normal file
View 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(){}