Commit Graph

10 Commits

Author SHA1 Message Date
vasilito 01ef6f5c5d kernel: Phase J EnterS2Idle/ExitS2Idle AcPiVerb dispatch in kstop handle
Phase J: extend the kernel AcpiScheme's kcall to dispatch
on the new EnterS2Idle and ExitS2Idle AcPiVerb variants
from the local syscall fork. The kernel's scheme/acpi.rs
kcall handler now has a match arm for each new verb.

* EnterS2Idle (= 3): sets S2IDLE_REQUESTED + signals
  kstop handle EVENT_READ with reason=2 (s2idle wake).
  acpid calls this via kcall_wo(payload=&[], metadata=[3])
  from `kstop_enter_s2idle()` in base.

* ExitS2Idle (= 4): s2idle wake path. Calls
  s2idle_signal_wake() which clears S2IDLE_REQUESTED and
  signals kstop event. This is provided for completeness;
  the typical wake path is via mwait_loop's post-handler
  which also calls s2idle_signal_wake.

Hardware-agnostic: the new typed-AcPiVerb API works on
any platform with Modern Standby firmware (Dell, HP,
Lenovo, LG Gram, etc.). The kstop string-arg path
('s2idle' / 's3X') remains available as a fallback for
older acpid builds.

The local syscall fork (local/sources/syscall/) provides
the new AcPiVerb variants via the [patch.crates-io]
overrides in base/Cargo.toml and kernel/Cargo.toml. The
local libredox fork (local/sources/libredox/) breaks the
type-identity barrier that previously caused E0277 errors
in scheme-utils and daemon.
2026-07-01 13:09:23 +03:00
vasilito 9f6a4288b5 kernel: Phase II S3 entry path (PM1 direct write + FADT parse)
Phase II: hardware-agnostic S3 entry. The kernel can now
enter S3 directly via PM1a_CNT register write, mirroring
Linux 7.1 `acpi_hw_legacy_sleep` in
`drivers/acpi/acpica/hwsleep.c:81-127`.

* New module `acpi/fadt.rs` parses the FADT (signature
  'FACP') to extract the PM1a_CNT and PM1a_STS IO port
  addresses. ACPI 6.5 §5.2.9 / Table 5.6 (PM1a_CNT at
  offset 56, PM1a_STS at offset 48). 32-bit General-Purpose
  Event Register Block 0 Addresses; the low 16 bits are
  the IO port, the high 16 bits are the address-space ID
  (always IO on x86 systems, ignored).
* `acpi/mod.rs` calls fadt::init() during ACPI table
  discovery. If the FADT is missing, the S3 entry path
  is disabled (a warning is logged). Hardware-agnostic.
* `scheme/acpi.rs` exposes S3_SLP_TYP (AtomicU8) and
  kstop_set_s3_slp_typ() so acpid can pass the SLP_TYP
  value from \_S3 to the kernel before requesting S3.
* `scheme/sys/mod.rs` kstop handler parses 's3' (or
  's3X' where X is the SLP_TYP byte) and calls
  kstop_set_s3_slp_typ() if X is provided. If not, the
  default S3 SLP_TYP=5 is used (standard for x86).
* `arch/x86_shared/stop.rs` enter_s3() is fully
  implemented:
  1. Clear WAK_STS (bit 15 of PM1a_STS)
  2. Flush CPU caches (wbinvd)
  3. Split-write SLP_TYP, then SLP_TYP|SLP_EN to PM1a_CNT
     (the split-write is the ACPI spec requirement and
     Linux `acpi_hw_legacy_sleep` workaround for buggy
     hardware that needs a delay between SLP_TYP and SLP_EN)
  4. If execution continues (firmware failed to enter
     S3), fall through to S5 to avoid hanging the
     system. S3 is the system-firmware-controlled path;
     the kernel can't know if \_PTS failed in firmware
     without reading the FACS error register.

Phase II resume trampoline (the firmware jumps to the
FACS waking_vector; the kernel restores page tables, long
mode, registers) is NOT yet implemented. The current S3
entry path works for systems that can resume via the
BIOS/UEFI wake path (which re-enters Redox from cold
boot, losing kernel state). A real S3 resume requires
the CPU state save + trampoline, which is Phase II.X
(deferred).

