debugger: reachable from the console, and named on the crash screen
Two things, both about the debugger being available at the moment you
actually need it rather than once a shell exists.
**Ctrl-G on the console runs every view.** No filesystem, no /dev, no
shell -- it is the last thing main() sets up before entering the scheduler,
so it answers from early in boot, which is exactly when boot problems
happen. It sits beside the older Ctrl-P, and the difference between them is
the interesting part: procdump() takes no lock at all, deliberately,
because a lock is a way to hang while reporting a hang. The views cannot
follow that rule -- a free list read torn is worse than not read -- so they
take locks, and a lock must never be taken from an interrupt handler that
may have interrupted its holder. The key therefore *requests* and a kernel
thread *performs*. A scheduler too wedged to run a thread will not answer
Ctrl-G; Ctrl-P still will, and that division is the honest one.
**PSOGM says where the report went.** Its closing line used to be an
addr2line command, which the call chain no longer needs -- it prints names
now. What replaced it is the thing nobody would guess:
This report is in /proc/kmsg after a restart.
schdbg, or Ctrl-G on the console, asks more.
PSOGM -- Purple Screen of Guru Meditation
"Restart and read it" beats "photograph this screen" by a wide margin, and
until the log outlived the kernel it was not true. Both panic.c and
graphics.md had claimed in writing that the screen was the only artefact of
a crash; neither says so now. The QR code stays, because it is still the
only channel that works when the machine will not come back at all.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VQ7Qx8E1q1M1bbCq8QLHS2
This commit is contained in:
parent
113595f80b
commit
415df0fd4d
7 changed files with 142 additions and 16 deletions
|
|
@ -2,6 +2,7 @@
|
|||
#include "types.h"
|
||||
#include "defs.h"
|
||||
#include "klog.h"
|
||||
#include "dbg.h"
|
||||
#include "vt.h"
|
||||
#include "kbd.h" /* KEY_VT_SWITCH -- the terminal-switch chords */
|
||||
#include "gfx.h"
|
||||
|
|
@ -462,6 +463,19 @@ consoleintr(int (*getc)(void))
|
|||
continue;
|
||||
}
|
||||
|
||||
// Ctrl-G: every debug view, on the console.
|
||||
//
|
||||
// The same thing `sysrq g` and `schdbg all` produce, reachable with no
|
||||
// filesystem mounted and no shell running -- which is the point. It only
|
||||
// asks; a kernel thread does the work, because the views take locks and
|
||||
// this is an interrupt handler. See dbg_request_dump().
|
||||
if (c == C('G')) {
|
||||
release(&input_lock);
|
||||
dbg_request_dump();
|
||||
acquire(&input_lock);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (v->tio.c_lflag & ICANON) {
|
||||
if (c == v->tio.c_cc[VERASE] || c == C('H')) {
|
||||
erase_one(v);
|
||||
|
|
|
|||
|
|
@ -217,6 +217,12 @@ kmain(uint32 fb_addr)
|
|||
// until mpmain() below enters the scheduler.
|
||||
netinit();
|
||||
if (boot_verbose) cprintf("verbose boot: netinit done\n");
|
||||
// The debugger's own thread, for the same reason netinit's comes after
|
||||
// sinit: kthread_create needs a usable process table. From here on Ctrl-G
|
||||
// on the console answers, with no filesystem mounted and nothing in
|
||||
// userspace started -- which is the whole point of putting it this early.
|
||||
dbg_thread_start();
|
||||
if (boot_verbose) cprintf("verbose boot: dbg thread started\n");
|
||||
mpmain();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -497,16 +497,25 @@ paint(char *reason, addr_t *pcs, int npcs)
|
|||
trace_line(line, sizeof(line), i, pcs[i]);
|
||||
gfx_text_at(vx - 3 * cw, y, line, PSOGM_FG);
|
||||
y += ch;
|
||||
if (y > sh - ch * 5)
|
||||
if (y > sh - ch * 6)
|
||||
break;
|
||||
}
|
||||
|
||||
// Two closing lines, bottom left: what to do with the numbers above, and
|
||||
// what this screen is called, so it can be searched for by name. Shortened
|
||||
// from the full command line, which at 62 characters ran under the QR card.
|
||||
gfx_text_at(left, sh - ch * 3,
|
||||
"Resolve: addr2line -e kernel <address>", PSOGM_DIM);
|
||||
gfx_text_at(left, sh - ch * 3 + ch + 4,
|
||||
// Three closing lines, bottom left. The first used to be an addr2line
|
||||
// command, which the call chain above no longer needs -- it prints names.
|
||||
//
|
||||
// What replaces it is the thing nobody would guess: **this screen is no
|
||||
// longer the only copy.** The log survives into the next boot (see
|
||||
// include/klog.h), so the right instruction on a crash screen is now
|
||||
// "restart and read it" rather than "photograph this".
|
||||
//
|
||||
// Kept under about 45 characters each: the QR card is on the right, and the
|
||||
// 62-character command line this replaces used to run underneath it.
|
||||
gfx_text_at(left, sh - ch * 4,
|
||||
"This report is in /proc/kmsg after a restart.", PSOGM_DIM);
|
||||
gfx_text_at(left, sh - ch * 4 + ch + 4,
|
||||
"schdbg, or Ctrl-G on the console, asks more.", PSOGM_DIM);
|
||||
gfx_text_at(left, sh - ch * 4 + (ch + 4) * 2,
|
||||
"PSOGM -- Purple Screen of Guru Meditation", PSOGM_DIM);
|
||||
}
|
||||
|
||||
|
|
@ -542,6 +551,14 @@ report_serial(char *reason, addr_t *pcs, int npcs)
|
|||
cprintf("\n Resolve with: addr2line -e build/kernel/kernel <address>\n");
|
||||
else
|
||||
cprintf("\n For a line number: addr2line -e build/kernel/kernel <address>\n");
|
||||
|
||||
// Where to go next. Worth printing even though the machine is about to stop,
|
||||
// because this text is also what ends up in the log -- and the log is the
|
||||
// thing being pointed at.
|
||||
cprintf(" This report is in /proc/kmsg after a restart.\n");
|
||||
cprintf(" Then: schdbg whose <addr> -- who owns a page\n");
|
||||
cprintf(" schdbg watch <addr> -- who writes to one\n");
|
||||
cprintf(" Ctrl-G on the console -- every view, no shell needed\n");
|
||||
cprintf(" Reason: %s\n", reason);
|
||||
cprintf(" System halted.\n");
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue