i2c-hid on a stack of its own; PSOGM powers off after three minutes

The touchpad driver crashed the ASUS TUF A15 at boot. Its thread runs the
firmware's AML -- _DSM, _PS0, _CRS -- through uACPI at -O0, on an 8 KB
kernel stack, and kernel stacks are one array: running off the end lands
in the next thread's stack, and the machine dies a moment later in some
other code. The thread now runs on a 64 KB stack of its own, through
SCFF's call_on_stack().

And a crashed laptop sat with its fans up until somebody held the power
button, since the other processors keep running. On an ordinary boot the
PSOGM now says it will power off, and does, after three minutes: SLP_TYP
from \_S5, read at boot, written straight to PM1 control with no AML, which
could sleep or wait on a lock a dead processor holds. A verbose boot keeps
the screen up for ever.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01S1giNvrHTrPMPw7V6x1kQ4
This commit is contained in:
Nexoniarz 2026-10-25 00:21:39 +02:00
commit b15fb2fdaa
4 changed files with 85 additions and 3 deletions

View file

@ -45,6 +45,7 @@
#include "gfx/theme.h"
#include "gfx/logo.h" /* LOGO_H -- the mark's height, for the layout below */
#include "gfx/qr.h"
#include "dev/acpi.h"
extern uint ticks;
extern int panicked;
@ -501,8 +502,12 @@ paint(char *reason, addr_t *pcs, int npcs)
// 62-character command line this replaces used to run underneath it.
text_at(left, sh - ch * 4,
"This report is in /proc/kmsg after a restart.", PSOGM_DIM);
// A verbose boot keeps the screen up for ever; any other powers off after
// PANIC_OFF_MS (see panic_blink), and says so rather than surprising anyone.
text_at(left, sh - ch * 4 + ch + 4,
"schdbg, or Ctrl-G on the console, asks more.", PSOGM_DIM);
boot_verbose ? "schdbg, or Ctrl-G on the console, asks more."
: "The machine powers itself off in 3 minutes.",
PSOGM_DIM);
text_at(left, sh - ch * 4 + (ch + 4) * 2,
"PSOGM -- Purple Screen of Guru Meditation", PSOGM_DIM);
gfx_flush_all();
@ -634,12 +639,24 @@ kbd_drain_ack(void)
// Scroll, Num and Caps, which is bits 0, 1 and 2 of the byte after 0xED.
#define LED_ALL 0x07
// How long the report stays up before the machine powers itself off, on an
// ordinary boot. A crashed laptop otherwise sits with its fans up -- the other
// processors are still running -- until somebody holds the power button, and
// three minutes is long enough to photograph the screen or scan the QR code.
// A verbose boot is somebody debugging on purpose, and keeps it up for ever.
#define PANIC_OFF_MS (3 * 60 * 1000)
static void
panic_blink(void)
{
int on = 0;
uint elapsed = 0;
for (;;) {
if (!boot_verbose && elapsed >= PANIC_OFF_MS) {
acpi_poweroff_now();
elapsed = 0; // still on: blink on, and try again later
}
kbd_out(0xED);
kbd_drain_ack();
kbd_out(on ? LED_ALL : 0x00);
@ -655,5 +672,6 @@ panic_blink(void)
// kernel that died during boot may be missing.
for (int i = 0; i < 300; i++)
microdelay(1000);
elapsed += 300;
}
}