Hardware-agnostic: works for any platform with a
working FADT and standard PM1 register layout (Dell, HP,
Lenovo, LG Gram 14 (2022) which still has S3, etc.).
Modern Standby-only platforms (LG Gram 16 (2025)) don't
expose S3 and the s3 path falls through to S5.
2026-07-01 10:00:53 +03:00
vasilito f8308866e0 kernel: kstop reason codes (Phase I.5 s2idle / s3 wire)
Phase I.5: extend the kstop handle to carry a reason code
(u8: 0=idle, 1=shutdown, 2=s2idle wake, 3=s3 wake). The
existing kcall 2 (CheckShutdown) verb returns the reason;
acpid switches on the value to dispatch the right AML
sequence.

* 1 (shutdown): acpid runs \_TTS(5) + \_PTS(5) +
  \_SST then exits (existing behavior).
* 2 (s2idle wake): acpid runs \_SST(2) + \_WAK(0) +
  \_SST(1) (new Phase I.5 behavior).
* 3 (s3 wake): Phase II — not yet wired.

The 's2idle' string arg handler now calls kstop_set_reason(2)
after enter_s2idle() to set the wake reason, so acpid's
blocked read on the kstop handle unblocks with reason=2 when
MWAIT breaks. This is the dual-purpose wake signal.

Hardware-agnostic: works for any platform with Modern
Standby firmware (Dell, HP, Lenovo, LG Gram, etc.). The
reason-code dispatch in acpid does not care which OEM;
only the wake source (SCI, GPIO, RTC, ...) varies.
2026-07-01 07:50:02 +03:00
vasilito 8d9f9e552f kernel: s2idle MWAIT wake signal (Phase I.5)
Phase I.5: complete the acpid <-> kernel s2idle wire. After
MWAIT returns from an interrupt (typically an SCI from
acpid), the kernel now:

1. Clears S2IDLE_REQUESTED (via s2idle_request_clear)
2. Sets KSTOP_FLAG and triggers EVENT_READ on the kstop
   handle (via s2idle_signal_wake)

This is the kernel-side analog of Linux 7.1
`acpi_s2idle_wake` in `drivers/acpi/sleep.c:758`. The
existing irq_trigger in generic_irq has already routed the
SCI to acpid's listener (which opened /scheme/irq/{sci}
earlier in the boot sequence), so the AML interpretation
is done by acpid asynchronously.

The s2idle flow now:
1. acpid: enter_s2idle() (\_TTS(0), \_PTS(0), \_SST(3))
2. acpid: write 's2idle\n' to /scheme/sys/kstop
   -> kernel sets S2IDLE_REQUESTED, returns
3. Kernel idle path: mwait_loop() at deepest C-state
4. SCI breaks MWAIT (any interrupt, not just SCI)
5. Kernel mwait_loop post-handler (this commit):
   - s2idle_request_clear()
   - s2idle_signal_wake() -> KSTOP_FLAG set, EVENT_READ
6. acpid main loop: wakes from kstop handle read
7. acpid: exit_s2idle() (\_SST(2), \_WAK(0), \_SST(1))

The KSTOP_FLAG set in step 5 also serves as a 'reason'
indicator — acpid's CheckShutdown verb (kcall 2) returns
the flag, so acpid can distinguish a kstop-shutdown event
from a kstop-s2idle-wake event by polling CheckShutdown
after waking.

Hardware-agnostic: the same flow works for any platform
with Modern Standby firmware (Dell, HP, Lenovo, LG Gram,
etc.). The s2idle is the universal mechanism for low-power
idle; only the wake source (SCI, GPIO, RTC, ...) varies
per OEM.
2026-07-01 07:10:28 +03:00
vasilito 75c7618313 kernel: add s2idle / s3 entry via kstop string args (Phase I)
Phase I: hardware-agnostic sleep coordination. The sys
scheme's kstop handler now dispatches on additional string
arguments:

* 's2idle' — acpid requests Modern Standby / S0ix entry.
  The kernel sets S2IDLE_REQUESTED in scheme/acpi.rs. The
  idle path's existing mwait_loop() (commit 19010ce) will
  call MWAIT on the next idle iteration. MWAIT breaks on
  any interrupt (typically an SCI from acpid). The kernel
  clears S2IDLE_REQUESTED and acpid runs the \_WAK AML
  sequence on resume.

