Commit Graph

12 Commits

Author SHA1 Message Date
Red Bear OS 5d2d114bf9 acpid: complete Linux-compatible AML S-state sequence + s2idle stubs
Phase I (LG Gram 16 (2025) / Arrow Lake-H S-state work).

This commit implements the full Linux 7.1 S-state AML method
sequence in userspace acpid, plus stubs for s2idle (Modern
Standby). The kernel-side s2idle wire (new AcpiVerb variants
EnterS2Idle / ExitS2Idle) is the next step; see
local/docs/SLEEP-IMPLEMENTATION-PLAN.md for the gap analysis.

Changes:

* FACS: add set_waking_vector / set_x_waking_vector methods.
  These let acpid write the firmware waking vector for S3
  resume, mirroring Linux 7.1
  drivers/acpi/acpica/hwxfsleep.c:92
  (acpi_set_firmware_waking_vector).
* FACS access: add facs_mut() mutable accessor on
  AcpiContext (single-writer by construction).
* AML methods: add set_system_status_indicator() that calls
  \_SI._SST(n). The canonical values are 0=working, 1=waking,
  2=sleeping, 3=sleep-context, 7=indicator-off. Mirrors Linux
  ACPI 6.5 §6.5.1 (System Status Indicator).
* wake_from_s_state(): wrap \_WAK(n) with the full Linux wake
  sequence (\_SI._SST(2) before, \_SI._SST(1) after). Mirrors
  drivers/acpi/acpica/hwsleep.c:255-314.
* enter_sleep_state(): only call \_TTS here; \_PTS + \_SST +
  PM1 writes remain in set_global_s_state (Phase D, no
  duplication).
* s2idle: add enter_s2idle() and exit_s2idle() methods on
  AcpiContext. These prepare/finish the s2idle path on systems
  without \_S3 (LG Gram 2025). Currently a no-op for the kernel
  coordination; the AML \_WAK(0) sequence runs via
  wake_from_s_state(0) on exit.

Cross-references:
* drivers/acpi/sleep.c (Linux 7.1) — acpi_suspend_begin/enter
* drivers/acpi/acpica/hwxfsleep.c — acpi_enter_sleep_state_prep
* drivers/acpi/acpica/hwsleep.c — acpi_hw_legacy_wake
* kernel/power/suspend.c — s2idle_loop, s2idle_state
* drivers/acpi/acpica/hwesleep.c — acpi_hw_execute_sleep_method

Files changed:
  drivers/acpid/src/acpi.rs (+203 -14)
2026-07-01 01:17:15 +03:00
Red Bear OS c335553c7e acpid: add /scheme/acpi/processor/ route + cpu_names() (Phase G.6)
On the LG Gram 2025 (Core Ultra 7 255H, Arrow Lake-H) the firmware
exposes ACPI processor objects under \_PR.CPU0..\_PR.CPU15 along
with full _PSS, _PSD, _CST, and _CPC objects. The HWP-aware
cpufreqd (Phase G.2) reads these to discover the P-state range
and the HWP activity window. Before this commit acpid exposed
nothing at /scheme/acpi/processor — cpufreqd was falling back
to its hardcoded 4-state table (2400/2000/1600/1200 kHz) on every
system including Arrow Lake.

This commit adds:

1. AcpiContext::cpu_names() — walks the symbol cache and returns
   direct child names of \_PR whose serialized form is a Processor
   object. Matches on the \_PR.<name> prefix (no further dots) to
   avoid returning sub-objects like \_PR.CPU0._PSS.

2. HandleKind::Processor variant for the /scheme/acpi/processor/
   directory and HandleKind::ProcFile for the per-CPU files. Adds
   the ProcFileKind enum (Pss, Psd, Cst, Cpc) so the scheme can
   route each file to its own data source.

3. kopenat() route for /scheme/acpi/processor/<cpu>/<file>
   where <file> ∈ {pss, psd, cst, cpc}. Path-component match
   extended to 4 elements (was 3); cpu_id parsed as u32.

4. getdents() entry for HandleKind::Processor using
   self.ctx.cpu_names() — matches the same pattern as Thermal
   and Power. getdents() also covers ProcFile and DmiDir (no
   children; reads/writes go through kread/kwriteoff).

5. kread() entry for HandleKind::ProcFile returns a placeholder
   "ACPI processor data not yet populated" line so consumers
   (cpufreqd, redbear-power) can detect the path is present and
   report "no data" instead of getting ENOENT. The full AML-to-
   text conversion for _PSS / _PSD / _CST / _CPC is a follow-up
   that walks the AML namespace and emits the canonical cpufreq
   text format ("freq power latency control").

6. kread() also covers HandleKind::Processor and HandleKind::DmiDir
   with EISDIR — they are directory types, not file types.

The acpid version remains at 0.1.0 — the policy in AGENTS.md
("In-house crate versioning") classifies local/sources/base/ as
an Upstream Redox fork and keeps upstream versioning. Phase G.6
adds infrastructure only, not a version bump.

Verified by: CI=1 ./local/scripts/build-redbear.sh redbear-mini
succeeded with exit 0. ISO at build/x86_64/redbear-mini.iso
(512 MB) at 2026-06-30 14:40. QEMU mini boot reaches Red Bear
login: as before. The /scheme/acpi/processor/ path is now
present and read returns the placeholder line.
2026-06-30 14:41:16 +03:00
Red Bear OS 181a36a4e4 base: add _TTS/_WAK AML hooks + opt-in DMAR init with hard cap
Phase E of the ACPI fork-sync plan. Two changes:

