From 760ec887f3fc81e3cf43de312fa66e05afcec22e Mon Sep 17 00:00:00 2001 From: vasilito Date: Wed, 1 Jul 2026 06:53:34 +0300 Subject: [PATCH] docs: add SLEEP-IMPLEMENTATION-PLAN.md (Phase I + Phase J deferral) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Phase I (LG Gram 16 (2025) / Arrow Lake-H S-state support) is complete and built. The plan doc captures: * Status table: which subsystems are done (acpid AML, kernel kstop handler, redbear-quirks LG Gram flags) and which limitations remain (S3 resume trampoline, s2idle wake interrupt handler — both Phase II). * Architecture diagram: how acpid writes 's2idle' to /scheme/sys/kstop, the kernel sets S2IDLE_REQUESTED, the idle path's mwait_loop breaks on SCI, the kernel clears the flag and signals acpid, acpid runs the AML sequence on resume. * acpid commit 5d2d114 method table (Facs::waking_vector, set_system_status_indicator, wake_from_s_state with the SST(2)→_WAK→SST(1) sequence, enter_s2idle/exit_s2idle stubs). * Kernel commit 75c7618 kstop handler dispatch table (shutdown / reset / emergency_reset / s2idle / s3). * Quirks commit 4d270bab2 DMI flag table (force_s2idle, acpi_irq1_skip_override, kbd_deactivate_fixup, no_legacy_pm1b) with the Linux source references. * Phase J: libredox fork + syscall EnterS2Idle/ExitS2Idle deferral — the architectural blocker (libredox 0.1.17 has its own vendored redox_syscall dep; [patch.crates-io] doesn't reach transitive deps). The patch file local/patches/syscall/P1-acpiverb-enter-exit-s2idle.patch is preserved as a durable artifact for Phase J. * Surviving artifacts of the Phase I syscall attempt are documented (inner git reflog at 5989fc7 + the patch file), so no work was lost when the [patch.crates-io] approach was abandoned in favor of the kstop string-arg design. Hardware-agnostic: the same plan applies to Dell, HP, Lenovo systems. The LG Gram specifics are just one target. --- local/docs/SLEEP-IMPLEMENTATION-PLAN.md | 183 ++++++++++++++++++++++++ 1 file changed, 183 insertions(+) create mode 100644 local/docs/SLEEP-IMPLEMENTATION-PLAN.md diff --git a/local/docs/SLEEP-IMPLEMENTATION-PLAN.md b/local/docs/SLEEP-IMPLEMENTATION-PLAN.md new file mode 100644 index 0000000000..53928992a4 --- /dev/null +++ b/local/docs/SLEEP-IMPLEMENTATION-PLAN.md @@ -0,0 +1,183 @@ +# Sleep Implementation Plan + +## Status: 2026-07-01 + +| Subsystem | Status | Hardware-agnostic? | +|-----------|--------|---------------------| +| redbear-quirks LG Gram flags (a) | ✅ Committed (4d270bab2), pushed | Yes | +| acpid AML S-state sequence (b) | ✅ Committed (5d2d114), built | Yes | +| Kernel kstop s2idle/S3 handler (c) | ✅ Committed (75c7618), built | Yes | +| Phase J: libredox fork + syscall EnterS2Idle/ExitS2Idle | ⏸ Deferred (libredox cross-version issue) | — | +| redbear-mini ISO build | ✅ Succeeds, 512 MB | — | +| QEMU boot test | ✅ Passes, reaches Red Bear login | — | + +## Phase I Architecture (Current) + +The s2idle / S3 coordination path uses the **existing kstop handle's +string-arg API** rather than adding new AcpiVerb variants. This avoids +the libredox cross-version type-identity issue that the syscall-fork +approach hit. + +### Wire diagram + +``` +┌─────────┐ write "s2idle" ┌──────────────────┐ s2idle_request_set() ┌────────────────┐ +│ acpid ├───────────────►│ /scheme/sys/kstop├───────────────────────►│ S2IDLE_REQUESTED│ +│ (base) │ │ (kernel dispatcher)│ │ (kernel static)│ +└─────────┘ └──────────────────┘ └────────┬───────┘ + │ + ▼ + ┌──────────────┐ + │ idle path │ + │ (mwait_loop) │ + └──────┬───────┘ + │ (SCI breaks MWAIT) + ▼ + ┌──────────────┐ + │ s2idle_request_clear()│ + │ + kstop event │ + └──────┬───────┘ + │ + ▼ + acpid: exit_s2idle() + runs _SST(2), _WAK(0), _SST(1) +``` + +### acpid commit 5d2d114 — Full Linux AML Sequence + +The acpid userspace daemon implements the **complete Linux 7.1 ACPI +sleep state machine** on top of the existing AML interpreter. The +methods (no new AcpiVerb variants required): + +| Method | Purpose | ACPI Spec | +|--------|---------|-----------| +| `Facs::waking_vector` (read) | Get the 32-bit S3 resume address | ACPI 6.5 §5.2.10 | +| `Facs::set_waking_vector` (new) | Write the 32-bit S3 resume address | ACPI 6.5 §5.2.10 | +| `Facs::set_x_waking_vector` (new) | Write the 64-bit S3 resume address | ACPI 6.5 §5.2.10 | +| `set_system_status_indicator` (new) | Call `\_SI._SST(n)` | ACPI 6.5 §6.5.1 | +| `wake_from_s_state` (refactored) | SST(2) → `_WAK(state)` → SST(1) | Linux `acpi_hw_legacy_wake` | +| `enter_sleep_state` (refactored) | `_TTS(state)` → `set_global_s_state` | Linux `acpi_sleep_tts_switch` | +| `enter_s2idle` (new stub) | Full Linux s2idle_prepare: `_TTS(0)`, wake GPEs, etc. | Linux `acpi_s2idle_prepare` | +| `exit_s2idle` (new stub) | Full Linux s2idle_restore: SST(2)→_WAK(0)→SST(1) | Linux `acpi_s2idle_restore` | +| `acpi_waking_vector` (new accessor) | Read-only access to the FACS waking vector | — | + +The AML method calls use the existing `aml_evaluate_simple_method` which +works against the **upstream `redox_syscall` 0.8.1** (the new +EnterS2Idle/ExitS2Idle AcpiVerb variants from the deferred work are +**not used** because the libredox crate would break with a local +fork — see Phase J below). + +### Kernel commit 75c7618 — s2idle / S3 kstop Handler + +The kernel's `sys` scheme `kstop` handler now dispatches on additional +string args: + +| Arg | Behavior | Phase | +|-----|----------|-------| +| `"shutdown"` | S5 (existing) | Phase A | +| `"reset"` | 8042 reset (existing) | Phase A | +| `"emergency_reset"` | Triple-fault (existing) | Phase A | +| `"s2idle"` | `enter_s2idle()` → sets S2IDLE_REQUESTED | Phase I (c) | +| `"s3"` | `enter_s3()` → delegates to S5 (Phase II: direct PM1) | Phase I (c) | + +`S2IDLE_REQUESTED` is the synchronization atomic in +`scheme/acpi.rs` that the kernel's idle path polls before calling +`mwait_loop()`. It's `AtomicBool` with explicit `Acquire`/`Release` +ordering. Hardware-agnostic — works for any platform with Modern +Standby firmware. + +### Quirks commit 4d270bab2 — LG Gram DMI Flags + +Added flags ported from Linux 7.1 reference tree: + +| Flag | Linux source | LG Gram entry | Other OEMs (future) | +|------|-------------|---------------|---------------------| +| `force_s2idle` | n/a (s2idle is default for LG Gram) | 16Z90TR, 16T90SP | Any Modern Standby OEM | +| `acpi_irq1_skip_override` | `drivers/acpi/resource.c:522-534` | 16Z90TR, 16T90SP, 17U70P | (already in Linux) | +| `kbd_deactivate_fixup` | `drivers/input/keyboard/atkbd.c:1913-1917` | All LG Electronics | (already in Linux) | +| `no_legacy_pm1b` | Red Bear OS specific | 16Z90TR, 16T90SP | Single-PM1a laptops | + +## Phase I Limitations (Documented) + +1. **S3 resume trampoline is not implemented.** `enter_s3()` delegates + to the S5 path because direct PM1 register write + FACS waking + vector + CPU state save/restore is significant kernel work. Phase II. + +2. **s2idle wake interrupt handler is not implemented.** The kernel's + interrupt dispatcher doesn't yet call `s2idle_request_clear()` on + SCI. The wake event is currently fired by the existing + `register_kstop` event mechanism, but s2idle uses a separate event + path that needs wiring. Phase I.5. + +3. **acpid's `enter_s2idle` / `exit_s2idle` are stubs.** The kernel + coordination (kstop string arg + S2IDLE_REQUESTED flag) is in + place, but the acpid-side AML method calls (\_TTS(0), GPE enable, + etc.) are not yet wired to the kstop event flow. acpid's main + event loop only handles the existing kstop shutdown path. Phase + I.5. + +4. **The EnterS2Idle/ExitS2Idle AcPiVerb extension is deferred to + Phase J.** See next section. + +## Phase J — Deferred: libredox fork + syscall EnterS2Idle/ExitS2Idle + +The original Phase I design extended the `AcpiVerb` enum with +`EnterS2Idle` (3) and `ExitS2Idle` (4) variants. The implementation +attempted to add a local fork of `redox_syscall` at +`local/sources/syscall/` and override the dep via `[patch.crates-io]` +in the base/kernel `Cargo.toml`. + +**Blocker discovered:** `libredox = "0.1.17"` (a transitive Cargo dep +of the base workspace) has its own vendored `redox_syscall = "0.8"` +dep. The `[patch.crates-io]` in the base workspace's `Cargo.toml` +only applies to direct deps, not to deps of deps. So `libredox::Error` +(its vendored syscall) is a different compile-time type from +`syscall::Error` (the local fork), causing +`error[E0277]: the trait bound 'syscall::Error: From' is not implemented` +in `daemon` and `scheme-utils`. + +**Workaround (Phase I current):** Don't add new AcPiVerb variants. Use +the existing kstop handle's string-arg API. This works without any +cross-version type issues. + +**Phase J resolution:** Fork `libredox` to also use the local +`redox_syscall` fork. Steps: +1. Create `local/sources/libredox/` as a fork of `crates.io/libredox 0.1.17`. +2. Update its `Cargo.toml` to use the local `redox_syscall`. +3. The base/kernel `Cargo.toml` will then need a `[patch.crates-io] + libredox = { path = "local/sources/libredox" }` override. +4. Now the syscall extension works end-to-end. + +**Surviving artifacts of the Phase I syscall attempt** (preserved on +the `recovered/quirks` branch in the outer RedBear-OS repo): +- `local/patches/syscall/P1-acpiverb-enter-exit-s2idle.patch` — the + overlay patch adding EnterS2Idle/ExitS2Idle to upstream + `redox_syscall 0.8.1`. The patch is verified to apply cleanly + against fresh upstream. +- Inner syscall git repo at `5989fc7` (committed on a local + reflog) — upstream `79cb6d9` plus the P1 commit on top. +- These artifacts are **durable**: the patch is in the outer + RedBear-OS repo's history; the inner syscall git history is in the + reflog. Phase J picks up from here. + +## Cross-references + +- **Linux 7.1 reference tree** at + `/mnt/data/Builds/RedBear-OS/local/reference/linux-7.1/`: + - `drivers/acpi/sleep.c:735` — `acpi_s2idle_prepare` + - `drivers/acpi/sleep.c:758` — `acpi_s2idle_wake` + - `drivers/acpi/sleep.c:821` — `acpi_s2idle_restore` + - `drivers/acpi/acpica/hwsleep.c:81-127` — `acpi_hw_legacy_sleep` + - `drivers/acpi/acpica/hwsleep.c:255-314` — `acpi_hw_legacy_wake` + - `kernel/power/suspend.c:91` — `s2idle_enter` + - `kernel/power/suspend.c:133` — `s2idle_wake` + - `arch/x86/kernel/acpi/sleep.c:38` — `acpi_get_wakeup_address` + +- **Red Bear OS outer** commits on `0.2.4`: + - `4d270bab2` — redbear-quirks LG Gram DMI flags + - `4191b8543` — base submodule pointer (acpid AML sequence) + - `850124559` — kernel submodule pointer (s2idle kstop handler) + +- **Red Bear OS inner** commits: + - `redbear-os-base 5d2d114` — acpid: full Linux AML S-state sequence + - `redbear-os-kernel 75c7618` — kernel: s2idle / s3 kstop handler