// mp kernel support (386 only) // // usage: acid -k -l kernel -l mach // MACHSIZE = BY2PG; defn machno() { print(m->machno, "\n"); } defn mach(mach) { complex Mach mach; print(mach\X, " ", mach.machno, " proc "); if mach.proc == 0 then print(0\X, "\n"); else proc(mach.proc); } defn machs() { local i; i = 0; loop 1, conf.nmach do { mach(machp[i]); i = i+1; } } defn machaddr(mach, addr) { if addr < *m || addr >= *m+MACHSIZE then return addr; addr = addr & (MACHSIZE-1); return mach+addr; } defn machureg(mach) { complex Mach mach; // dbgreg 0 is valid; current register state return (Ureg)machaddr(mach, mach.dbgreg); } defn machpc(mach) { complex Mach mach; local ureg; ureg = machureg(mach); return ureg.pc; } defn machsp(mach) { complex Mach mach; local ureg; if mach.dbgsp == 0 then { ureg = machureg(mach); return ureg.sp; } else return mach.dbgsp; } defn machgpr(mach) { complex Mach mach; local ureg; ureg = machureg(mach); print("AX\t", ureg.ax\X, " BX\t", ureg.bx\X, " CX\t", ureg.cx\X, " DX\t", ureg.dx\X, "\n"); print("DI\t", ureg.di\X, " SI\t", ureg.si\X, " BP\t", ureg.bp\X, "\n"); } defn machspr(mach) { complex Mach mach; local ureg, sp; ureg = machureg(mach); sp = machsp(mach); print("PC\t", ureg.pc\X, " ", fmt(ureg.pc, 'a'), " "); pfl(ureg.pc); print("SP\t", sp\X, " ECODE ", ureg.ecode\X, " EFLAG ", ureg.flags\X, "\n"); print("CS\t", ureg.cs\X, " DS\t ", ureg.ds\X, " SS\t", ureg.ss\X, "\n"); print("GS\t", ureg.gs\X, " FS\t ", ureg.fs\X, " ES\t", ureg.es\X, "\n"); print("TRAP\t", ureg.trap\X, " ", reason(ureg.trap), "\n"); } defn machregs(mach) { machspr(mach); machgpr(mach); } defn machstk(mach) { _stk(machpc(mach), machaddr(mach, machsp(mach)), 0, 0); } defn machlstk(mach) { _stk(machpc(mach), machaddr(mach, machsp(mach)), 0, 1); } defn machstacks() { local i; i = 0; loop 1, conf.nmach do { print("=========================================================\n"); mach(machp[i]); machstk(machp[i]); i = i+1; } } // a function of last resort... defn machunwind(mach) { complex Mach mach; local sp, se; sp = machsp(mach); if mach.proc != 0 then se = sp | (KSTACK-1); else se = sp | (MACHSIZE-1); dump(machaddr(mach, sp), (se-sp)/4, "a"); } // kernel procstk assumes gotolabel; breaks on mp defn procstk(p) { complex Proc p; if p.mach != 0 then _stk(machpc(p.mach), machaddr(p.mach, machsp(p.mach)), 0, 0); else if p.state != 0 then _stk(gotolabel, *(p.sched), 0, 0); } defn proclstk(p) { complex Proc p; if p.mach != 0 then _stk(machpc(p.mach), machaddr(p.mach, machsp(p.mach)), 0, 1); else if p.state != 0 then _stk(gotolabel, *(p.sched), 0, 1); } // builtin reason ignores status; breaks on mp defn reason(status) { if status == 0 then return "divide error"; else if status == 1 then return "debug exception"; else if status == 2 then return "nonmaskable interrupt"; else if status == 3 then return "breakpoint"; else if status == 4 then return "overflow"; else if status == 5 then return "bounds check"; else if status == 6 then return "invalid opcode"; else if status == 7 then return "coprocessor not available"; else if status == 8 then return "double fault"; else if status == 9 then return "coprocessor segment overrun"; else if status == 10 then return "invalid TSS"; else if status == 11 then return "segment not present"; else if status == 12 then return "stack exception"; else if status == 13 then return "general protection violation"; else if status == 14 then return "page fault"; else if status == 16 then return "coprocessor error"; else if status == 17 then return "alignment check"; else if status == 18 then return "machine check"; else if status == 19 then return "SIMD exception"; else if status == 64 then return "system call"; // emulate i386except brokenness: return "exception "+itoa(status); } print("/sys/lib/acid/mach");