int askregvar(Symbol p, Symbol regs) { Symbol r; assert(p); if (p->sclass != REGISTER) return 0; else if (!isscalar(p->type)) { p->sclass = AUTO; return 0; } else if (p->temporary) { p->x.name = "?"; return 1; } else if ((r = askreg(regs, vmask)) != NULL) { p->x.regnode = r->x.regnode; p->x.regnode->vbl = p; p->x.name = r->x.name; debug(dumpregs("(allocating %s to symbol %s)\n", p->x.name, p->name)); return 1; } else { p->sclass = AUTO; return 0; } }
/* ------------------------------------------------------------------------*//** * @FUNCTION core44xx_main * @BRIEF PRCM CORE menu * @RETURNS 0 in case of success * OMAPCONF_ERR_ARG * OMAPCONF_ERR_CPU * OMAPCONF_ERR_INTERNAL * @param[in] argc: shell input argument number * @param[in] argv: shell input argument(s) * @DESCRIPTION PRCM CORE menu *//*------------------------------------------------------------------------ */ int core44xx_main(int argc, char *argv[]) { int ret; CHECK_CPU(44xx, OMAPCONF_ERR_CPU); if (argc == 2) { if (!init_done) core44xx_regtable_init(); if (strcmp(argv[1], "dump") == 0) { ret = dumpregs(prcm_core_reg_table); } else if (strcmp(argv[1], "cfg") == 0) { ret = core44xx_config_show(stdout); } else if (strcmp(argv[1], "dep") == 0) { ret = core44xx_dependency_show(stdout); } else { help(HELP_PRCM); ret = OMAPCONF_ERR_ARG; } } else { help(HELP_PRCM); ret = OMAPCONF_ERR_ARG; } return ret; }
// lastcontinuehandler is reached, because runtime cannot handle // current exception. lastcontinuehandler will print crash info and exit. uint32 runtime·lastcontinuehandler(ExceptionRecord *info, Context *r, G *gp) { bool crash; if(runtime·panicking) // traceback already printed runtime·exit(2); runtime·panicking = 1; runtime·printf("Exception %x %p %p %p\n", info->ExceptionCode, (uintptr)info->ExceptionInformation[0], (uintptr)info->ExceptionInformation[1], (uintptr)r->Eip); runtime·printf("PC=%x\n", r->Eip); if(g->m->lockedg != nil && g->m->ncgo > 0 && gp == g->m->g0) { runtime·printf("signal arrived during cgo execution\n"); gp = g->m->lockedg; } runtime·printf("\n"); if(runtime·gotraceback(&crash)){ runtime·traceback(r->Eip, r->Esp, 0, gp); runtime·tracebackothers(gp); runtime·dumpregs(r); } if(crash) runtime·crash(); runtime·exit(2); return 0; // not reached }
static void profintr(Ureg *ur, void*) { OstmrReg *ost = OSTMRREG; int t; if((ost->osmr[3] - ost->oscr) < 2*CLOCKFREQ) { /* less than 2 seconds before reset, say something */ setpanic(); clockpoll(); dumpregs(ur); panic("Watchdog timer will expire"); } /* advance the profile clock tick */ ost->osmr[2] += timer_incr[2]; ost->ossr = (1 << 2); /* Clear the SR */ t = 1; while((ost->osmr[2] - ost->oscr) > 0x80000000) { ost->osmr[2] += timer_incr[2]; t++; } if(prof_fcn) prof_fcn(ur, t); }
uint32 runtime·sighandler(ExceptionRecord *info, Context *r, G *gp) { uintptr *sp; switch(info->ExceptionCode) { case EXCEPTION_BREAKPOINT: r->Eip--; // because 8l generates 2 bytes for INT3 return 1; } if(gp != nil && runtime·issigpanic(info->ExceptionCode)) { // Make it look like a call to the signal func. // Have to pass arguments out of band since // augmenting the stack frame would break // the unwinding code. gp->sig = info->ExceptionCode; gp->sigcode0 = info->ExceptionInformation[0]; gp->sigcode1 = info->ExceptionInformation[1]; gp->sigpc = r->Eip; // Only push runtime·sigpanic if r->eip != 0. // If r->eip == 0, probably panicked because of a // call to a nil func. Not pushing that onto sp will // make the trace look like a call to runtime·sigpanic instead. // (Otherwise the trace will end at runtime·sigpanic and we // won't get to see who faulted.) if(r->Eip != 0) { sp = (uintptr*)r->Esp; *--sp = r->Eip; r->Esp = (uintptr)sp; } r->Eip = (uintptr)runtime·sigpanic; return 0; } if(runtime·panicking) // traceback already printed runtime·exit(2); runtime·panicking = 1; runtime·printf("Exception %x %p %p\n", info->ExceptionCode, info->ExceptionInformation[0], info->ExceptionInformation[1]); runtime·printf("PC=%x\n", r->Eip); if(m->lockedg != nil && m->ncgo > 0 && gp == m->g0) { runtime·printf("signal arrived during cgo execution\n"); gp = m->lockedg; } runtime·printf("\n"); if(runtime·gotraceback()){ runtime·traceback((void*)r->Eip, (void*)r->Esp, 0, gp); runtime·tracebackothers(gp); runtime·dumpregs(r); } runtime·exit(2); return 0; }
/* ------------------------------------------------------------------------*//** * @FUNCTION core44xx_dump * @BRIEF dump PRCM CORE registers * @RETURNS 0 in case of success * OMAPCONF_ERR_REG_ACCESS * OMAPCONF_ERR_CPU * @DESCRIPTION dump PRCM CORE registers *//*------------------------------------------------------------------------ */ int core44xx_dump(void) { CHECK_CPU(44xx, OMAPCONF_ERR_CPU); if (!init_done) core44xx_regtable_init(); return dumpregs(prcm_core_reg_table); }
/* ------------------------------------------------------------------------*//** * @FUNCTION wkup44xx_dump * @BRIEF dump PRCM WKUP registers * @RETURNS 0 in case of success * OMAPCONF_ERR_REG_ACCESS * OMAPCONF_ERR_CPU * @DESCRIPTION dump PRCM WKUP registers *//*------------------------------------------------------------------------ */ int wkup44xx_dump(void) { CHECK_CPU(44xx, OMAPCONF_ERR_ARG); if (!init_done) wkup44xx_regtable_init(); return dumpregs(prcm_wkup_reg_table); }
static int mxc_hdmi_codec_prepare(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { struct snd_pcm_runtime *runtime = substream->runtime; hdmi_set_layout(runtime->channels); hdmi_set_sample_rate(runtime->rate); dumpregs(); return 0; }
static void faultarm(Ureg *ureg) { char buf[ERRMAX]; sprint(buf, "sys: trap: fault pc=%8.8lux", (ulong)ureg->pc); if(0){ iprint("%s\n", buf); dumpregs(ureg); } disfault(ureg, buf); }
static void ralloc(Node p) { int i; unsigned mask[2]; mask[0] = tmask[0]; mask[1] = tmask[1]; assert(p); debug(fprint(stderr, "(rallocing %x)\n", p)); for (i = 0; i < NELEMS(p->x.kids) && p->x.kids[i]; i++) { Node kid = p->x.kids[i]; Symbol r = kid->syms[RX]; assert(r && kid->x.registered); if (r->sclass != REGISTER && r->x.lastuse == kid) putreg(r); } if (!p->x.registered && NeedsReg[opindex(p->op)] && (*IR->x.rmap)(opkind(p->op))) { Symbol sym = p->syms[RX], set = sym; assert(sym); if (sym->temporary) set = (*IR->x.rmap)(opkind(p->op)); assert(set); if (set->sclass != REGISTER) { Symbol r; if (*IR->x._templates[getrule(p, p->x.inst)] == '?') for (i = 1; i < NELEMS(p->x.kids) && p->x.kids[i]; i++) { Symbol r = p->x.kids[i]->syms[RX]; assert(p->x.kids[i]->x.registered); assert(r && r->x.regnode); assert(sym->x.wildcard || sym != r); mask[r->x.regnode->set] &= ~r->x.regnode->mask; } r = getreg(set, mask, p); if (sym->temporary) { Node q; r->x.lastuse = sym->x.lastuse; for (q = sym->x.lastuse; q; q = q->x.prevuse) { q->syms[RX] = r; q->x.registered = 1; if (sym->u.t.cse && q->x.copy) q->x.equatable = 1; } } else { p->syms[RX] = r; r->x.lastuse = p; } debug(dumpregs("(allocating %s to node %x)\n", r->x.name, (char *) p)); } } p->x.registered = 1; (*IR->x.clobber)(p); }
void fatal(const char *format, ...) { va_list ap; va_start(ap, format); vprintf(format, ap); va_end(ap); closeide(); fflush(stdout); dumppic(); dumpregs(); fflush(stdout); exit(-1); }
int main(int argc, char **argv) { if (argc < 2) { fprintf(stderr, "Need spi device\n"); return 1; } int fd = open(argv[1], O_RDWR); if (fd < 0) { perror("open"); return 1; } dumpstat(argv[1], fd); dumpregs(fd); close(fd); }
/* ------------------------------------------------------------------------*//** * @FUNCTION stm_dump_regs * @BRIEF dump STM registers * @RETURNS 0 in case of success * OMAPCONF_ERR_NOT_AVAILABLE * @DESCRIPTION dump STM registers *//*------------------------------------------------------------------------ */ int stm_dump_regs(void) { if (!emu44xx_is_enabled()) { printf("stm_dump_regs(): " "trying to enable ETB but EMU domain OFF!!!\n"); return OMAPCONF_ERR_NOT_AVAILABLE; } if (!stm_is_claimed()) { printf("stm_dump_regs(): STM not claimed!\n"); return OMAPCONF_ERR_INTERNAL; } return dumpregs((reg_table *) omap4_stm_reg_table); }
void closepc() { atapi->exit(); // ioctl_close(); dumppic(); // output=7; // setpitclock(clocks[0][0][0]); // while (1) runpc(); savedisc(0); savedisc(1); dumpregs(); closevideo(); device_close_all(); midi_close(); }
static void faultarm(Ureg *ureg, ulong fsr, uintptr addr) { int user, insyscall, read; static char buf[ERRMAX]; char *err; read = (fsr & (1<<11)) == 0; user = userureg(ureg); if(!user){ if(addr >= USTKTOP || up == nil) _dumpstack(ureg); if(addr >= USTKTOP) panic("kernel fault: bad address pc=%#.8lux addr=%#.8lux fsr=%#.8lux", ureg->pc, addr, fsr); if(up == nil) panic("kernel fault: no user process pc=%#.8lux addr=%#.8lux fsr=%#.8lux", ureg->pc, addr, fsr); } if(up == nil) panic("user fault: up=nil pc=%#.8lux addr=%#.8lux fsr=%#.8lux", ureg->pc, addr, fsr); insyscall = up->insyscall; up->insyscall = 1; switch(fsr & 0x1F){ case 0x05: /* translation fault L1 */ case 0x07: /* translation fault L2 */ case 0x03: /* access flag fault L1 */ case 0x06: /* access flag fault L2 */ case 0x09: /* domain fault L1 */ case 0x0B: /* domain fault L2 */ case 0x0D: /* permission fault L1 */ case 0x0F: /* permission fault L2 */ if(fault(addr, read) == 0) break; /* wet floor */ default: err = faulterr[fsr & 0x1F]; if(err == nil) err = "fault"; if(!user){ dumpregs(ureg); _dumpstack(ureg); panic("kernel %s: pc=%#.8lux addr=%#.8lux fsr=%#.8lux", err, ureg->pc, addr, fsr); } sprint(buf, "sys: trap: %s %s addr=%#.8lux", err, read ? "read" : "write", addr); postnote(up, 1, buf, NDebug); } up->insyscall = insyscall; }
/* ------------------------------------------------------------------------*//** * @FUNCTION sr44xx_dump * @BRIEF dump SR PRCM registers * @RETURNS 0 in case of success * OMAPCONF_ERR_CPU * OMAPCONF_ERR_REG_ACCESS * @DESCRIPTION dump SR PRCM registers *//*------------------------------------------------------------------------ */ int sr44xx_dump(void) { unsigned int ret; if (!cpu_is_omap44xx()) return OMAPCONF_ERR_CPU; if (!init_done) sr44xx_regtable_init(); if (mod44xx_is_accessible(OMAP4_SMARTREFLEX_MPU) != 1) { printf("SR_MPU not accessible.\n"); } else { ret = dumpregs(prcm_sr_mpu_reg_table); if (ret != 0) return ret; ret = dumpregs(prcm_sr_vp_mpu_reg_table); if (ret != 0) return ret; } if (mod44xx_is_accessible(OMAP4_SMARTREFLEX_IVA) != 1) { printf("SR_IVA not accessible.\n"); } else { ret = dumpregs(prcm_sr_iva_reg_table); if (ret != 0) return ret; ret = dumpregs(prcm_sr_vp_iva_reg_table); if (ret != 0) return ret; } if (mod44xx_is_accessible(OMAP4_SMARTREFLEX_CORE) != 1) { printf("SR_CORE not accessible.\n"); } else { ret = dumpregs(prcm_sr_core_reg_table); if (ret != 0) return ret; ret = dumpregs(prcm_sr_vp_core_reg_table); if (ret != 0) return ret; } return dumpregs(prcm_sr_vc_reg_table); }
/* ------------------------------------------------------------------------*//** * @FUNCTION stm_atb_capture_enable * @BRIEF enable STM trace to be captured in ETB via ATB * @RETURNS 0 in case of success * OMAPCONF_ERR_NOT_AVAILABLE * @DESCRIPTION enable STM trace to be captured in ETB via ATB * NB: make sure EMU domain is ON before calling this * function. *//*------------------------------------------------------------------------ */ int stm_atb_capture_enable(void) { if (!emu44xx_is_enabled()) { printf("stm_atb_capture_enable(): " "trying to enable ETB but EMU domain OFF!!!\n"); return OMAPCONF_ERR_NOT_AVAILABLE; } if (!stm_is_claimed()) { printf("stm_atb_capture_enable(): STM not claimed!\n"); return OMAPCONF_ERR_INTERNAL; } mem_write(OMAP4430_ATB_CONFIG, 0x00010000); #ifdef STM_OMAP4_DEBUG printf("stm_atb_capture_enable(): ATB capture enabled.\n"); dumpregs((reg_table *) omap4_stm_reg_table); #endif return 0; }
void sighandler(int32 sig, Siginfo *info, void *context) { Ucontext *uc; Mcontext *mc; Regs *r; if(sigtab[sig].flags & SigQueue) { if(sigsend(sig) || (sigtab[sig].flags & SigIgnore)) return; exit(2); // SIGINT, SIGTERM, etc } if(panicking) // traceback already printed exit(2); panicking = 1; if(sig < 0 || sig >= NSIG){ printf("Signal %d\n", sig); }else{ printf("%s\n", sigtab[sig].name); } uc = context; mc = uc->uc_mcontext; r = &mc->ss; printf("Faulting address: %p\n", info->si_addr); printf("pc: %X\n", r->rip); printf("\n"); if(gotraceback()){ traceback((void*)r->rip, (void*)r->rsp, (void*)r->r15); tracebackothers((void*)r->r15); dumpregs(r); } breakpoint(); exit(2); }
static void dumpregs_v8p(const prgregset_t reg, const prxregset_t *xreg, int is64) { static const uint32_t zero[8] = { 0 }; int gr, xr, cols = 2; uint64_t xval; if (memcmp(xreg->pr_un.pr_v8p.pr_xg, zero, sizeof (zero)) == 0 && memcmp(xreg->pr_un.pr_v8p.pr_xo, zero, sizeof (zero)) == 0) { dumpregs(reg, is64); return; } for (gr = R_G0, xr = XR_G0; gr <= R_G7; gr++, xr++) { xval = (uint64_t)xreg->pr_un.pr_v8p.pr_xg[xr] << 32 | (uint64_t)(uint32_t)reg[gr]; (void) printf(" %s = 0x%.16" PRIX64, regname[gr], xval); if ((gr + 1) % cols == 0) (void) putchar('\n'); } for (gr = R_O0, xr = XR_O0; gr <= R_O7; gr++, xr++) { xval = (uint64_t)xreg->pr_un.pr_v8p.pr_xo[xr] << 32 | (uint64_t)(uint32_t)reg[gr]; (void) printf(" %s = 0x%.16" PRIX64, regname[gr], xval); if ((gr + 1) % cols == 0) (void) putchar('\n'); } for (gr = R_L0; gr < NPRGREG; gr++) { (void) printf(" %s = 0x%.8lX", regname[gr], (long)reg[gr]); if ((gr + 1) % cols == 0) (void) putchar('\n'); } if (gr % cols != 0) (void) putchar('\n'); }
static void fault386(Ureg* ureg, void*) { ulong addr; int read, user, n, insyscall; char buf[ERRMAX]; addr = getcr2(); read = !(ureg->ecode & 2); user = (ureg->cs & 0xFFFF) == UESEL; if(!user){ if(vmapsync(addr)) return; if(addr >= USTKTOP) panic("kernel fault: bad address pc=0x%.8lux addr=0x%.8lux", ureg->pc, addr); if(up == nil) panic("kernel fault: no user process pc=0x%.8lux addr=0x%.8lux", ureg->pc, addr); } if(up == nil) panic("user fault: up=0 pc=0x%.8lux addr=0x%.8lux", ureg->pc, addr); insyscall = up->insyscall; up->insyscall = 1; n = fault(addr, read); if(n < 0){ if(!user){ dumpregs(ureg); panic("fault: 0x%lux", addr); } checkpages(); checkfault(addr, ureg->pc); sprint(buf, "sys: trap: fault %s addr=0x%lux", read ? "read" : "write", addr); postnote(up, 1, buf, NDebug); } up->insyscall = insyscall; }
void sighandler(int32 sig, Siginfo* info, void* context) { Ucontext *uc; Mcontext *mc; if(sigtab[sig].flags & SigQueue) { if(sigsend(sig) || (sigtab[sig].flags & SigIgnore)) return; exit(2); // SIGINT, SIGTERM, etc } if(panicking) // traceback already printed exit(2); panicking = 1; uc = context; mc = &uc->uc_mcontext; if(sig < 0 || sig >= NSIG) printf("Signal %d\n", sig); else printf("%s\n", sigtab[sig].name); printf("Faulting address: %p\n", info->si_addr); printf("PC=%X\n", mc->mc_eip); printf("\n"); if(gotraceback()){ traceback((void*)mc->mc_eip, (void*)mc->mc_esp, m->curg); tracebackothers(m->curg); dumpregs(mc); } breakpoint(); exit(2); }
void runtime·sighandler(int32 sig, Siginfo *info, void *context, G *gp) { Ucontext *uc; Sigcontext *r; SigTab *t; uc = context; r = &uc->uc_mcontext; if(sig == SIGPROF) { runtime·sigprof((uint8*)r->arm_pc, (uint8*)r->arm_sp, (uint8*)r->arm_lr, gp); return; } t = &runtime·sigtab[sig]; if(info->si_code != SI_USER && (t->flags & SigPanic)) { if(gp == nil) goto Throw; // Make it look like a call to the signal func. // Have to pass arguments out of band since // augmenting the stack frame would break // the unwinding code. gp->sig = sig; gp->sigcode0 = info->si_code; gp->sigcode1 = r->fault_address; gp->sigpc = r->arm_pc; // If this is a leaf function, we do smash LR, // but we're not going back there anyway. // Don't bother smashing if r->arm_pc is 0, // which is probably a call to a nil func: the // old link register is more useful in the stack trace. if(r->arm_pc != 0) r->arm_lr = r->arm_pc; // In case we are panicking from external C code r->arm_r10 = (uintptr)gp; r->arm_r9 = (uintptr)m; r->arm_pc = (uintptr)runtime·sigpanic; return; } if(info->si_code == SI_USER || (t->flags & SigNotify)) if(runtime·sigsend(sig)) return; if(t->flags & SigKill) runtime·exit(2); if(!(t->flags & SigThrow)) return; Throw: if(runtime·panicking) // traceback already printed runtime·exit(2); runtime·panicking = 1; if(sig < 0 || sig >= NSIG) runtime·printf("Signal %d\n", sig); else runtime·printf("%s\n", runtime·sigtab[sig].name); runtime·printf("PC=%x\n", r->arm_pc); runtime·printf("\n"); if(runtime·gotraceback()){ runtime·traceback((void*)r->arm_pc, (void*)r->arm_sp, (void*)r->arm_lr, gp); runtime·tracebackothers(gp); runtime·printf("\n"); runtime·dumpregs(r); } // breakpoint(); runtime·exit(2); }
void runtime·sighandler(int32 sig, Siginfo *info, void *context, G *gp) { Ucontext *uc; Sigcontext *r; SigTab *t; uc = context; r = &uc->uc_mcontext; if(sig == SIGPROF) { runtime·sigprof((uint8*)r->arm_pc, (uint8*)r->arm_sp, (uint8*)r->arm_lr, gp); return; } t = &runtime·sigtab[sig]; if(info->si_code != SI_USER && (t->flags & SigPanic)) { if(gp == nil || gp == m->g0) goto Throw; // Make it look like a call to the signal func. // Have to pass arguments out of band since // augmenting the stack frame would break // the unwinding code. gp->sig = sig; gp->sigcode0 = info->si_code; gp->sigcode1 = r->fault_address; gp->sigpc = r->arm_pc; // We arrange lr, and pc to pretend the panicking // function calls sigpanic directly. // Always save LR to stack so that panics in leaf // functions are correctly handled. This smashes // the stack frame but we're not going back there // anyway. r->arm_sp -= 4; *(uint32 *)r->arm_sp = r->arm_lr; // Don't bother saving PC if it's zero, which is // probably a call to a nil func: the old link register // is more useful in the stack trace. if(r->arm_pc != 0) r->arm_lr = r->arm_pc; // In case we are panicking from external C code r->arm_r10 = (uintptr)gp; r->arm_r9 = (uintptr)m; r->arm_pc = (uintptr)runtime·sigpanic; return; } if(info->si_code == SI_USER || (t->flags & SigNotify)) if(runtime·sigsend(sig)) return; if(t->flags & SigKill) runtime·exit(2); if(!(t->flags & SigThrow)) return; Throw: if(runtime·panicking) // traceback already printed runtime·exit(2); runtime·panicking = 1; if(sig < 0 || sig >= NSIG) runtime·printf("Signal %d\n", sig); else runtime·printf("%s\n", runtime·sigtab[sig].name); runtime·printf("PC=%x\n", r->arm_pc); if(m->lockedg != nil && m->ncgo > 0 && gp == m->g0) { runtime·printf("signal arrived during cgo execution\n"); gp = m->lockedg; } runtime·printf("\n"); if(runtime·gotraceback()) { runtime·traceback((void*)r->arm_pc, (void*)r->arm_sp, (void*)r->arm_lr, gp); runtime·tracebackothers(gp); runtime·printf("\n"); runtime·dumpregs(r); } // breakpoint(); runtime·exit(2); }
/* * Entered in AP core context, upon traps (system calls go through acsyscall) * using up->dbgreg means cores MUST be homogeneous. * * BUG: We should setup some trapenable() mechanism for the AC, * so that code like fpu.c could arrange for handlers specific for * the AC, instead of doint that by hand here. * * All interrupts are masked while in the "kernel" */ void actrap(Ureg *u) { panic("actrap"); #if 0 char *n; ACVctl *v; n = nil; _pmcupdate(m); if(m->proc != nil){ m->proc->nactrap++; m->proc->actime1 = fastticks(nil); } if(u->type < nelem(acvctl)){ v = acvctl[u->type]; if(v != nil){ DBG("actrap: cpu%d: %ulld\n", machp()->machno, u->type); n = v->f(u, v->a); if(n != nil) goto Post; return; } } switch(u->type){ case IdtDF: print("AC: double fault\n"); dumpregs(u); ndnr(); case IdtIPI: m->intr++; DBG("actrap: cpu%d: IPI\n", machp()->machno); apiceoi(IdtIPI); break; case IdtTIMER: apiceoi(IdtTIMER); panic("timer interrupt in an AC"); break; case IdtPF: /* this case is here for debug only */ m->pfault++; DBG("actrap: cpu%d: PF cr2 %#ullx\n", machp()->machno, cr2get()); break; default: print("actrap: cpu%d: %ulld\n", machp()->machno, u->type); } Post: m->icc->rc = ICCTRAP; m->cr2 = cr2get(); memmove(m->proc->dbgreg, u, sizeof *u); m->icc->note = n; fpuprocsave(m->proc); _pmcupdate(m); mfence(); m->icc->fn = nil; ready(m->proc); mwait(&m->icc->fn); if(m->icc->flushtlb) acmmuswitch(); if(m->icc->fn != actrapret) acsched(); DBG("actrap: ret\n"); memmove(u, m->proc->dbgreg, sizeof *u); if(m->proc) m->proc->actime += fastticks2us(fastticks(nil) - m->proc->actime1); #endif }
void runtime·sighandler(int32 sig, Siginfo *info, void *context, G *gp) { Ucontext *uc; Mcontext *mc; Sigcontext *r; uintptr *sp; uc = context; mc = &uc->uc_mcontext; r = (Sigcontext*)mc; // same layout, more conveient names if(sig == SIGPROF) { runtime·sigprof((uint8*)r->rip, (uint8*)r->rsp, nil, gp); return; } if(gp != nil && (runtime·sigtab[sig].flags & SigPanic)) { // Make it look like a call to the signal func. // Have to pass arguments out of band since // augmenting the stack frame would break // the unwinding code. gp->sig = sig; gp->sigcode0 = info->si_code; gp->sigcode1 = ((uintptr*)info)[2]; gp->sigpc = r->rip; // Only push runtime·sigpanic if r->rip != 0. // If r->rip == 0, probably panicked because of a // call to a nil func. Not pushing that onto sp will // make the trace look like a call to runtime·sigpanic instead. // (Otherwise the trace will end at runtime·sigpanic and we // won't get to see who faulted.) if(r->rip != 0) { sp = (uintptr*)r->rsp; *--sp = r->rip; r->rsp = (uintptr)sp; } r->rip = (uintptr)runtime·sigpanic; return; } if(runtime·sigtab[sig].flags & SigQueue) { if(runtime·sigsend(sig) || (runtime·sigtab[sig].flags & SigIgnore)) return; runtime·exit(2); // SIGINT, SIGTERM, etc } if(runtime·panicking) // traceback already printed runtime·exit(2); runtime·panicking = 1; if(sig < 0 || sig >= NSIG) runtime·printf("Signal %d\n", sig); else runtime·printf("%s\n", runtime·sigtab[sig].name); runtime·printf("PC=%X\n", r->rip); runtime·printf("\n"); if(runtime·gotraceback()){ runtime·traceback((void*)r->rip, (void*)r->rsp, 0, gp); runtime·tracebackothers(gp); runtime·dumpregs(r); } runtime·exit(2); }
void runtime·sighandler(int32 sig, Siginfo *info, void *ctxt, G *gp) { uintptr *sp; SigTab *t; bool crash; if(sig == SIGPROF) { if(gp != m->g0 && gp != m->gsignal) runtime·sigprof((byte*)SIG_RIP(info, ctxt), (byte*)SIG_RSP(info, ctxt), nil, gp); return; } t = &runtime·sigtab[sig]; if(SIG_CODE0(info, ctxt) != SI_USER && (t->flags & SigPanic)) { if(gp == nil || gp == m->g0) goto Throw; // Make it look like a call to the signal func. // Have to pass arguments out of band since // augmenting the stack frame would break // the unwinding code. gp->sig = sig; gp->sigcode0 = SIG_CODE0(info, ctxt); gp->sigcode1 = SIG_CODE1(info, ctxt); gp->sigpc = SIG_RIP(info, ctxt); #ifdef GOOS_darwin // Work around Leopard bug that doesn't set FPE_INTDIV. // Look at instruction to see if it is a divide. // Not necessary in Snow Leopard (si_code will be != 0). if(sig == SIGFPE && gp->sigcode0 == 0) { byte *pc; pc = (byte*)gp->sigpc; if((pc[0]&0xF0) == 0x40) // 64-bit REX prefix pc++; else if(pc[0] == 0x66) // 16-bit instruction prefix pc++; if(pc[0] == 0xF6 || pc[0] == 0xF7) gp->sigcode0 = FPE_INTDIV; } #endif // Only push runtime·sigpanic if rip != 0. // If rip == 0, probably panicked because of a // call to a nil func. Not pushing that onto sp will // make the trace look like a call to runtime·sigpanic instead. // (Otherwise the trace will end at runtime·sigpanic and we // won't get to see who faulted.) if(SIG_RIP(info, ctxt) != 0) { sp = (uintptr*)SIG_RSP(info, ctxt); *--sp = SIG_RIP(info, ctxt); SIG_RSP(info, ctxt) = (uintptr)sp; } SIG_RIP(info, ctxt) = (uintptr)runtime·sigpanic; return; } if(SIG_CODE0(info, ctxt) == SI_USER || (t->flags & SigNotify)) if(runtime·sigsend(sig)) return; if(t->flags & SigKill) runtime·exit(2); if(!(t->flags & SigThrow)) return; Throw: m->throwing = 1; m->caughtsig = gp; runtime·startpanic(); if(sig < 0 || sig >= NSIG) runtime·printf("Signal %d\n", sig); else runtime·printf("%s\n", runtime·sigtab[sig].name); runtime·printf("PC=%X\n", SIG_RIP(info, ctxt)); if(m->lockedg != nil && m->ncgo > 0 && gp == m->g0) { runtime·printf("signal arrived during cgo execution\n"); gp = m->lockedg; } runtime·printf("\n"); if(runtime·gotraceback(&crash)){ runtime·traceback(SIG_RIP(info, ctxt), SIG_RSP(info, ctxt), 0, gp); runtime·tracebackothers(gp); runtime·printf("\n"); runtime·dumpregs(info, ctxt); } if(crash) runtime·crash(); runtime·exit(2); }
void sighandler(int32 sig, Siginfo *info, void *context) { Ucontext *uc; Mcontext *mc; Regs *r; G *gp; uintptr *sp; byte *pc; uc = context; mc = uc->uc_mcontext; r = &mc->ss; if((gp = m->curg) != nil && (sigtab[sig].flags & SigPanic)) { // Work around Leopard bug that doesn't set FPE_INTDIV. // Look at instruction to see if it is a divide. // Not necessary in Snow Leopard (si_code will be != 0). if(sig == SIGFPE && info->si_code == 0) { pc = (byte*)r->rip; if((pc[0]&0xF0) == 0x40) // 64-bit REX prefix pc++; if(pc[0] == 0xF7) info->si_code = FPE_INTDIV; } // Make it look like a call to the signal func. // Have to pass arguments out of band since // augmenting the stack frame would break // the unwinding code. gp->sig = sig; gp->sigcode0 = info->si_code; gp->sigcode1 = (uintptr)info->si_addr; // Only push sigpanic if r->rip != 0. // If r->rip == 0, probably panicked because of a // call to a nil func. Not pushing that onto sp will // make the trace look like a call to sigpanic instead. // (Otherwise the trace will end at sigpanic and we // won't get to see who faulted.) if(r->rip != 0) { sp = (uintptr*)r->rsp; *--sp = r->rip; r->rsp = (uintptr)sp; } r->rip = (uintptr)sigpanic; return; } if(sigtab[sig].flags & SigQueue) { if(sigsend(sig) || (sigtab[sig].flags & SigIgnore)) return; exit(2); // SIGINT, SIGTERM, etc } if(panicking) // traceback already printed exit(2); panicking = 1; if(sig < 0 || sig >= NSIG){ printf("Signal %d\n", sig); }else{ printf("%s\n", sigtab[sig].name); } printf("pc: %X\n", r->rip); printf("\n"); if(gotraceback()){ traceback((void*)r->rip, (void*)r->rsp, 0, (void*)r->r15); tracebackothers((void*)r->r15); dumpregs(r); } breakpoint(); exit(2); }
void callback8271() { int diff=i8271.params[0]-i8271.curtrack[curdrive]; fdctime=0; // printf("Callback 8271 - command %02X\n",i8271.command); switch (i8271.command) { case 0x0B: /*Write*/ if (!i8271.phase) { i8271.curtrack[curdrive]=i8271.params[0]; disc_writesector(curdrive,i8271.cursector,i8271.params[0],(i8271.drvout&0x20)?1:0,0); i8271.phase=1; i8271.status=0x8C; i8271.result=0; NMI8271(); return; } i8271.sectorsleft--; if (!i8271.sectorsleft) { i8271.status=0x18; i8271.result=0; NMI8271(); setspindown8271(); verify8271=0; return; } i8271.cursector++; disc_writesector(curdrive,i8271.cursector,i8271.params[0],(i8271.drvout&0x20)?1:0,0); byte=0; i8271.status=0x8C; i8271.result=0; NMI8271(); break; case 0x13: /*Read*/ case 0x1F: /*Verify*/ if (!i8271.phase) { // printf("Seek to %i\n",i8271.params[0]); i8271.curtrack[curdrive]=i8271.params[0]; // i8271.realtrack+=diff; // disc_seek(0,i8271.realtrack); // printf("Re-seeking - track now %i %i\n",i8271.curtrack,i8271.realtrack); disc_readsector(curdrive,i8271.cursector,i8271.params[0],(i8271.drvout&0x20)?1:0,0); i8271.phase=1; return; } i8271.sectorsleft--; if (!i8271.sectorsleft) { i8271.status=0x18; i8271.result=0; NMI8271(); setspindown8271(); verify8271=0; return; } i8271.cursector++; disc_readsector(curdrive,i8271.cursector,i8271.params[0],(i8271.drvout&0x20)?1:0,0); byte=0; break; case 0x1B: /*Read ID*/ // printf("Read ID callback %i\n",i8271.phase); if (!i8271.phase) { i8271.curtrack[curdrive]=i8271.params[0]; // i8271.realtrack+=diff; // disc_seek(0,i8271.realtrack); disc_readaddress(curdrive,i8271.params[0],(i8271.drvout&0x20)?1:0,0); i8271.phase=1; return; } // printf("Read ID track %i %i\n",i8271.params[0],i8271.sectorsleft); i8271.sectorsleft--; if (!i8271.sectorsleft) { i8271.status=0x18; i8271.result=0; NMI8271(); // printf("8271 : ID read done!\n"); setspindown8271(); return; } i8271.cursector++; disc_readaddress(curdrive,i8271.params[0],(i8271.drvout&0x20)?1:0,0); byte=0; break; case 0x23: /*Format*/ if (!i8271.phase) { i8271.curtrack[curdrive]=i8271.params[0]; disc_writesector(curdrive,i8271.cursector,i8271.params[0],(i8271.drvout&0x20)?1:0,0); i8271.phase=1; i8271.status=0x8C; i8271.result=0; NMI8271(); return; } if (i8271.phase==2) { i8271.status=0x18; i8271.result=0; NMI8271(); setspindown8271(); verify8271=0; return; } disc_format(curdrive,i8271.params[0],(i8271.drvout&0x20)?1:0,0); i8271.phase=2; break; case 0x29: /*Seek*/ i8271.curtrack[curdrive]=i8271.params[0]; // i8271.realtrack+=diff; i8271.status=0x18; i8271.result=0; NMI8271(); // disc_seek(0,i8271.realtrack); // printf("Seek done!\n"); setspindown8271(); break; case 0xFF: break; default: break; printf("Unknown 8271 command %02X 3\n",i8271.command); dumpregs(); exit(-1); } }
/* * All traps come here. It is slower to have all traps call trap() * rather than directly vectoring the handler. However, this avoids a * lot of code duplication and possible bugs. The only exception is * VectorSYSCALL. * Trap is called with interrupts disabled via interrupt-gates. */ void trap(Ureg* ureg) { int clockintr, vno, user; // cache the previous vno to see what might be causing // trouble static int lastvno; vno = ureg->type; uint64_t gsbase = rdmsr(GSbase); //if (sce > scx) iprint("===================="); if (vno == 8) { iprint("Lstar is %p\n", (void *)rdmsr(Lstar)); iprint("GSbase is %p\n", (void *)gsbase); iprint("ire %d irx %d sce %d scx %d lastvno %d\n", ire, irx, sce, scx, lastvno); iprint("irxe %d \n", irxe); die("8"); } lastvno = vno; if (gsbase < 1ULL<<63) die("bogus gsbase"); Mach *m = machp(); char buf[ERRMAX]; Vctl *ctl, *v; if (0 && m && m->externup && m->externup->pid == 6) { //iprint("type %x\n", ureg->type); if (ureg->type != 0x49) die("6\n"); } m->perf.intrts = perfticks(); user = userureg(ureg); if(user && (m->nixtype == NIXTC)){ m->externup->dbgreg = ureg; cycles(&m->externup->kentry); } clockintr = 0; //_pmcupdate(m); if(ctl = vctl[vno]){ if(ctl->isintr){ m->intr++; if(vno >= VectorPIC && vno != VectorSYSCALL) m->lastintr = ctl->irq; }else if(m->externup) m->externup->nqtrap++; if(ctl->isr) ctl->isr(vno); for(v = ctl; v != nil; v = v->next){ if(v->f) v->f(ureg, v->a); } if(ctl->eoi) ctl->eoi(vno); intrtime(vno); if(ctl->isintr){ if(ctl->irq == IrqCLOCK || ctl->irq == IrqTIMER) clockintr = 1; if(m->externup && !clockintr) preempted(); } } else if(vno < nelem(excname) && user){ spllo(); snprint(buf, sizeof buf, "sys: trap: %s", excname[vno]); postnote(m->externup, 1, buf, NDebug); } else if(vno >= VectorPIC && vno != VectorSYSCALL){ /* * An unknown interrupt. * Check for a default IRQ7. This can happen when * the IRQ input goes away before the acknowledge. * In this case, a 'default IRQ7' is generated, but * the corresponding bit in the ISR isn't set. * In fact, just ignore all such interrupts. */ /* clear the interrupt */ i8259isr(vno); iprint("cpu%d: spurious interrupt %d, last %d\n", m->machno, vno, m->lastintr); intrtime(vno); if(user) kexit(ureg); return; } else{ if(vno == VectorNMI){ nmienable(); if(m->machno != 0){ iprint("cpu%d: PC %#llux\n", m->machno, ureg->ip); for(;;); } } dumpregs(ureg); if(!user){ ureg->sp = PTR2UINT(&ureg->sp); dumpstackwithureg(ureg); } if(vno < nelem(excname)) panic("%s", excname[vno]); panic("unknown trap/intr: %d\n", vno); } splhi(); /* delaysched set because we held a lock or because our quantum ended */ if(m->externup && m->externup->delaysched && clockintr){ if(0) if(user && m->externup->ac == nil && m->externup->nqtrap == 0 && m->externup->nqsyscall == 0){ if(!waserror()){ m->externup->ac = getac(m->externup, -1); poperror(); runacore(); return; } } sched(); splhi(); } if(user){ if(m->externup && m->externup->procctl || m->externup->nnote) notify(ureg); kexit(ureg); } }
//This is run in interrupt context and apart from initialization and destruction, this is the only code //touching the host (=spihost[x]) variable. The rest of the data arrives in queues. That is why there are //no muxes in this code. static void IRAM_ATTR spi_intr(void *arg) { BaseType_t r; BaseType_t do_yield = pdFALSE; spi_slave_transaction_t *trans = NULL; spi_slave_t *host = (spi_slave_t *)arg; #ifdef DEBUG_SLAVE dumpregs(host->hw); if (host->dmadesc_rx) dumpll(&host->dmadesc_rx[0]); #endif //Ignore all but the trans_done int. if (!host->hw->slave.trans_done) return; if (host->cur_trans) { if (host->dma_chan == 0 && host->cur_trans->rx_buffer) { //Copy result out uint32_t *data = host->cur_trans->rx_buffer; for (int x = 0; x < host->cur_trans->length; x += 32) { uint32_t word; int len = host->cur_trans->length - x; if (len > 32) len = 32; word = host->hw->data_buf[(x / 32)]; memcpy(&data[x / 32], &word, (len + 7) / 8); } } else if (host->dma_chan != 0 && host->cur_trans->rx_buffer) { int i; //In case CS goes high too soon, the transfer is aborted while the DMA channel still thinks it's going. This //leads to issues later on, so in that case we need to reset the channel. The state can be detected because //the DMA system doesn't give back the offending descriptor; the owner is still set to DMA. for (i = 0; host->dmadesc_rx[i].eof == 0 && host->dmadesc_rx[i].owner == 0; i++) ; if (host->dmadesc_rx[i].owner) { spicommon_dmaworkaround_req_reset(host->dma_chan, spi_slave_restart_after_dmareset, host); } } if (host->cfg.post_trans_cb) host->cfg.post_trans_cb(host->cur_trans); //Okay, transaction is done. //Return transaction descriptor. xQueueSendFromISR(host->ret_queue, &host->cur_trans, &do_yield); host->cur_trans = NULL; } if (host->dma_chan != 0) { spicommon_dmaworkaround_idle(host->dma_chan); if (spicommon_dmaworkaround_reset_in_progress()) { //We need to wait for the reset to complete. Disable int (will be re-enabled on reset callback) and exit isr. esp_intr_disable(host->intr); if (do_yield) portYIELD_FROM_ISR(); return; } } //Grab next transaction r = xQueueReceiveFromISR(host->trans_queue, &trans, &do_yield); if (!r) { //No packet waiting. Disable interrupt. esp_intr_disable(host->intr); } else { //We have a transaction. Send it. host->hw->slave.trans_done = 0; //clear int bit host->cur_trans = trans; if (host->dma_chan != 0) { spicommon_dmaworkaround_transfer_active(host->dma_chan); host->hw->dma_conf.val |= SPI_OUT_RST | SPI_IN_RST | SPI_AHBM_RST | SPI_AHBM_FIFO_RST; host->hw->dma_out_link.start = 0; host->hw->dma_in_link.start = 0; host->hw->dma_conf.val &= ~(SPI_OUT_RST | SPI_IN_RST | SPI_AHBM_RST | SPI_AHBM_FIFO_RST); host->hw->dma_conf.out_data_burst_en = 0; host->hw->dma_conf.indscr_burst_en = 0; host->hw->dma_conf.outdscr_burst_en = 0; //Fill DMA descriptors if (trans->rx_buffer) { host->hw->user.usr_miso_highpart = 0; spicommon_setup_dma_desc_links(host->dmadesc_rx, ((trans->length + 7) / 8), trans->rx_buffer, true); host->hw->dma_in_link.addr = (int)(&host->dmadesc_rx[0]) & 0xFFFFF; host->hw->dma_in_link.start = 1; } if (trans->tx_buffer) { spicommon_setup_dma_desc_links(host->dmadesc_tx, (trans->length + 7) / 8, trans->tx_buffer, false); host->hw->user.usr_mosi_highpart = 0; host->hw->dma_out_link.addr = (int)(&host->dmadesc_tx[0]) & 0xFFFFF; host->hw->dma_out_link.start = 1; } host->hw->slave.sync_reset = 1; host->hw->slave.sync_reset = 0; } else { //No DMA. Turn off SPI and copy data to transmit buffers. host->hw->cmd.usr = 0; host->hw->slave.sync_reset = 1; host->hw->slave.sync_reset = 0; host->hw->user.usr_miso_highpart = 0; host->hw->user.usr_mosi_highpart = 0; if (trans->tx_buffer) { const uint32_t *data = host->cur_trans->tx_buffer; for (int x = 0; x < trans->length; x += 32) { uint32_t word; memcpy(&word, &data[x / 32], 4); host->hw->data_buf[(x / 32)] = word; } } } host->hw->slv_rd_bit.slv_rdata_bit = 0; host->hw->slv_wrbuf_dlen.bit_len = trans->length - 1; host->hw->slv_rdbuf_dlen.bit_len = trans->length - 1; host->hw->mosi_dlen.usr_mosi_dbitlen = trans->length - 1; host->hw->miso_dlen.usr_miso_dbitlen = trans->length - 1; host->hw->user.usr_mosi = (trans->tx_buffer == NULL) ? 0 : 1; host->hw->user.usr_miso = (trans->rx_buffer == NULL) ? 0 : 1; //Kick off transfer host->hw->cmd.usr = 1; if (host->cfg.post_setup_cb) host->cfg.post_setup_cb(trans); } if (do_yield) portYIELD_FROM_ISR(); }