panic: blink the keyboard lights, and mark the screen on the way in
A laptop has no serial port, and the machine we are trying to boot stops with the loader's splash still on screen. Three completely different things look exactly like that: the jump never landed, the kernel started and hung, or the kernel started and panicked with a full report drawn into a framebuffer nobody can see. They call for different next steps, so the kernel now says which without needing a console at all. **A bar, as the kernel's first act.** Eight lines of accent colour across the top of the framebuffer, written straight through the handoff block before a single subsystem exists -- no gfx, no scanout, no allocator, nothing that can itself fail. If it appears over the splash, the jump landed and the kernel is executing. If it does not, nothing below that point is worth looking at. Skipped when the framebuffer is above the direct map, because a fault there leaves the machine quieter still, and free on a boot that works: the console clears the screen a few lines later. **Blinking keyboard lights, on panic.** Scroll, Num and Caps together, about three times a second, for ever. It is the one output every PC has had since before any of this existed -- no driver, no interrupt, no memory -- and it works when the graphics do not. Linux does the same thing for the same reason. Every wait in it is bounded. It runs after `panicked` is set so there is nothing left to protect, but a machine that hangs inside its own death rattle tells you less than one that stops quietly. The delay is microdelay, which spins on the TSC: no timer, no interrupt, no calibration -- all three of which a kernel that died during boot may not have. That makes the three cases distinguishable from across the room: no bar and no blink is a jump that did not land; a bar and no blink is a kernel that hung; a blinking keyboard is a panic, and the report is in /proc/kmsg after a restart. **And the loader now describes the mode it is actually handing over**, not only the one the firmware started in. On a machine where changing the resolution loses the splash entirely, the difference between those two lines is the bug report; on a boot that works nobody sees either, because ClearScreen runs a few lines later. Verified: `echo c > /proc/sysrq`, then QMP polled for five and a half seconds afterwards -- the machine answers throughout and a screendump still shows the panic report intact, so the blink loop runs without faulting, resetting, or scribbling on what it is there to accompany. Both supported configurations boot clean with the early bar in place. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
0331d548c4
commit
3c5212a7c7
4 changed files with 151 additions and 2 deletions
|
|
@ -122,6 +122,44 @@ when the early console is set up. So a low framebuffer is attached exactly as
|
|||
before, and a high one is attached a few dozen instructions later, immediately
|
||||
after `kvmalloc()` — still thousands of lines before anything else happens.
|
||||
|
||||
### Two signals for a machine that cannot speak
|
||||
|
||||
A laptop has no serial port. When it stops with the loader's splash still on
|
||||
screen, three very different things look identical: the jump never landed, the
|
||||
kernel started and hung, or the kernel started and *panicked* with a full
|
||||
report drawn into a framebuffer nobody can see. Each calls for a different next
|
||||
step, so the kernel now produces two signals that need no console at all.
|
||||
|
||||
**A bar, as the kernel's first act.** Eight lines of accent colour across the
|
||||
top of the framebuffer, written straight through the handoff block before a
|
||||
single subsystem exists — no gfx, no scanout, no allocator. If it appears over
|
||||
the loader's splash, the jump landed and the kernel is executing; if it does
|
||||
not, nothing below that point is worth looking at. It is skipped when the
|
||||
framebuffer is above the direct map, because a fault there would leave the
|
||||
machine quieter still, and it costs nothing on a boot that works: the console
|
||||
clears the screen a few lines later.
|
||||
|
||||
**Blinking keyboard lights, on panic.** `panic_blink()` toggles Scroll, Num and
|
||||
Caps together, about three times a second, for ever. It is the one output every
|
||||
PC has had since before any of this existed: no driver, no interrupt, no
|
||||
memory, and it works when the graphics do not. Linux does the same thing for
|
||||
the same reason.
|
||||
|
||||
Every wait in it is bounded. It runs after `panicked` is set, so there is
|
||||
nothing left to protect — but a machine that hangs inside its own death rattle
|
||||
tells you less than one that stops quietly, so no loop in there can be entered
|
||||
that cannot be left. The delay is `microdelay`, which spins on the TSC and
|
||||
needs no timer, no interrupt and no calibration — all three of which a kernel
|
||||
that died during boot may not have.
|
||||
|
||||
So the three cases separate:
|
||||
|
||||
| What you see | What happened |
|
||||
| --- | --- |
|
||||
| No bar, no blink | The jump did not land. The loader's last label says where. |
|
||||
| Bar, no blink | The kernel is executing and hung. Not a panic. |
|
||||
| Blinking lights | The kernel panicked. The report is in `/proc/kmsg` after a restart. |
|
||||
|
||||
### The loader says which stage it is in
|
||||
|
||||
After the splash, `print()` goes to the serial port and nowhere else — writing
|
||||
|
|
|
|||
Loading…
Reference in a new issue