Files
RedBear-OS/local/docs/SLEEP-IMPLEMENTATION-PLAN.md
T
vasilito 760ec887f3 docs: add SLEEP-IMPLEMENTATION-PLAN.md (Phase I + Phase J deferral)
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.
2026-07-01 06:53:34 +03:00

9.9 KiB

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<libredox::error::Error>' 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:735acpi_s2idle_prepare
    • drivers/acpi/sleep.c:758acpi_s2idle_wake
    • drivers/acpi/sleep.c:821acpi_s2idle_restore
    • drivers/acpi/acpica/hwsleep.c:81-127acpi_hw_legacy_sleep
    • drivers/acpi/acpica/hwsleep.c:255-314acpi_hw_legacy_wake
    • kernel/power/suspend.c:91s2idle_enter
    • kernel/power/suspend.c:133s2idle_wake
    • arch/x86/kernel/acpi/sleep.c:38acpi_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