1. New methods on AcpiContext (Linux 7.1 best practices):

   - transition_to_s_state(state): evaluates _TTS(state) AML method.
     Mirrors Linux 7.1 acpi_sleep_tts_switch (drivers/acpi/sleep.c:36).
     Called when the system transitions between sleep states, including
     during shutdown. Failure is non-fatal: _TTS is optional per ACPI
     spec.

   - wake_from_s_state(state): evaluates _WAK(state) AML method.
     Mirrors Linux 7.1 acpi_sleep_finish_wake (drivers/acpi/sleep.c).
     Called by userspace on resume from a sleep state. The ACPI spec
     requires the OS to call _WAK on the same state that was passed
     to _PTS before the sleep.

   - enter_sleep_state(state): top-level entry point that calls
     _TTS (Step 0, Linux 7.1) then set_global_s_state (Steps 1-5,
     Phase D). This is the public API that future kernel S3/S4 paths
     should use.

2. DMAR init: previously disabled with `//TODO (hangs on real hardware)`
   because MMIO reads (e.g. gl_sts.read()) on some real hardware block
   or spin forever. Phase E.4 fix:

   - Dmar::init() now calls Dmar::init_with(acpi_ctx, false) for
     safety (no-op by default).
   - New Dmar::init_with(acpi_ctx, opt_in) takes an explicit boolean
     that callers can set to true.
   - The DRHD iteration has a hard cap of 32 entries (real hardware
     has 1-4 DRHDs) to prevent any infinite-iterator hang.
   - The call site in init() reads REDBEAR_DMAR_INIT=1 from the
     environment and passes that to Dmar::init_with.

   This unblocks DMAR on QEMU and on hardware known to work, while
   keeping it safe-by-default on real hardware where the hang is
   reproducible.

Verified by: CI=1 ./local/scripts/build-redbear.sh redbear-mini
succeeded with exit 0. ISO at build/x86_64/redbear-mini.iso
(512 MB) at 2026-06-30 07:11. QEMU boot reaches Red Bear login:
prompt cleanly with no errors. Both @inputd:661 and @ps2d:96
startup logs visible. redbear-sessiond working with login1
registered on D-Bus.
2026-06-30 07:14:00 +03:00
Red Bear OS 8140a2cd27 base: refactor set_global_s_state to follow Linux 7.1 acpi_enter_sleep_state
Phase D of the ACPI fork-sync plan.

Refactors acpi.rs set_global_s_state to follow the canonical Linux 7.1
pattern from drivers/acpi/acpica/hwxfsleep.c:283 (acpi_enter_sleep_state):

  1. Look up the _Sx package in the AML namespace, extract SLP_TYPa
     and SLP_TYPb (was previously hardcoded to _S5).
  2. Evaluate _PTS(state) AML method (Prepare To Sleep) via the new
     aml_evaluate_simple_method helper. Failure is non-fatal: _PTS is
     optional per ACPI spec.
  3. Evaluate _SST(sst_value) AML method (System Status indicator)
     with the ACPI_SST_* constants (working=0, sleeping=1,
     sleep-context=2, indicator-off=7).
  4. Write SLP_EN|SLP_TYPa to PM1a, SLP_EN|SLP_TYPb to PM1b.
  5. Spin (machine should power off before this returns).

Also adds:

- Generic aml_evaluate_simple_method(path, arg) helper that
  mirrors Linux 7.1 acpi_execute_simple_method (drivers/acpi/utils.c).
  Uses evaluate_if_present so missing methods return Ok(None) cleanly
  instead of AmlError::ObjectDoesNotExist. Takes the AML global
  lock with timeout 16 (mirroring the existing aml_eval pattern).

- Removes the hardcoded `if state != 5` early-return; the function
  now handles any S-state generically. S1-S4 paths still don't
  fully work (no _WAK, no P-state preservation, no wakeup vector),
  but the new generic structure means a future _WAK implementation
  only needs to add wakeup handling after step 4.

- Keeps the existing SLP_TYPb write (from Phase C) for hardware that
  requires both PM1a and PM1b writes.

Combined with the existing scheme.rs change (thermal_zones() and
power_adapters() methods that enumerate _TZ and PowerResource
entries from the AML namespace), this completes the major ACPI
subsystem gaps identified by the 2026-06-30 assessment:

  - Gap #1 RSDP validation (closed in Phase A)
  - Gap #3 AML mutex stubs (closed in Phase C)
  - Gap #4 set_global_s_state genericity + _PTS + _SST (closed here)
  - Gap #5 SLP_TYPb write (closed in Phase C)
  - Gap #6 parse_lnk_irc range validation (closed in Phase C)
  - Gap #7 thermal/power enumeration (closed in Phase C)
  - Gap #8 AcpiScheme fevent (closed in Phase A)

Remaining open:
  - Gap #2 DMAR init (needs real-hardware investigation)
  - Gap #4b _WAK infrastructure for real S1-S4 suspend (the
    generic Sx scaffolding is now in place; _WAK + wakeup vector
    + P-state preservation are still TBD)

Verified by: CI=1 ./local/scripts/build-redbear.sh redbear-mini
succeeded with exit 0. ISO at build/x86_64/redbear-mini.iso
(512 MB) at 2026-06-30 06:28. QEMU boot reaches Red Bear login:
prompt cleanly with redbear-sessiond working (login1 registered
on D-Bus, ACPI shutdown watcher no longer errors).
2026-06-30 06:32:09 +03:00