machdep.c
来自「操作系统SunOS 4.1.3版本的源码」· C语言 代码 · 共 716 行
C
716 行
#ifndef lintstatic char sccsid[] = "@(#)machdep.c 1.1 92/07/30";#endif/* * Copyright (c) 1986 by Sun Microsystems, Inc. */#include <sys/param.h>#include <sys/errno.h>#include <sys/vmmac.h>#include <sun4/buserr.h>#include <sun4/enable.h>#include <sun4/mmu.h>#include <sun4/cpu.h>#include <sun4/pte.h>#include <sun4/scb.h>#include <sun4/psl.h>#include <sun4/trap.h>#include <sun4/clock.h>#include <sun4/intreg.h>#include "reg.h"#include "../../debug/debug.h"#include "../../debug/debugger.h"#include "asm_linkage.h"extern int errno;#define DVMA 0xfff00000int istrap = 0;int scbsyncdone = 0;int cpudelay = 0; /* old macros: shift right amount to scale (n << 4) */int Cpudelay = 11; /* new macros: count down counter initial value */int cpu;int vac_linesize; /* number of bytes in a cache line */int vac_pglines; /* number of cache lines in a page */int vac_nlines; /* number of cache lines in cache */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 */int clock_type;static int clock_peek = 0;unsigned long old_clock0_pte, old_counter_pte; /* save old ptes */extern char estack[], etext[];/* * Definitions for registers in jmp_buf */#define JB_PC 0#define JB_SP 1static jmp_buf state; /* used for temporary games *//* * Startup code after relocation. */startup(){ register int i; register int pg; u_char intreg; extern Setpgmap(); extern char start[], end[], etext[];#ifndef SAS set_clock_ptes();#endif !SAS Setpgmap((caddr_t)INTREG_ADDR, PG_V|PG_KW|PGT_OBIO|btop(OBIO_INTREG_ADDR)); set_clock_type(); 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 += NBPG) { pg = Getpgmap(i); Setpgmap(i, (pg & ~PG_PROT) | PG_KR); } cpu = getmachinetype(); switch (cpu) { case SUN4_ARCH: /* proto 1 */ case CPU_SUN4_260: case CPU_SUN4_110: case CPU_SUN4_330: case CPU_SUN4_470: break; default: printf("%s: UNKNOWN MACHINE TYPE IN ID PROM\n", myname); printf("%s: DEFAULTING MACHINE TYPE TO SUN4_260\n", myname); cpu = CPU_SUN4_260; break; } if (cpu != CPU_SUN4_110) cache_on = getenablereg() & ENA_CACHE; if (cache_on || (cpu == CPU_SUN4_110)) { cpudelay = 1; } else { cpudelay = 4; vac_init(); /* invalidate entire cache */ }}asm(" .align 4 ");asm("_tcode: ");asm(" sethi %hi(_trap), %l3 ");asm(" or %l3, %lo(_trap), %l3 ");asm(" jmp %l3 ");asm(" mov %psr, %l0 ");scbsync(){ kadbscbsync(); scbsyncdone = 1;}kadbscbsync(){ register struct scb *tbr; register int otbr_pg; extern trapvec tcodee; extern trapvec tcode; extern struct scb *gettbr(); 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) { /* * 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;#ifdef notdef (void) _setjmp(state); state[JB_PC] = DVEC-8; /* new pc value */ state[JB_SP] = *(int *)state[JB_SP]; /* new sp value */ _longjmp(state, 1); /*NOTREACHED*/#endif asm(" t 126 /*TRAPBRKNO*/ -1 "); }}/* * 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 intreg, dummy; register int s;/* XXX - need SUNRAY support */#ifndef SAS /* * make sure that we are only playing w/ * clock interrupt register bits */ on &= (IR_ENA_CLK14 | IR_ENA_CLK10); off &= (IR_ENA_CLK14 | IR_ENA_CLK10); s = splhi(); /* * Get a copy of current interrupt register, * turning off any undesired bits (aka `off') */ intreg = *INTREG & ~(off | IR_ENA_INT); *INTREG &= ~IR_ENA_INT; /* * Next we turns off the CLK10 and CLK14 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. */ *INTREG &= ~(IR_ENA_CLK14 | IR_ENA_CLK10); if (clock_type == INTERSIL7170) { CLOCK0->clk_cmd = (CLK_CMD_NORMAL & ~CLK_CMD_INTRENA); dummy = CLOCK0->clk_intrreg; /* clear clock */ } else { dummy = COUNTER->limit10; dummy = COUNTER->limit14; } #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. */ *INTREG |= (intreg | on); /* enable flip-flops */ if (clock_type == INTERSIL7170) { CLOCK0->clk_cmd = CLK_CMD_NORMAL; /* enable clock intr */ } *INTREG |= IR_ENA_INT; /* enable interrupts */ (void)splx(s);#endif !SAS}/* * 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*/ }/* showregs(ondebug_stack ? "unexpected fault" : "unexpected exception", 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\n"); _longjmp(abort_jmp, 1); /*NOTREACHED*/ } if (clock_peek) { /* we were peeking for clock type */ jmp_buf_ptr sav = nofault; nofault = NULL; _longjmp(sav, 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 call cmd %x %x %x %x\n", trap,getsp(),trappc,trapnpc); cmd(); /* error not resolved, ether debugger */}long trap_window[25];showregs(str, locregs) register char *str; register struct allregs *locregs;{/* printf("g1-g7: %x, %x, %x, %x, %x, %x, %x\n", rp->r_g1, rp->r_g2, rp->r_g3, rp->r_g4, rp->r_g5, rp->r_g6, rp->r_g7);printf("trap_window: wim=%x\n", trap_window[24]);printf("o0-o7: %x, %x, %x, %x, %x, %x, %x, %x\n",trap_window[0], trap_window[1], trap_window[2], trap_window[3],trap_window[4], trap_window[5], trap_window[6], trap_window[7]);printf("l0-l7: %x, %x, %x, %x, %x, %x, %x, %x\n",trap_window[8], trap_window[9], trap_window[10], trap_window[11],trap_window[12], trap_window[13], trap_window[14], trap_window[15]);printf("i0-i7: %x, %x, %x, %x, %x, %x, %x, %x\n",trap_window[16], trap_window[17], trap_window[18], trap_window[19],trap_window[20], trap_window[21], trap_window[22], trap_window[23]);#ifndef SAS DELAY(2000000);#endif (void) splx(s); */}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 */intPeekc(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);}shortpeek(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);}longpeekl(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);}intpokec(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);}intpokel(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, i; 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; } if ((cpu != CPU_SUN4_110) && !(pg&PG_NC)){ 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 */ if ((cpu != CPU_SUN4_110) && !(pg&PG_NC)){ 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; if (curregs != 0) { printf("bad call to spawn\n"); exit(1); } if (!_setjmp(mainregs)) { /* * 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(){ if (!_setjmp(curregs)) { /* * 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; /* * 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; } if (cpu == CPU_SUN4_260) cache_on = getenablereg() & ENA_CACHE; if (cache_on || (cpu == CPU_SUN4_110)) cpudelay = 1; else cpudelay = 4; /* * Set up for monitor's input routines to work. This * requires that we call the monitor's nmi handler on level14 * clock interrupts and that interrupts and level14 clock * interrupt are enabled. */ if ((*INTREG & (IR_ENA_INT | IR_ENA_CLK14)) != (IR_ENA_INT | IR_ENA_CLK14)) { resetclk = 1; interreg = *INTREG; set_clk_mode(IR_ENA_CLK14, 0); } s = spl13(); do { doswitch(); if (dorun == 0) printf("cmd: nothing to do\n"); } while (dorun == 0); if (resetclk) { set_clk_mode(0, IR_ENA_CLK14); *INTREG = interreg; } /* we don't need to splx since we are returning to the caller */ /* and will reset his/her state */}voidvac_init(){ if (cpu == CPU_SUN4_470) { vac_linesize = VAC_LINESIZE_SUNRAY; } else { vac_linesize = VAC_LINESIZE_SUNRISE; } vac_nlines = VAC_SIZE / vac_linesize; vac_pglines = PAGESIZE / vac_linesize; vac_tagsinit();}set_clock_type() { clock_peek = 1; if (Peekc((char *)&CLOCK0->clk_hsec) != -1) { clock_type = INTERSIL7170; /* put back other old pte */ Setpgmap((caddr_t)COUNTER_ADDR, old_counter_pte); } else { clock_type = MOSTEK48T02; /* put back other old pte */ Setpgmap((caddr_t)CLOCK0_ADDR, old_clock0_pte); } clock_peek = 0;}/* * Return an available physical page number */intgetapage(){ extern int lastpg; return (--lastpg);} #ifndef SASset_clock_ptes() { caddr_t i; int segm; /* copy old ptes, put the unused page pte back to what it was */ old_clock0_pte = Getpgmap((caddr_t)CLOCK0_ADDR); old_counter_pte = Getpgmap((caddr_t)COUNTER_ADDR); i = (caddr_t) CLOCK0_ADDR; /* KLUDGE The last seg may not be mapped in by eporom. Only the sun4s with intel ethernet chip have the last smeg mapped in. For example, sun4_260 has the last smg mapped in while sun4_330 does not (because 4_330 uses LANCE ethernet chip). */ if ((segm = Getsegmap(i)) == (npmgrps-1)) { segm = --lastpm; Setsegmap((caddr_t)CLOCK0_ADDR, segm); } Setpgmap((caddr_t)CLOCK0_ADDR, /* intersil clock */ PG_V|PG_KW|PGT_OBIO|btop(OBIO_CLOCK_ADDR)); Setpgmap((caddr_t)COUNTER_ADDR, /* mostek clock */ PG_V|PG_KW|PGT_OBIO|btop(OBIO_COUNTER_ADDR)); }#endif/* * Call into the monitor (hopefully) */montrap(){ (*romp->v_exit_to_mon)();}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?