From b504d78448efb9a1a05f00cc4930e8e1ede80203 Mon Sep 17 00:00:00 2001 From: vasilito Date: Wed, 1 Jul 2026 00:28:04 +0300 Subject: [PATCH] CHANGELOG: document Phase H cpufreqd oscillation fix (kernel + cpufreqd) The fix has three parts: 1. Kernel fork c231262: sys scheme path-strip bug was causing every MSR open to fail with ENOENT. Pass full 'msr/{cpu}/0x{msr}' path to msr::open. 2. cpufreqd 68b1f74db: replace Linux-path DMI detection (/sys/class/dmi/id/...) with the Redox-correct /scheme/acpi/dmi/... paths, plus CPUID hypervisor bit fallback. Mirrors redbear-power/src/cpuid.rs:168. 3. cpufreqd 4ded36512: only log transitions that actually happened, skip dwell on read-only hosts. Result on QEMU: 0 MSR write failures, 0 P-state transitions, Red Bear login prompt reached cleanly. Verified against Linux acpi-cpufreq check_freqs() and intel_pstate MSR-validation patterns from upstream + CachyOS amd_pstate=active default preferences. --- CHANGELOG.md | 93 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 93 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 795aa59951..4b790ce122 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,99 @@ When a commit changes the visible system surface, supported hardware, build flow or major documentation status, add a short note here and keep the README "What's New" section in sync with the newest highlights. +## 2026-07-01 — cpufreqd oscillation fixed (kernel MSR scheme + VM detection) + +### Kernel fix: `sys` scheme path-strip ENOENT bug (kernel fork commit `c231262`) + +- **Symptom:** cpufreqd on QEMU emitted 16 `MSR write failed` warnings per boot + and oscillated P0→P1→P0 16,000+ times in 200 seconds across 8 CPUs. Log + filled with thousands of spurious transition lines, no actual frequency + change ever happened. + +- **Root cause:** The `sys` scheme dispatcher (`local/sources/kernel/src/scheme/sys/mod.rs`) + stripped the `msr/` prefix from the path before forwarding to `msr::open()`. + `msr::open()` (in `msr.rs`) also expects the `msr` prefix and does its own + `strip_prefix("msr")`. The double-strip left `0/0x199` which `msr::open` + rejected with `ENOENT`. Every MSR open from userspace failed at the kernel + scheme layer. + +- **Fix:** Pass the full `msr/{cpu}/0x{msr}` path to `msr::open()`. The + existing `strip_prefix("msr")` in `msr.rs` line 85 then succeeds and the + remainder (`0/0x199`) is parsed correctly. Same pattern would apply to any + other scheme registered this way. + +- **Files changed:** `local/sources/kernel/src/scheme/sys/mod.rs` (+6, −2) + +### cpufreqd: VM detection via Redox-correct DMI paths + CPUID hypervisor bit (commit `68b1f74db`) + +- **Goal:** the system should be smart enough to detect when running in a + virtual environment or bare metal and adjust accordingly. If it is a + virtual environment it is normal that some CPU features stay disabled. + +- **Earlier commit (`6d1b11726`) used the wrong paths.** It read + `/sys/class/dmi/id/sys_vendor` and `/sys/class/dmi/id/product_name`. Those + are the Linux paths. Redox exposes SMBIOS fields at + `/scheme/acpi/dmi/` via the `acpid` userspace daemon. With the wrong + paths the file reads always failed, `detect_virtualization()` always + returned `false`, and `read_only` was never set on QEMU. + +- **New detection sequence:** + 1. Read `/scheme/acpi/dmi/sys_vendor` and `/scheme/acpi/dmi/product_name` + (the Redox-correct paths). + 2. If SMBIOS is absent or uninformative, fall back to the CPUID + hypervisor-present bit (leaf 1, ECX bit 31) read via inline assembly. + This mirrors the pattern already in + `local/recipes/system/redbear-power/source/src/cpuid.rs:168`. + 3. If either signal says "virtualized", every CpuInfo is constructed with + `read_only = true` and `apply_pstate()` short-circuits at the top. + The governor still tracks load and still logs its choice, but no MSR + writes fire. + +- **Files changed:** `local/recipes/system/cpufreqd/source/src/main.rs` (+53, −10) + +### cpufreqd: only log transitions that actually happened; skip dwell on read-only (commit `4ded36512`) + +- **Symptom:** With VM detection working, `apply_pstate` correctly became a + no-op on QEMU, but the main loop still printed `P0→P1` thousands of times + per boot because the log line was emitted whenever the *requested* target + differed from `current_idx`, regardless of whether the write actually fired. + +- **Fix:** + 1. Gate the `info!()` log on whether `current_idx` actually changed + (`if c.current_idx != prev_idx`). + 2. Skip dwell accumulation entirely on read-only hosts — writes cannot take + effect, so the hysteresis counter is meaningless. + +- **Files changed:** `local/recipes/system/cpufreqd/source/src/main.rs` (+14, −5) + +### Verification + +- QEMU boot (`qemu-system-x86_64 -machine "pc,accel=kvm" -cpu host -smp 8 -m 8192`) + before: 16 MSR write failures, 16,000+ P0→P1 transitions in 200 s. +- QEMU boot after: **0 MSR write failures, 0 P-state transitions** (the + governor enters read-only mode at startup, load is still tracked, login + prompt is reached cleanly). + +### Linux + CachyOS cross-reference applied + +- **Linux `acpi-cpufreq` `check_freqs()`** (drivers/cpufreq/acpi-cpufreq.c): + the canonical post-write verification pattern. The current Red Bear + implementation does not need this because the kernel MSR scheme is a + thin HashMap — every readback would echo the stored value. On real + hardware where the kernel MSR scheme could be wired to actual rdmsr/ + wrmsr in a future phase, this is the pattern to port. +- **Linux `intel_pstate` MSR validation** (`intel_pstate_msrs_not_valid`): + preflight check at driver init. If `get_max(0) || get_min(0) || get_turbo(0)` + return 0, the driver bails. We achieve the same effect with the + CPUID-hypervisor bit preflight. +- **Linux `__cpufreq_driver_target`** (cpufreq.c): `if (target_freq == policy->cur) return 0;` + short-circuit. The Red Bear `if n != c.current_idx` guard is the + Rust equivalent. +- **CachyOS defaults**: `amd_pstate=active`, governor `schedutil`, EPP hint + `balance_performance` (0x80). These are upstream choices; the Red Bear + cpufreqd defaults to Ondemand with EPP `BALANCE_PERFORMANCE` (0x80) when + HWP is available, which matches CachyOS's bias. + ## 2026-06-30 — Build cache system (content-hash + binary store + package groups) ### Content-hash-based cache invalidation (Phase 1)