machdep.c
来自「操作系统SunOS 4.1.3版本的源码」· C语言 代码 · 共 992 行 · 第 1/2 页
C
992 行
#ifndef lintstatic 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 || sun3xextern 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 2static 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", ®s, &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))
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?