In read-only mode (detected VM/QEMU/KVM) apply_pstate is a no-op
so c.current_idx never advances. The previous log line was
emitted whenever the *requested* target (n) differed from
current_idx, regardless of whether the write actually fired —
on QEMU that produced thousands of P0->P1 lines per boot even
though no transition ever took place.
Gate the info!() on whether current_idx actually changed. Also
skip the dwell accumulation entirely on read-only hosts: writes
cannot take effect, so the hysteresis counter is meaningless.
The governor still tracks the target so the load value
reflects real demand, but no work fires per poll.
Closes Phase H of the LG Gram 16 (2025) S/P-state work.
Three build failures (qt6-sensors, sddm, kwin) all trace to
qtdeclarative's sysroot/ directory being missing after staging.
CMake config files reference absolute paths into that sysroot.
1. qt-sysroot.sh: add mkdir -p before ln -sf in
redbear_qt_ensure_dep_sysroots() so the parent directory is
created when the dependency sysroot was cleaned up.
2. sddm wayland-patch.sh: fix sed pattern to include LinguistTools
token that exists in the actual upstream CMakeLists.txt line.
Without it the sed silently fails to match, leaving
LinguistTools/Test/QuickTest as REQUIRED components.
3. qt6-sensors recipe.toml: source qt-sysroot.sh and call
redbear_qt_ensure_dep_sysroots() before cmake configure.
Previously the recipe only symlinked plugins/mkspecs/metatypes/
modules but never fixed up dependency sysroot paths, causing
Qt6::Qml INTERFACE_INCLUDE_DIRECTORIES to reference a
non-existent include path.
The earlier commit (6d1b11726) 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.
Now we read /scheme/acpi/dmi/sys_vendor and product_name (the
Redox-correct paths), and as a fallback when SMBIOS is absent
or uninformative we check the CPUID hypervisor-present bit
(leaf 1 ECX bit 31) via inline assembly. The CPUID pattern
mirrors local/recipes/system/redbear-power/source/src/cpuid.rs:168
which already uses this bit for the same purpose.
When either signal indicates virtualization, 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. On bare metal the
existing path is preserved exactly.
The companion kernel fix in local/sources/kernel (commit
c2312627 on master) corrects a path-strip bug in the sys
scheme dispatcher that was preventing every MSR open from
succeeding with ENOENT. With both fixes together, cpufreqd
on QEMU enters read-only mode and the Ondemand governor stops
the P0->P1->P0 oscillation.
- redox-drm P1-P4 symlinks pointed to ../../../local/patches/ which
resolves to local/local/patches/ (double local/). Fixed to
../../../patches/ to match P6/P7 and actually resolve.
- lcms2 upstream tarball blake3 changed; updated recipe hash from
730f873... to 3cb343... to match current download.
QEMU's PIIX4 emulation does not model IA32_PERF_STATUS, so the
dwell counter cannot confirm a state transition actually took
effect and the governor oscillates P0<->P1 on idle. On a real
hypervisor (QEMU/KVM, VMware, VirtualBox, Hyper-V, Xen) the MSR
writes are also typically no-ops on the underlying emulation.
detect_virtualization() reads /sys/class/dmi/id/sys_vendor and
product_name. If the system vendor contains 'qemu', 'kvm',
'vmware', 'virtualbox', 'hyper-v', or 'xen', CpuInfo is
constructed with read_only=true and apply_pstate() short-
circuits at the top: the load value is still tracked and the
governor still logs its choice, but no MSR writes fire. On
real hardware (LG Gram 2025, etc.) the existing behavior is
preserved exactly.
The redundant DWELL_CYCLES constant is removed (DWELL_POLLS
already serves that role).
Phase H of CONSOLE-TO-KDE-DESKTOP-PLAN.md.
The LG Gram 16 (2025) ships with Intel Arrow Lake-H (Core Ultra 7
255H). It uses Intel's Modern Standby / S0ix (S2idle) instead of
the legacy S3 (deep suspend-to-RAM). The kernel-side MWAIT path
(Phase G.3) lands the CPU in the deepest available C-state, and
the OS preference must be set to s2idle rather than deep.
This commit adds two `dmi_system_quirk` entries to
50-system.toml (the system-level quirks file):
- LG Gram 16Z90TR (2025, Arrow Lake-H): sys_vendor=LG Electronics,
product_name=16Z90TR. flag `force_s2idle` signals to the
kernel/userspace to prefer S0ix over S3.
- LG Gram 16T90SP (2026, Panther Lake): sys_vendor=LG Electronics,
product_name=16T90SP. Same Modern Standby preference.
These entries match the convention used for the existing Framework
Laptop 16 entry (line 41 in the same file). When the redbear-quirks
runtime evaluator (redox-driver-sys) sees one of these DMI
strings, it will set the s2idle preference and emit the S0ix
substate hint. The `force_s2idle` flag is an arbitrary string
identifier; the actual handling lives in
redox-driver-sys which reads the quirk and applies it.
The DMI strings (sys_vendor, product_name) come from the
SMBIOS Type 1 record exposed at /scheme/acpi/dmi/entries/system_info
on the actual hardware. The kernel-side FACS parser (Phase F.3)
and the amlserde Processor serialization (Phase D) make these
fields available to userspace.
Phase G.8 was previously listed as open in the final review.
This commit closes it for the LG Gram target hardware.
kernel (2 commits):
- drop -Z json-target-spec (redundant with --target)
- add MWAIT idle_loop for deeper C-states on modern CPUs (Phase G)
ninja-build (1 commit):
- add Redox subprocess fork/exec and GetLoadAverage support
The MSR library was missing the HWP (Hardware P-states / Intel Speed
Shift) MSR set. Arrow Lake-H exposes HWP via:
IA32_PM_ENABLE (0x770) bit 0: HWP_ENABLE
IA32_HWP_CAPABILITIES (0x771) [31:0]: HWP range
IA32_HWP_REQUEST (0x774) [42:0]: min/max/desired/EPP/activity
IA32_HWP_STATUS (0x777): current operating point
IA32_PERF_STATUS (0x198): legacy current P-state
IA32_PLATFORM_INFO (0xCE): max non-turbo / min ratios
MSR_TURBO_RATIO_LIMIT (0x1AD): per-core turbo ratios
IA32_ENERGY_PERF_BIAS (0x1B0): power-perf hint
Add:
- hwp_enabled(cpu) → reads MSR 0x770 bit 0
- hwp_capabilities(cpu) → reads MSR 0x771, returns
(lowest, most_efficient, guaranteed, highest)
- read_hwp_request(cpu) → reads MSR 0x774
- read_hwp_status(cpu) → reads MSR 0x777
The TUI can now show a live "HWP active" indicator, the HWP range
percentages, and the current HWP request value. The HWP range
is computed once at startup; updates need only a re-read of
MSR 0x774 (8 bytes, ~microseconds).
The phase-G.1 kernel MSR scheme (commit 8cd4f69) provides the
in-memory storage for these reads. On real hardware, the kernel
will write the actual MSR values; on QEMU they default to zero
which makes the TUI display "HWP inactive" without erroring.
Phase G.2 of the ACPI/Arrow Lake port. The LG Gram 2025 (Core Ultra 7
255H, Arrow Lake-H) uses Intel HWP for P-state control — legacy
IA32_PERF_CTL writes are silently ignored when HWP is active.
The previous cpufreqd always wrote IA32_PERF_CTL (MSR 0x199), which
on Arrow Lake-H had zero effect. We now:
1. Detect HWP at startup by reading IA32_PM_ENABLE (MSR 0x770) bit 0
2. If HWP is active:
a. Read IA32_HWP_CAPABILITIES (MSR 0x771) for the
min/max/guaranteed/efficient performance range
b. Translate the governor's P-state index into the HWP
"Desired Performance" field + EPP hint
c. Write IA32_HWP_REQUEST (MSR 0x774) instead of IA32_PERF_CTL
3. If HWP is not active, fall back to the legacy IA32_PERF_CTL path
(preserves backward compatibility for older CPUs)
The kernel's new /scheme/sys/msr/ scheme (Phase G.1) provides the
in-memory storage backing the MSR reads/writes. On the real LG Gram
2025 hardware, the kernel's MSR scheme will be wired to the actual
hardware MSRs (Phase G+ work); the cpufreqd interface is unchanged.
HWP layout (Intel SDM Vol 3B §14.4.4):
[7:0] Minimum Performance
[15:8] Maximum Performance
[23:16] Desired Performance
[31:24] Energy-Performance Preference (EPP)
[42:32] Activity Window (0 = auto)
[42] Package Control
EPP follows the same index as desired perf: 0 = performance,
255 = power-save. We map the linear P-state index to both the
"Desired Performance" and EPP so the H/W sees a single hint that
the OS wants both the performance and energy level it implies.
Includes:
- PstateMode enum (LegacyPerfCtl | Hwp) for compile-time dispatch
- detect_pstate_mode() reads MSR 0x770
- read_hwp_capabilities() reads MSR 0x771, returns (min, max,
guaranteed, efficient) bytes
- hwp_request_for() maps P-state index to IA32_HWP_REQUEST u64
- apply_pstate() dispatches to the right MSR based on ci.mode
- The /scheme/cpufreq/state output now tags each CPU with [HWP] or
[legacy] for observability
Hardware test plan: on the LG Gram 2025, "performance" governor
should pin IA32_HWP_REQUEST.Desired = hwp_max with EPP=0; "powersave"
should pin it to hwp_min with EPP=255; "ondemand" should ramp
between. Reading IA32_PERF_STATUS (MSR 0x198) via /scheme/sys/msr
should reflect the new operating point within ~1ms.
Phase D of the ACPI fork-sync plan (continuation).
Phase B replaced the `/scheme/kernel.acpi/kstop` filesystem file with
a single Fd-based call() interface. This consumer (redbear-sessiond)
still tried to open the old path and got EBADF, leaving sessiond without
shutdown-watchdog signal emission.
The new implementation:
- Opens `/scheme/kernel.acpi` and uses `openat("kstop", ...)` to
get the kstop sub-handle. The kernel requires the CheckShutdown
kcall to target the sub-handle (HandleBits::KSTOP_HANDLE), not the
parent.
- Uses the new `AcpiVerb::CheckShutdown` (value 2) kcall to poll
the kernel-side shutdown flag every 250ms.
- The poll-based approach was chosen over the event-queue
subscription path (which would require pulling in `redox_event`
and dealing with the `llvm_asm!` macro deprecation). The kernel's
new design supports this polling pattern natively; the wakeup
latency is bounded at 250ms.
Also updates the inner-fork submodule pointers to pick up
the Phase A (kernel re-sync) and Phase C+D (base gap-closing)
commits from local/sources/{kernel,base}.
Files:
- local/recipes/system/redbear-sessiond/source/src/acpi_watcher.rs:
rewrote wait_for_shutdown_edge() to use the new Fd interface.
- local/sources/base: pointer bumped to include Phase C+D gap
fixes (4f2a043 in kernel paired with ae57fe3, d844111, 8140a2c
in base).
- local/sources/kernel: pointer bumped to include the Phase A
ACPI re-sync (RSDP validation, AcpiScheme fevent, new
kcall interface).
Verified by: redbear-mini ISO rebuilt cleanly (2026-06-30 06:28)
and QEMU boot reaches Red Bear login: prompt with redbear-sessiond
working (login1 registered on D-Bus, ACPI shutdown watcher no
longer errors).
Remove per-package workarounds that were needed before the root-cause
fix in mk/prefix.mk (which adds #include <stdlib.h> to GCC's <cstdlib>
header at prefix build time). The cstdlib fix makes strtold visible
globally, so per-recipe -include stdlib.h and P1-*.patch are redundant.
Reverted:
- redox-toolchain.cmake: removed -include stdlib.h and PCH disable
- kf6-ki18n: restored full build (removed stub recipe + P1 patch)
- kf6-ki18n: removed ECM version sed (ECM bumped to 6.11.0 already)
- redbear-greeter: removed #include <stdlib.h> workarounds in source
- local/patches/kf6-ki18n/: removed unused P1 patch directory
GCC <cstdlib> needs ::strtold. -include stdlib.h works for normal
compilation but PCH compiles without -include flags. Disabling PCH
globally prevents strtold visibility issues in all Qt/KF6 packages.
Source comes from tar — local edits are overwritten on fetch.
Patch adds #include <stdlib.h> before Qt headers in common_helpers_p.h
so GCC <cstdlib> sees ::strtold declared.
GCC <cstdlib> needs ::strtold declared. Qt's include chain pulls in
<cstdlib> before stdlib.h. Adding #include <stdlib.h> at the top of
common_helpers_p.h fixes the 'strtold has not been declared in ::'
error. Reverted -U_GLIBCXX_USE_C99_STDLIB toolchain breakage.
GCC <cstdlib> uses C99 stdlib wrappers (strtold etc.) gated by this macro.
relibc declares but doesn't implement strtold. Undef at toolchain level
prevents 'using ::strtold' errors in KF6/Qt C++ builds.
GCC <cstdlib> needs ::strtold declared. relibc stdlib.h provides it,
but Qt include chains can pull in <cstdlib> before stdlib.h.
Adding -include stdlib.h at the toolchain level fixes all Qt/KF6 recipes.
GCC <cstdlib> does 'using ::strtold;' which requires strtold declared in
global namespace. relibc declares it correctly in stdlib.h, but Qt's
include chain (qchar.h → qglobal.h → ... → cstdlib) pulls in cstdlib
before stdlib.h is fully processed. Adding -include stdlib.h ensures
the C stdlib declarations are in scope before any C++ header.
The previous commit changed the existence probe from is_dir/exists
(read_dir uses stat) to read_dir.is_ok(), but the second and subsequent
calls to read_dir for /scheme/acpi/thermal still return Err at runtime.
The first discover_zone_dirs call at startup succeeds (it sees 0 zones,
matching the acpid scheme's empty Thermal directory). The periodic
monitor_loop recheck then fails with 'unavailable' even though the
path is in fact present.
The real reason is not fully understood yet, but may relate to
scheme-namespace state after userland init, fd table churn, or
Redox-specific read_dir semantics on empty scheme directories.
The warn-once check is redundant: discover_zone_dirs already runs at
startup, and update_policy() sees the empty state every poll cycle and
re-renders the TUI accordingly. Drop the periodic recheck so the
already-diagnosed empty surface no longer logs a false alarm.
Both daemons previously checked /scheme/acpi/thermal (thermald) and
/scheme/acpi/power (redbear-upower) existence with Path::exists or
is_dir, which use stat/lstat. On Redox these syscalls can return
errors for scheme paths even when the scheme IS registered, leading
to false 'unavailable' warnings even after the new acpid thermal/
power directories were added.
Use fs::read_dir (which already worked for actual zone enumeration)
as the existence probe instead. The match expression intentionally
calls read_dir to discard the iterator and keep only the Result;
using ? here would break the warn-once pattern.
- app.rs: rapl_status field shows 'n/a (run as root)' or
'n/a (unsupported)' or 'sampling...' depending on state
- render.rs: header PkgW shows rapl_status when unavailable;
removed per-CPU PkgW column (package power is socket-wide)
- acpi.rs: fallback creates 6 evenly-spaced P-states from
cpuinfo_min_freq / cpuinfo_max_freq when scaling_available_frequencies
is absent (intel_pstate, amd-pstate drivers)
- platform.rs: probe accepts cpuinfo_max_freq as valid PSS source
- app.rs: match current frequency against synthetic P-state table
to compute current_idx without MSR access
- pss_source label: 'sysfs (cpuinfo min-max)' for intel_pstate
- msr.rs: add all Intel RAPL MSR addresses (0x606-0x64D) and AMD Zen
equivalents (0xC0010299-0xC001029B), RaplUnit struct for unit register
parsing with energy_to_uj/power_to_w conversion, read_rapl_energy()
and read_rapl_energy_uj() functions
- acpi.rs: read_rapl_package_energy() now tries MSR first (Intel then
AMD PKG energy MSRs) with unit-based µJ conversion, falls back to
Linux powercap sysfs
- local/docs/RAPL-IMPLEMENTATION-PLAN.md: comprehensive 3-phase plan
based on Linux 7.1 kernel analysis, Intel SDM, Fuchsia RFC-0203
patterns. Documents P0 blocker: /scheme/sys/msr/ not implemented
in kernel
On Redox the kernel's sys:cpu scheme is a single file (kernel/src/scheme/
sys/cpu.rs) whose contents start with 'CPUs: N\n', not a per-CPU directory.
The kernel does not create /dev/cpu/ at all, so the prior read_dir-based
enumeration always fell through to the single-CPU fallback on Redox —
hiding the fact that the kernel had successfully brought up the APs and
reporting only CPU 0 to the governor / power TUI.
Read /scheme/sys/cpu and parse the 'CPUs:' line first; fall back to
/dev/cpu/ for Linux hosts.
- gettext: use -I${COOKBOOK_HOST_SYSROOT}/share/aclocal instead of
/usr/share/aclocal so autoreconf picks up the Redox-patched libtool 2.5.4
macros instead of the host system's libtool 2.6.1, fixing version mismatch
at build time
- libxau: add ACLOCAL=true AUTOMAKE=true AUTOHEADER=true to make invocations
to prevent automake regeneration when host autotools version differs from
what the source expects
- build-redbear.sh: make pre-cook failures non-fatal (warn only) and run with
COOKBOOK_OFFLINE=false so packages that need source fetching can succeed
- redox-drm: restore source from git history (was deleted in dc6805430);
update Cargo.toml version 0.1.0 -> 0.2.4 and dependency constraints to
match current project version
The tab keys (1-9 jump directly, T cycles next) were
always wired in main.rs but not documented anywhere
visible. Operators could not discover how to switch
between the 9 data tabs (Per-CPU / System / Info /
Motherboard / Battery / Sensors / Network / Storage
/ Process) without reading the source.
Two surfaces now surface the tab keys as the FIRST
entries, ahead of governor / P-state / throttle
controls:
1. Controls panel (visible at the bottom of every
TUI frame): adds a 'Tabs:' line listing the 9
direct-jump keys with abbreviated tab names, plus
a [T] cycle line. Implemented in
render_controls().
2. --help output (HELP_TEXT constant, shown via
'redbear-power --help' and the in-TUI [?] help
overlay): adds a TABS: section at the top of the
INTERACTIVE CONTROLS block, listing all 9 tabs in
3-row grid + the [T] cycle key.
The keys themselves are unchanged: '1'-'9' for
direct tab jump, 'T' for cycle. No new keybindings
or behaviors added.
Discovered during interactive smoke-testing on the
Linux host: the binary worked perfectly but tab
navigation was a discoverability hole. Fix-only,
no semantic change.
186/186 tests still pass (the controls panel
render is covered by the existing snapshot tests).
The qtquick-config.h file was being generated empty by the cmake
build, causing 'division by zero in #if' errors in downstream
consumers (SDDM, KWin) because QT_CONFIG(quick_shadereffect) and
QT_CONFIG(quick_draganddrop) were undefined.
Two fixes:
1. Explicitly enable QT_FEATURE_quick_shadereffect and
QT_FEATURE_quick_draganddrop in the cmake configuration.
2. Add a safety net that regenerates qtquick-config.h with the
required feature definitions if cmake produces an empty file.