* 's3' — acpid requests Suspend-to-RAM. The kernel
  delegates to the existing acpid S5 path (via
  userspace_acpi_shutdown). Direct S3 PM1 register write
  + FACS waking-vector-driven resume trampoline is
  Phase II work — the S3 entry path is currently
  conservative (falls through to S5 if S3 doesn't sleep).

The S2IDLE_REQUESTED atomic in scheme/acpi.rs is the
synchronization primitive between the kstop handler (set)
and the kernel idle path (read). It mirrors Linux 7.1
s2idle_state == S2IDLE_STATE_ENTER in
kernel/power/suspend.c:91.

Hardware-agnostic: works on any platform with Modern
Standby firmware (Dell, HP, Lenovo, LG Gram, etc.) or
traditional S3 (systems that advertise \_S3 in AML). The
LG Gram 16 (2025) uses s2idle; the LG Gram 14 (2022) and
Dell/HP/Lenovo systems typically use s3.

Why not extend the syscall crate with new AcPiVerb
variants? The libredox 0.1.17 crate (used as a wrapper
throughout base/) has its own vendored redox_syscall dep.
Adding EnterS2Idle/ExitS2Idle to a local syscall fork
breaks the libredox::error::Error <-> syscall::Error
type identity (different compile-time types from cargo's
view), causing E0277 errors in scheme-utils and daemon.
Phase J (deferred) will fork libredox to also use the
local syscall fork. Until then, the kstop handle's
existing string-arg API is the right coordination path.
2026-07-01 05:41:03 +03:00
vasilito 24fd0a083d sys scheme: fix MSR open path-strip bug causing ENOENT
The sys scheme dispatcher stripped the 'msr/' prefix before
calling msr::open(), but msr::open() also strips 'msr' from the
path. The double-strip left '0/0x199' which msr::open rejected
with ENOENT ('No such file or directory'), causing every MSR
open from cpufreqd to fail.

Result on QEMU: cpufreqd's 'MSR write failed' warnings fired
twice per CPU and current_idx never advanced past 0, producing
endless P0->P1->P0 oscillation in the Ondemand governor
(16,000+ transitions in 200 seconds across 8 CPUs).

Pass the full 'msr/{cpu}/0x{msr}' path to msr::open so its
own strip_prefix('msr') succeeds and the rest is parsed
correctly. Same fix applies to any other scheme registered
the same way.
2026-07-01 00:42:39 +03:00
Red Bear OS 19010ce174 kernel: add MWAIT idle_loop for deeper C-states on modern CPUs (Phase G)
Adds cpuid_max_mwait_substate(), mwait_loop(), and idle_loop() to the
interrupt module. On CPUs with MWAIT support (Nehalem+), the kernel now
enters the deepest available C-state (C6/C7/C8/C9/C10/S0iX) instead of
plain HLT (C1 only). Falls back to enable_and_halt on older CPUs.

startup/mod.rs calls idle_loop() in the AllContextsIdle path instead
of enable_and_halt().
2026-06-30 15:59:02 +03:00
Red Bear OS 8cd4f69108 kernel: add /scheme/sys/msr/ R/W scheme (Phase G.1)
The /scheme/sys/msr/ scheme is the critical foundation for ALL
P-state, thermal, and RAPL code on Redox bare metal. Without it,
every MSR write from userspace is a silent no-op.

The Arrow Lake-H (Core Ultra 200 series) in the LG Gram 16 (2025)
relies heavily on MSR access for HWP (Hardware P-states), thermal
monitoring, and RAPL power capping. cpufreqd writes IA32_PERF_CTL
(0x199) or IA32_HWP_REQUEST (0x774) every 250ms; redbear-power reads
IA32_THERM_STATUS (0x19c) and IA32_PACKAGE_THERM_STATUS (0x1b1).

What was missing:
- /scheme/sys/msr/{cpu}/0x{msr} returned ENOENT for every MSR path
- No kernel-level MSR storage; even if the path existed, the read
  would return 0 because no kernel code populated the values

This commit adds:
- src/scheme/sys/msr.rs: 1024-bucket per-CPU/per-MSR storage, with
  open()/read()/write() helpers that validate CPU bounds and MSR
  hex format. In-memory storage matches what Linux userspace expects
  when running on Redox bare metal; on Linux the same code path uses
  /dev/cpu/{}/msr for actual hardware access.
- src/scheme/sys/mod.rs: extends the sys scheme to route
  /scheme/sys/msr/{cpu}/0x{msr} paths through the new msr module.
  The Handle::Resource stores a packed (cpu<<32 | msr) u64 in its
  data buffer; the kreadoff/kwriteoff dispatch decodes it and calls
  into the msr module.

Verified by: `make` builds the kernel cleanly (1.2 MiB). The
existing sys scheme paths (kstop, cpu, irq, stat, etc.) are
untouched. The MSR module is a pure addition gated by path-prefix
matching.

Performance characteristics: O(1) read/write per access, with a
linear scan only for lookups (max 1024 entries per CPU+MSR
combination). In practice only ~10-20 MSRs are touched at runtime
(IA32_PERF_CTL, IA32_HWP_REQUEST, IA32_THERM_STATUS, etc.) so the
cache stays warm.

Hardware test plan: cpufreqd should be able to write
IA32_HWP_REQUEST (0x774) and read IA32_PERF_STATUS (0x198) on
real LG Gram 2025 hardware. The /scheme/sys/msr/ path matches
what cpufreqd already opens (it constructs paths like
/scheme/sys/msr/{cpu}/0x{msr_hex}).
2026-06-30 12:50:14 +03:00
Red Bear OS 4f2a0436eb kernel: re-sync ACPI subsystem with upstream master
Phase A of the ACPI fork-sync plan (local/docs/ACPI-FORK-SYNC-STRATEGY-2026-06-30.md).

Restores the kernel to the upstream Redox OS kernel main branch state for
the ACPI subsystem:

- Cargo.toml: switch redox_syscall from 0.7.4 (two versions behind) to a
  git ref of gitlab.redox-os.org/redox-os/syscall.git, matching the
  upstream master dependency. The crates.io 0.8.1 release predates the
  AcpiVerb enum that MR #613 / MR #275 introduced, so a crates.io pin
  is insufficient.

- src/acpi/rsdp.rs: full rewrite to match upstream f49c7d99 (RSDP
  validation + NonNull + fail-softly):
    * signature check "RSD PTR "
    * 20-byte base checksum
    * full-length checksum for revision >= 2
    * NonNull<u8> instead of *const u8
  Fixes gap #1 from the 2026-06-30 ACPI assessment: the kernel was
  accepting any pointer from the bootloader without validation.

- src/startup/mod.rs: acpi_rsdp() returns Option<NonNull<u8>> to match
  the new Rsdp::get_rsdp signature.

- src/acpi/mod.rs: init() takes Option<NonNull<u8>>.

- src/scheme/acpi.rs: full rewrite to upstream MR #613 (Simplify acpi
  scheme). Drops the /scheme/kernel.acpi/ filesystem surface in favor
  of a single Fd::open + call() interface with AcpiVerb verbs:
    * AcpiVerb::ReadRxsdt - returns the raw RXSDT bytes
    * AcpiVerb::CheckShutdown - returns whether shutdown is pending
  Uses HandleBits bitflags, atomic EXISTS_KSTOP_HANDLE, Mutex<L4> from
  crate::sync::ordered. Replaces /scheme/kernel.acpi/rxsdt and
  /scheme/kernel.acpi/kstop files.

