Files
seta75D 2e8a93c394 Init
2021-10-11 18:20:23 -03:00

992 lines
22 KiB
C

#ifndef lint
static char sccsid[] = "@(#)machdep.c 1.1 92/07/30 SMI";
#endif
/*
* Copyright (c) 1987 by Sun Microsystems, Inc.
*/
#include <sys/param.h>
#include <sys/errno.h>
#include <sys/vmmac.h>
#include <machine/buserr.h>
#include <machine/enable.h>
#include <machine/mmu.h>
#include <machine/cpu.h>
#include <machine/pte.h>
#include <machine/reg.h>
#include <machine/scb.h>
#include <machine/psl.h>
#include <machine/trap.h>
#include <mon/keyboard.h>
#include <debug/debugger.h>
#if defined(sun3) || defined(sun3x)
#include <machine/clock.h>
#include <machine/interreg.h>
#endif sun3 || sun3x
extern int errno;
extern int dottysync;
int scbsyncdone = 0;
#define T_TRAP 0x80 /* vector address for trap #0 */
#define CALL(func) (*(int (*)())((int)(func) - (int)start + real))
#define RELOC(adr) ((adr) - (int)start + real)
#ifdef sun3x
#undef CLKADDR
#define CLKADDR ((struct intersil7170 *)(DEBUGEND - 2 * MMU_PAGESIZE + \
(OBIO_CLKADDR & MMU_PAGEOFFSET)))
#undef INTERREG
#define INTERREG ((u_char *)(DEBUGEND - MMU_PAGESIZE + \
(OBIO_INTERREG & MMU_PAGEOFFSET)))
#undef ENABLEREG
#define ENABLEREG ((u_short *)(0xfef18000))
#define TMPVADDR ((caddr_t)(DEBUGEND - 3 * MMU_PAGESIZE))
int cpudelay = 2; /* XXX-this is a guess */
int cpu;
extern Setpgmap(), atc_flush(), RELOC_Setpgmap();
extern u_int Getpgmap(), getpteaddr();
#endif sun3x
#ifdef sun3
#define DVMA 0x0ff00000 /* 28 bit DVMA addr for sun3 */
int cpudelay = 3;
int cpu;
#endif sun3
#ifdef sun2
#define DVMA 0x00f00000 /* 24 bit DVMA addr for sun2 */
int cpudelay = 5;
#endif sun2
#define RTE 0x4e73 /* code for a 680x0 rte instruction */
#define TRAP 0x4e40 /* code for a 680x0 trap intruction */
#define TRAPBRK (TRAP | TRAPBRKNO) /* code for a trap breakpoint intr */
extern char estack[], etext[];
/*
* Definitions for registers in jmp_buf
*/
#define JB_PC 3
#define JB_A6 15
#define JB_A7 2
static jmp_buf state; /* used for temporary games */
/*
* This routine is called before we are relocated to the correct address,
* so everything is done via funny macros when dealing w/ globals.
*/
startup(real)
register int real;
{
register int cnt, pg, i;
register int *from, *to;
#ifndef sun3x
int pm, lopm;
int lastpmsav;
#endif sun3x
int lastpgsav;
struct scb *vbr;
func_t *fp;
extern Setpgmap(), setkcontext(), getsegmap(), setsegmap();
extern char start[], end[], etext[];
#ifdef sun3x
union {
struct pte pte;
int ipte;
} tmppte;
struct physmemory *pmem;
int last;
#endif sun3x
#ifndef sun3x
(void) CALL(setkcontext)();
#endif sun3x
cnt = btoc(end - ((int)start & ~PGOFSET));
#ifndef sun3x
/*
* DOESN'T WORK WITH REV N PROTOTYPE PROMS!!!
* v_memorysize is the amount of physical memory while
* v_memoryavail is the amount of usable memory in versions
* equal or greater to 1.
*/
if (romp->v_romvec_version >= 1)
pg = btoc(*romp->v_memoryavail) - cnt;
else
pg = btoc(*romp->v_memorysize) - cnt;
/*
* Look for the lowest pmeg in use in the monitor and DVMA space
*/
lopm = PMGRP_INVALID;
for (i = MONSTART; i < MONEND; i += NBSG)
if ((pm = CALL(getsegmap)(i)) < lopm)
lopm = pm;
for (i = DVMA; i < DVMA + 0x100000; i += NBSG)
if ((pm = CALL(getsegmap)(i)) < lopm)
lopm = pm;
/*
* Adjust down from there to get our starting pmeg
* and save copies of last pmeg and page used.
*/
lopm -= (((int)end+SGOFSET)&~SGOFSET)-((int)start&~SGOFSET) >> SGSHIFT;
lastpmsav = lopm;
lastpgsav = pg;
for (i = (int)start; i < (int)end; i += NBPG) {
if (CALL(getsegmap)(i) == PMGRP_INVALID) {
register int j = i & ~SGOFSET;
int last = j + NPMENTPERPMGRP * NBPG;
(void) CALL(setsegmap)(i, lopm++);
for (; j < last; j += NBPG)
(void) CALL(Setpgmap)(j, 0);
}
(void) CALL(Setpgmap)(i, PG_V | PG_KW | pg++);
}
#else sun3x
tmppte.ipte = MMU_INVALIDPTE;
tmppte.pte.pte_vld = PTE_VALID;
for (pmem = romp->v_physmemory;pmem != (struct physmemory *)NULL;
pmem = pmem->next)
last = (int) pmem->address + pmem->size;
pg = btoc(last - (*romp->v_memorysize - *romp->v_memoryavail)) - cnt;
lastpgsav = pg;
for (i = (int)start; i < (int)end; i += NBPG) {
tmppte.pte.pte_pfn = pg++;
(void) CALL(RELOC_Setpgmap)(i, tmppte.ipte, real);
}
CALL(atc_flush)();
#endif sun3x
/*
* Copy program up to correct address
*/
for (to = (int *)start, from = (int *)real; to < (int *)end; )
*to++ = *from++;
/*
* Now we can reference global variables,
* save page count and monitor's nmi routine address.
*/
lastpg = lastpgsav;
#ifndef sun3x
lastpm = lastpmsav;
#endif sun3x
pagesused = cnt;
vbr = getvbr();
monnmi = vbr->scb_autovec[7 - 1];
/*
* initialize the exception vectors (except nmi, trace, and
* trap) to all point to our fault handling routine, then
* call scbsync() to take care of trace & trap routines.
*/
for (fp = (func_t *)vbr; fp < &vbr->scb_user[0]; fp++) {
if (fp != &vbr->scb_autovec[7 - 1] && fp != &vbr->scb_trace &&
!(fp >= &vbr->scb_trap[0] && fp <= &vbr->scb_trap[16 - 1]))
*fp = fault;
}
kadbscbsync();
/*
* Now make text (and dvec) read only,
* this also sets a stack redzone
*/
#ifndef sun3x
for (i = (int)start; i < (int)etext; i += NBPG) {
pg = Getpgmap(i);
Setpgmap(i, (pg & ~PG_PROT) | PG_KR);
}
#ifdef sun3
Setpgmap((caddr_t)CLKADDR, PG_V|PG_KW|PGT_OBIO|btop(OBIO_CLKADDR));
Setpgmap((caddr_t)INTERREG, PG_V|PG_KW|PGT_OBIO|btop(OBIO_INTERREG));
if ((cpu = getmachinetype()) == CPU_SUN3_260) {
cpudelay = 2;
cache_init(); /* invalidate entire cache */
}
#endif sun3
#else sun3x
for (i = (int) start; i < (int) etext; i += NBPG) {
tmppte.ipte = Getpgmap(i);
tmppte.pte.pte_readonly = 1;
Setpgmap(i, tmppte.ipte);
}
tmppte.ipte = MMU_INVALIDPTE;
tmppte.pte.pte_vld = PTE_VALID;
tmppte.pte.pte_pfn = btop(OBIO_CLKADDR);
Setpgmap((caddr_t)CLKADDR, tmppte.ipte);
tmppte.pte.pte_pfn = btop(OBIO_INTERREG);
Setpgmap((caddr_t)INTERREG, tmppte.ipte);
atc_flush();
#endif sun3x
#ifdef never
/*
* Initialize more of the page mappings so we can boot
* programs that are larger than 0xc0000 - 0x4000!
*/
pg = PG_V | PG_UW | (0xc0000 >> MMU_PAGESHIFT);
for (i = 0xc0000; i < 0x200000; i += NBPG)
Setpgmap(i, pg++);
#endif sun2
/*
* If we are using an old keyboard, avoid calling monitor's
* initgetkey() routine because of a bug which will toggle
* the state of the CAPS lock!
*/
if ((*romp->v_keybid & 0xF) == KB_VT100 ||
(*romp->v_keybid & 0xF) == KB_MS_103SD32)
dottysync = 0;
}
scbsync()
{
kadbscbsync();
scbsyncdone = 1;
}
kadbscbsync()
{
struct scb *vbr = getvbr();
vbr->scb_trap[10] = trap; /* install trap handler */
if (vbr->scb_trace != trace) {
ktrace = vbr->scb_trace; /* save old handler */
vbr->scb_trace = trace; /* install new handler */
}
if (scbstop) {
/*
* Set things up so that we call the debugger.
* Use _setjmp()/_longjmp() with some adjustments
* to pull this non-local goto off correctly.
*/
scbstop = 0;
(void) _setjmp(state);
state[JB_PC] = DVEC; /* new pc value */
state[JB_A7] = state[JB_A6]; /* pop off frame */
state[JB_A6] = *(int *)state[JB_A6]; /* restore fp */
_longjmp(state, 1);
/*NOTREACHED*/
}
}
#if defined(sun3) || defined(sun3x)
/*
* Set and/or clear the desired clock bits in the interrupt
* register. We have to be extremely careful that we do it
* in such a manner that we don't get ourselves lost.
*/
set_clk_mode(on, off)
u_char on, off;
{
register u_char interreg, dummy;
/*
* make sure that we are only playing w/
* clock interrupt register bits
*/
on &= (IR_ENA_CLK7 | IR_ENA_CLK5);
off &= (IR_ENA_CLK7 | IR_ENA_CLK5);
/*
* Get a copy of current interrupt register,
* turning off any undesired bits (aka `off')
*/
interreg = *INTERREG & ~(off | IR_ENA_INT);
*INTERREG &= ~IR_ENA_INT;
/*
* Next we turns off the CLK5 and CLK7 bits to clear
* the flip-flops, then we disable clock interrupts.
* Now we can read the clock's interrupt register
* to clear any pending signals there.
*/
#ifdef sun3x
*ENABLEREG |= (short) 0x100;
#endif
*INTERREG &= ~(IR_ENA_CLK7 | IR_ENA_CLK5);
CLKADDR->clk_cmd = (CLK_CMD_NORMAL & ~CLK_CMD_INTRENA);
dummy = CLKADDR->clk_intrreg; /* clear clock */
#ifdef lint
dummy = dummy;
#endif
/*
* Now we set all the desired bits
* in the interrupt register, then
* we turn the clock back on and
* finally we can enable all interrupts.
*/
*INTERREG |= (interreg | on); /* enable flip-flops */
CLKADDR->clk_cmd = CLK_CMD_NORMAL; /* enable clock intr */
*INTERREG |= IR_ENA_INT; /* enable interrupts */
}
#endif sun3 || sun3x
/*
* Miscellanous fault error handler
*/
faulterr(dfc, sfc, regs, fmt)
struct regs regs;
struct stkfmt fmt;
{
int ondebug_stack = (getsp() > (int)etext && getsp() < (int)estack);
if (nofault && ondebug_stack) {
jmp_buf_ptr sav = nofault;
nofault = NULL;
_longjmp(sav, 1);
/*NOTREACHED*/
}
showregs(ondebug_stack ? "unexpected fault" : "unexpected exception",
&regs, &fmt);
/*
* If we are on the debugger stack and
* abort_jmp is set, do a longjmp to it.
*/
if (abort_jmp && ondebug_stack) {
_longjmp(abort_jmp, 1);
/*NOTREACHED*/
}
/*
* Ok, the user faulted while not in the
* debugger. Just return to locore which will
* bounce us back out to the main cmd loop
* so that the user can look around...
*/
}
showregs(str, locregs, fmtp)
char *str;
struct regs *locregs;
struct stkfmt *fmtp;
{
int *r;
int fcode, accaddr;
char *why;
printf("\n%s: %s\n", myname, str);
printf("trap address 0x%x, pc = %x, sr = %x, stkfmt %x\n",
fmtp->f_vector, locregs->r_pc, locregs->r_sr, fmtp->f_stkfmt);
switch (fmtp->f_stkfmt) {
#if defined(sun3) || defined(sun3x)
case SF_MEDIUM: {
struct bei_medium *beip =
(struct bei_medium *)&fmtp->f_beibase;
fcode = beip->bei_fcode;
if (beip->bei_dfault) {
why = "data";
accaddr = beip->bei_fault;
} else if (beip->bei_faultc) {
why = "stage c";
accaddr = locregs->r_pc+2;
} else if (beip->bei_faultb) {
why = "stage b";
accaddr = locregs->r_pc+4;
} else {
why = "unknown";
accaddr = 0;
}
printf("%s fault address %x faultc %d faultb %d ",
why, accaddr, beip->bei_faultc, beip->bei_faultb);
printf("dfault %d rw %d size %d fcode %d\n",
beip->bei_dfault, beip->bei_rw,
beip->bei_size, fcode);
break;
}
case SF_LONGB: {
struct bei_longb *beip =
(struct bei_longb *)&fmtp->f_beibase;
fcode = beip->bei_fcode;
if (beip->bei_dfault) {
why = "data";
accaddr = beip->bei_fault;
} else if (beip->bei_faultc) {
why = "stage c";
accaddr = beip->bei_stageb-2;
} else if (beip->bei_faultb) {
why = "stage b";
accaddr = beip->bei_stageb;
} else {
why = "unknown";
accaddr = 0;
}
printf("%s fault address %x faultc %d faultb %d ",
why, accaddr, beip->bei_faultc, beip->bei_faultb);
printf("dfault %d rw %d size %d fcode %d\n",
beip->bei_dfault, beip->bei_rw, beip->bei_size, fcode);
break;
}
#endif sun3 || sun3x
#ifdef sun2
case SF_LONG8: {
struct bei_long8 *beip =
(struct bei_long8 *)&fmtp->f_beibase;
fcode = beip->bei_fcode;
accaddr = beip->bei_accaddr;
printf("access address %x ifetch %d dfetch %d ",
accaddr, beip->bei_ifetch, beip->bei_dfetch);
printf("hibyte %d bytex %d rw %d fcode %d\n",
beip->bei_hibyte, beip->bei_bytex, beip->bei_rw, fcode);
break;
}
#endif sun2
default:
printf("bad bus error stack format %x\n", fmtp->f_stkfmt);
}
r = &locregs->r_dreg[0];
printf("D0-D7 %x %x %x %x %x %x %x %x\n",
r[0], r[1], r[2], r[3], r[4], r[5], r[6], r[7]);
r = &locregs->r_areg[0];
printf("A0-A7 %x %x %x %x %x %x %x %x\n",
r[0], r[1], r[2], r[3], r[4], r[5], r[6], r[7]);
}
static jmp_buf_ptr saved_jb;
static jmp_buf jb;
extern int debugging;
poketext(addr, val)
int *addr;
int val;
{
int pg = 0;
struct scb *scb = getvbr();
func_t oldbus;
oldbus = scb->scb_buserr;
scb->scb_buserr = faulterr;
again:
saved_jb = nofault;
nofault = jb;
if (!_setjmp(jb)) {
*addr = val;
/* if we get here, it worked */
nofault = saved_jb;
if (pg) {
/*
* Reset to page map to previous entry,
* but mark as modified
*/
#ifdef sun3
if (cpu == CPU_SUN3_260) {
cache_pageflush(addr);
if (btop(addr + sizeof (int) - 1) != btop(addr))
cache_pageflush(addr + sizeof (int) - 1);
}
#endif sun3
#ifdef sun3x
atc_flush();
#endif sun3x
Setpgmap(addr, pg | PG_M);
}
scb->scb_buserr = oldbus;
return (0);
}
/* a fault occured */
nofault = saved_jb;
if (pg) {
/*
* Reset to page map to previous entry.
*/
#ifdef sun3
if (cpu == CPU_SUN3_260) {
cache_pageflush(addr);
if (btop(addr + sizeof (int) - 1) != btop(addr))
cache_pageflush(addr + sizeof (int) - 1);
}
#endif sun3
#ifdef sun3x
atc_flush();
#endif sun3x
Setpgmap((int)addr, pg);
if (debugging > 2)
printf("poketext %X failed\n", addr);
goto err;
}
/*
* See if the problem was a write protected page.
* If so, make the page writable, do the operation,
* and then put the protections back as we found them.
*/
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;
}
#ifndef sun3x
if ((pg & PGT_MASK) != PGT_OBMEM) {
#else sun3x
if (MAKE_PFNUM((struct pte *)&pg) > mmu_btop(ENDOFTYPE0)) {
#endif sun3x
if (debugging > 2)
printf("poketext: incorrect page type %X at %X\n",
pg, addr);
goto err;
}
/*
* Make page writable
*/
#ifdef sun3
if (cpu == CPU_SUN3_260) {
cache_pageflush(addr);
if (btop(addr + sizeof (int) - 1) != btop(addr))
cache_pageflush(addr + sizeof (int) - 1);
}
#endif sun3
#ifdef sun3x
atc_flush();
#endif sun3x
if ((pg & PG_PROT) == PG_KR)
Setpgmap(addr, (pg & ~PG_PROT) | PG_KW);
else if ((pg & PG_PROT) == PG_UR)
Setpgmap(addr, (pg & ~PG_PROT) | PG_UW);
else {
if (debugging > 2)
printf("poketext: unknown page prot %X at %X\n",
pg, addr);
goto err;
}
/*
* Now try again
*/
goto again;
err:
scb->scb_buserr = oldbus;
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)
int *sp;
func_t routine;
{
int *fp;
if (curregs != 0) {
printf("bad call to spawn\n");
exit(1);
}
if (!_setjmp(mainregs)) {
*--sp = (int)exit; /* routine to goto if routine returns */
*--sp = 0; /* terminate fp's */
fp = sp; /* save address of this fp */
*--sp = (int)routine;
*--sp = (int)fp;
/* copy entire jump buffer to debugregs */
bcopy((caddr_t)mainregs, (caddr_t)debugregs, sizeof (jmp_buf));
debugregs[JB_A6] = (int)sp; /* set fp */
debugregs[JB_A7] = (int)sp; /* set sp */
curregs = debugregs;
_longjmp(debugregs, 1);/* jump to new context */
/*NOTREACHED*/
}
}
doswitch()
{
if (!_setjmp(curregs)) {
/*
* Switch curregs to other descriptor
*/
if (curregs == mainregs) {
curregs = debugregs;
} else /* curregs == debugregs */ {
#if defined(sun3) || defined(sun3x)
flush20();
#endif sun3 || sun3x
#ifdef sun3x
vac_flush();
#endif sun3x
curregs = mainregs;
}
_longjmp(curregs, 1);
/*NOTREACHED*/
}
/*
* else continue on in new context
*/
}
/*
* tracestate is used to track tracing over instruction
* when an `rte' instruction is used. This allows us
* to single step over an rte instruction into user code.
* HOWEVER, the more difficult problem of rte'ing to
* the middle of an rte back to user land cannot be
* handled reliably (Motorola doesn't give enough visable
* info in the exception frames to do this right).
*
* TS_IDLE = normal state
* TS_RTE = debuggee executing `rte' w/ trace bit on
*/
#define TS_IDLE 0
#define TS_RTE 1
int tracestate = TS_IDLE;
int istrap = 0;
/*
* Main interpreter command loop.
*/
cmd(dfc, sfc, regs, fmt)
struct regs regs;
struct stkfmt fmt;
{
register struct scb *vbr = getvbr();
func_t nmisav = vbr->scb_autovec[7 - 1];
func_t buserrsav = vbr->scb_buserr;
func_t addrerrsav = vbr->scb_addrerr;
func_t illinstsav = vbr->scb_illinst;
func_t zerodivsav = vbr->scb_zerodiv;
#if defined(sun3) || defined(sun3x)
int resetclk = 0;
u_char interreg;
#endif sun3 || sun3x
#ifdef sun2
int uc;
short enable;
#endif sun2
int addr, t;
dotrace = dorun = 0;
reg = &regs;
/*
* See if the sp says that we are already on the debugger stack
*/
addr = getsp();
if (addr > (int)etext && addr < (int)estack) {
printf("Already in debugger!\n");
goto out;
}
if (fmt.f_vector == T_TRAP + TRAPBRKNO * sizeof (int))
istrap = 1;
else
istrap = 0;
/*
* Set up for monitor's input routines to work. This
* requires that the monitor's nmi handler is installed,
* interrupts (and level7 clock) are enabled. Also,
* for sun2 we make sure we are in the correct context.
* In addition, we adjust the sp so that it looks like
* the correct value BEFORE the expection was taken.
*/
dorun = dotrace = 0;
vbr->scb_autovec[7 - 1] = monnmi;
vbr->scb_buserr = fault;
vbr->scb_addrerr = fault;
vbr->scb_illinst = fault;
vbr->scb_zerodiv = fault;
regs.r_sp = (int)&fmt.f_beibase;
#if defined(sun3) || defined(sun3x)
switch (fmt.f_stkfmt) {
case SF_NORMAL6:
regs.r_sp += sizeof (struct bei_normal6);
break;
case SF_COPROC:
regs.r_sp += sizeof (struct bei_coproc);
break;
case SF_MEDIUM:
regs.r_sp += sizeof (struct bei_medium);
break;
case SF_LONGB:
regs.r_sp += sizeof (struct bei_longb);
break;
}
if ((*INTERREG & (IR_ENA_INT | IR_ENA_CLK7)) !=
(IR_ENA_INT | IR_ENA_CLK7)) {
resetclk = 1;
interreg = *INTERREG;
set_clk_mode(IR_ENA_CLK7, 0);
}
#endif sun3 || sun3x
#ifdef sun2
if (fmt.f_stkfmt == SF_LONG8)
regs.r_sp += sizeof (struct bei_long8);
enable = getenable();
setenable(enable | ENA_INTS);
uc = getusercontext();
setusercontext(KCONTEXT);
#endif sun2
do {
doswitch();
t = (dotrace == 0 && dorun == 0);
if (t)
printf("cmd: nothing to do\n");
} while (t);
/*
* Restore state - context, interrupt regs, nmi and clock values
*/
#ifdef sun2
setusercontext(uc);
setenable(enable);
#endif sun2
#if defined(sun3) || defined(sun3x)
if (resetclk) {
set_clk_mode(0, IR_ENA_CLK7);
*INTERREG = interreg;
}
#endif sun3 || sun3x
vbr->scb_autovec[7 - 1] = nmisav;
vbr->scb_buserr = buserrsav;
vbr->scb_addrerr = addrerrsav;
vbr->scb_illinst = illinstsav;
vbr->scb_zerodiv = zerodivsav;
out:
t = tracestate;
if (dotrace == 0) {
regs.r_ps &= ~PSL_T;
tracestate = TS_IDLE;
return (t == TS_RTE);
}
/*
* trying to single step, check tracestate
*/
if (t == TS_IDLE && trace_rte(&regs, &fmt)) {
tracestate = TS_RTE;
} else if (t == TS_RTE) {
tracestate = TS_IDLE;
}
/*
* If we are about to execute an rte instruction to an sr
* which does not have the trace bit on, turn it on now.
*/
if ((addr = rte_addr(&regs, &fmt)) != 0) {
int sr;
if ((sr = peek(addr)) != -1 && (sr & PSL_T) == 0)
(void) poke(addr, sr | PSL_T);
}
regs.r_ps |= PSL_T;
return (t == TS_RTE);
}
/*
* Return the address of the eventual sr for rte or 0 if none
*/
rte_addr(r, f)
register struct regs *r;
register struct stkfmt *f;
{
int offset;
if (peek(r->r_pc) != RTE)
return (0);
/*
* read the ps value for rte which is atop the stack,
*/
switch (f->f_stkfmt) {
case SF_NORMAL:
offset = 0;
break;
#if defined(sun3) || defined(sun3x)
case SF_THROWAWAY:
offset = 0;
break;
case SF_NORMAL6:
offset = sizeof (struct bei_normal6);
break;
case SF_COPROC:
offset = sizeof (struct bei_coproc);
break;
case SF_MEDIUM:
offset = sizeof (struct bei_medium);
break;
case SF_LONGB:
offset = sizeof (struct bei_longb);
break;
#endif sun3 || sun3x
#ifdef sun2
case SF_LONG8:
offset = sizeof (struct bei_long8);
break;
#endif sun2
default:
printf("rte_addr: unknown stack format %x\n", f->f_stkfmt);
return (0);
}
offset += 0xa; /* sizeof ((long)sr + pc + (short)fmt) */
return (r->r_sp + offset);
}
/*
* Return true if we are about to execute an rte which will set the trace bit.
*/
trace_rte(r, f)
register struct regs *r;
register struct stkfmt *f;
{
register int sr, addr;
if (((addr = rte_addr(r, f)) == 0) || /* not an rte instruction */
((sr = peek(addr)) == -1) || /* shouldn't happen */
((sr & PSL_T) == 0)) /* the trace bit was off */
return (0);
else
return (1);
}
/*
* Return an available physical page number
*/
int
getapage()
{
extern int lastpg;
return (--lastpg);
}
#ifdef sun3x
Setpgmap(addr, pte)
u_int addr, pte;
{
u_int physaddr, offset;
union {
struct pte pte;
u_int ipte;
} tpte;
u_int *ppte;
physaddr = getpteaddr(addr);
if (physaddr == 0) {
printf("setpgmap -- no pte at %x\n", addr);
return;
}
offset = physaddr & MMU_PAGEOFFSET;
tpte.ipte = MMU_INVALIDPTE;
tpte.pte.pte_vld = PTE_VALID;
tpte.pte.pte_pfn = mmu_btop(physaddr);
ppte = (u_int *)*romp->v_monptaddr;
ppte += mmu_btop(TMPVADDR - DEBUGSTART);
*ppte = tpte.ipte;
atc_flush();
ppte = (u_int *)(TMPVADDR + offset);
*ppte = pte;
}
u_int
Getpgmap(addr)
u_int addr;
{
u_int physaddr, offset;
union {
struct pte pte;
u_int ipte;
} tpte;
u_int *ppte;
physaddr = getpteaddr(addr);
if (physaddr == 0) {
printf("getpgmap -- no pte at %x\n", addr);
return (0);
}
offset = physaddr & MMU_PAGEOFFSET;
tpte.ipte = MMU_INVALIDPTE;
tpte.pte.pte_vld = PTE_VALID;
tpte.pte.pte_pfn = mmu_btop(physaddr);
ppte = (u_int *)*romp->v_monptaddr;
ppte += mmu_btop(TMPVADDR - DEBUGSTART);
*ppte = tpte.ipte;
atc_flush();
ppte = (u_int *)(TMPVADDR + offset);
return (*ppte);
}
RELOC_Setpgmap(addr, pte, real)
u_int addr, pte, real;
{
u_int physaddr, offset;
union {
struct pte pte;
u_int ipte;
} tpte;
u_int *ppte;
physaddr = CALL(getpteaddr)(addr);
if (physaddr == 0) {
CALL(printf)("setpgmap -- no pte at %x\n", addr);
return;
}
offset = physaddr & MMU_PAGEOFFSET;
tpte.ipte = MMU_INVALIDPTE;
tpte.pte.pte_vld = PTE_VALID;
tpte.pte.pte_pfn = mmu_btop(physaddr);
ppte = (u_int *)*romp->v_monptaddr;
ppte += mmu_btop(TMPVADDR - DEBUGSTART);
*ppte = tpte.ipte;
CALL(atc_flush)();
ppte = (u_int *)(TMPVADDR + offset);
*ppte = pte;
}
#endif sun3x