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.
This commit is contained in:
@@ -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/<field>` 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)
|
||||
|
||||
Reference in New Issue
Block a user