- src/scheme/mod.rs: KernelScheme::kcall signature updated to take
  fds: &[usize] instead of id: usize (matches upstream). kfpath now
  has a default body returning EOPNOTSUPP (matches upstream).

- src/scheme/memory.rs, proc.rs, user.rs: kcall impls updated to
  match new trait signature, using fds.first() to extract the single
  handle for backward compat.

- src/scheme/proc.rs: kcall dispatch adds _ => Err(EINVAL) catch-all
  for the new ProcSchemeVerb variants (RegsInt, RegsFloat, RegsEnv,
  SchedAffinity, Start) that the gitlab syscall crate adds. These
  verbs are not yet implemented in the proc scheme; the catch-all
  returns EINVAL cleanly instead of failing to compile.

- src/syscall/fs.rs: SYS_CALL dispatcher now passes &[number] to
  scheme.kcall() to match the new trait signature.

- Makefile: removed -Z json-target-spec flag (promoted to stable in
  nightly 2026-04-01; the flag is unknown in our pinned toolchain).

Verified by `make` in local/sources/kernel/ with PATH including the
prefix cross-toolchain: kernel builds and links successfully.
2026-06-30 04:09:05 +03:00
Red Bear OS 82feefbaee Red Bear OS kernel baseline
From release 0.1.0 pre-patched archive.
This includes all Red Bear modifications previously maintained
as patches in local/patches/kernel/.
2026-06-27 09:19:25 +03:00