📄 machdep.c
字号:
#ident "@(#)machdep.c 1.1 7/30/92"/* * Copyright (c) 1990 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/mmu.h>#include <machine/cpu.h>#include <machine/pte.h>#include <machine/enable.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 <machine/vm_hat.h>#include "allregs.h"#include "../../debug/debug.h"#include <debug/debugger.h>extern int errno;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 print_cpu_done;/* * properties tchotchkes */#define GETPROPLEN prom_getproplen#define GETPROP prom_getprop#define NEXT prom_nextnode#define CHILD prom_childnodeextern int getprop();int debug_props = 0; /* Turn on to enable debugging message */#ifdef MULTIPROCESSOR#define CPUTOMID(x) ((x) | 0x8)#define MIDTOCPU(x) ((x) & 0x3)int cpus_enabled[NCPU];#ifdef PROM_IDLECPUS_WORKSextern int prom_idlecpu();extern int prom_resumecpu();unsigned cpus_nodeid[NCPU];#endif /* PROM_IDLECPUS_WORKS */#endif MULTIPROCESSOR/* * 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 */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();extern int cache;/* * 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();void Setpgmap();/* * get_rom_l2_ptr: * return the physical address in the current context of the pte * that would map virtual address 'vaddr' for 'size' bytes. * We are only setup to use level-2 (256KB) mappings. If a level-0 * or level-1 mapping already exists then do not need to do anything. */#define UPTPE_NULL (union ptpe *)NULLunion ptpe *get_l2_ptr(vaddr)u_int vaddr;{ union ptpe ct, rp, l1; ct.ptpe_int = mmu_getctp(); rp.ptpe_int = ldphys(ct.ptp.PageTablePointer << MMU_STD_PTPSHIFT); switch (rp.ptp.EntryType) { case MMU_ET_PTE: /* pte in context table */ return (UPTPE_NULL); case MMU_ET_PTP: /* ptp in context table */ l1.ptpe_int = ldphys((rp.ptp.PageTablePointer << MMU_STD_PTPSHIFT) | MMU_L1_INDEX(vaddr) << 2); switch (l1.ptp.EntryType) { case MMU_ET_PTE: /* pte in level-1 table */ return (UPTPE_NULL); case MMU_ET_PTP: /* ptp in level-1 table */ return ((union ptpe *)((l1.ptp.PageTablePointer << MMU_STD_PTPSHIFT) | MMU_L2_INDEX(vaddr) << 2)); } }}/* * 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, i; register int *from, *to; register int lastpmsav, lastpgsav; caddr_t vstart; int too_big = 0; /* number of level-3 tables required by the debugger */#define NDBGL3PTS (mmu_btop(DEBUGSIZE)/MMU_NPTE_THREE) /*(void) CALL(setcontext)(0); - remove? */ /* * 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.) We reserve * an extra page for our own level-3 page tables. We can't use level-2 * page tables since that would require us to be 256KB aligned which * could be more wasteful of memory than just grabbing a page here. * * It seems that in allocating the extra page for the level-3 * page tables we run into a problem with the PROM virtual address * allocation with sbrk. Do we need this extra page here??? * Right now have worked around in sbrk. * Cant call sbrk here, so if need page, need workaround. */ cnt = mmu_btopr(end - start) + 1; /* XXX */ vstart = (caddr_t)(*romp->op2_alloc)((int)start, mmu_ptob(cnt)); if ((u_int)vstart != (u_int)start) too_big = 1; /* * 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. * Dont need this information on OBP. */ lastpg = 0; pagesused = 0; mon_tbr = gettbr(); if (too_big) { printf("kadb: size %x exceeded available memory\n", mmu_ptob(cnt)); }}/* * Startup code after relocation. */startup(){ register int i; register int pg; /* * Set our implementation parameters from prom properties. */ fiximp(); /* * 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 */#ifdef later for (i = (int)start; i < (int)etext; i += MMU_PAGESIZE) { pg = getpgmap(i); Setpgmap(i, (pg & ~PG_PROT) | PG_KR); }#endif mmu_flushall();}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 */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; pg = getpgmap((int)addr); if (PTE_ETYPE(pg) != MMU_ET_PTE) { if (debugging > 2) printf("poketext: invalid page map %X at %X\n", pg, addr); goto err; } if ((pg & PTE_CE_MASK) && !((cache == CACHE_PAC) || (cache == CACHE_PAC_E))) { vac_pageflush(addr); if (btop(addr + sizeof (int) - 1) != btop(addr)) vac_pageflush(addr + sizeof (int) - 1); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -