📄 machdep.c
字号:
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 ((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); } /* XXX - why not referenced also? */ Setpgmap(addr, pg | PTE_MOD(1)); mmu_flushall(); 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 addr; 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; } 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 */}/* * 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() * NOTE: we use the fact that the per- * processor clocks are available and * mapped properly at "utimers". */staticsetcpudelay(){ /* If need this call grab the latest from kernels machdep.c */} /* * Set the pte (level-3) for address v using the software pte given. * Setpgmap() automatically turns off the `cacheable' bit * for all mappings between DEBUGSTART and DEBUGEND. */voidSetpgmap(v, pte) caddr_t v; u_int pte;{ 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->op2_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) { /* * Cant test against BT_ or SP_ because using the 32-bit space * as bustype. So since no define for OBMEM space, hardcoding * in the value of 0x0. */ if (rp[i].reg_bustype != 0x0) 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);}/* * setpgmap: * set the pte that maps virtual address `v' to `pte'. * for success `v' must be mapped by a level-3 pte * XXX - fix this so that we can look at monitors pages. */setpgmap(v, pte)caddr_t v;u_int pte;{ union ptpe *l2ptr; union ptpe l2ptpe; union ptes *l3ptr; union ptes l3ptes; l2ptr = get_l2_ptr(v); l2ptpe.ptpe_int = ldphys(l2ptr); l3ptr = ((union ptes *)(l2ptpe.ptp.PageTablePointer << MMU_STD_PTPSHIFT)) + MMU_L3_INDEX((u_int)v); l3ptes.pte_int = ldphys((u_int *)l3ptr); stphys((u_int *)l3ptr, pte); /* Flush the TLB after fiddling with PTE */ srmmu_mmu_flushpage(v); return (0);}/* * getpgmap: * return the pte that maps virtual address `v'. * for success `v' must be mapped by a level-3 pte */getpgmap(v)caddr_t v;{ union ptpe *l2ptr; union ptpe l2ptpe; union ptes *l3ptr; union ptes l3ptes; l2ptr = get_l2_ptr(v); l2ptpe.ptpe_int = ldphys(l2ptr); l3ptr = ((union ptes *)(l2ptpe.ptp.PageTablePointer << MMU_STD_PTPSHIFT)) + MMU_L3_INDEX((u_int)v); l3ptes.pte_int = ldphys((u_int *)l3ptr); return (l3ptes.pte_int);}#ifdef MULTIPROCESSOR/* * XXX-These functions should eventually implement the cross-call * mechanism, or someother such method. */idle_cpus(mid)dnode_t mid;{int cur_cpuid, i; cur_cpuid = MIDTOCPU(mid); /* * Only print which cpu we are on, if we have more * than one cpu. Else, its unnecessary. */ for (i=1; i < NCPU; i++) { if (cpus_enabled[i]) { if (!print_cpu_done) printf("currently on cpu%d\n", cur_cpuid); break; } }#ifdef PROM_IDLECPU_WORKS for (i=0; i < NCPU; i++) { if (cpus_enabled[i] && (i != cur_cpuid)) { /* * prom_idlecpu returns 0 on success, -1 on failure */ if (prom_idlecpu(cpus_nodeid[i])) printf("-->failed to idle cpu%d\n", i); } } /* Now back to the regularly scheduled program */#endif /* PROM_IDLECPU_WORKS */ cmd();}#ifdef PROM_IDLECPUS_WORKS/* * On way out of kadb have to get other cpu's back up. */resume_cpus(mid)dnode_t mid;{int cur_cpuid, i; cur_cpuid = MIDTOCPU(mid); for (i=0; i < NCPU; i++) { if (cpus_enabled[i] && (i != cur_cpuid)) { /* * prom_resumecpu returns 0 on success, -1 on failure */ if (prom_resumecpu(cpus_nodeid[i])) printf("-->failed to resume cpu%d\n", i); } }}#endif /* PROM_IDLECPUS_WORKS */#endif MULTIPROCESSOR
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -