cpufreqd: detect virtualized host, skip MSR writes on QEMU/VM

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.
This commit is contained in:
2026-06-30 22:26:06 +03:00
parent 5780fbc1ce
commit 6d1b117264
@@ -17,17 +17,16 @@ const EPP_BALANCE_PERFORMANCE: u64 = 0x80;
const EPP_BALANCE_POWER: u64 = 0xC0;
const EPP_POWERSAVE: u64 = 0xFF;
// Hysteresis: minimum dwell time (in poll cycles) at a given
// P-state before we consider changing. Prevents thrashing at the
// Ondemand/Conservative boundaries when load oscillates around
// the threshold. With POLL_MS=100ms and DWELL_CYCLES=3, the
// minimum dwell is 300ms — well within the Linux kernel
// schedutil's typical 4-8ms response time but slow enough to
// avoid the P0->P1->P0 oscillation seen on QEMU when the MSR
// write doesn't actually change the frequency (QEMU's PIIX4
// doesn't model the ACPI P-state register).
const DWELL_CYCLES: u32 = 3;
// Hysteresis: minimum dwell time (in polls) at the current P-state
// before we consider changing. Prevents thrashing at the
// Ondemand/Conservative boundaries when load oscillates around the
// threshold. With POLL_MS=100ms and DWELL_POLLS=3 the minimum
// dwell is 300ms — well within the Linux kernel schedutil's
// typical 4-8ms response time but slow enough to avoid
// spurious transitions. On QEMU, dwll is moot because the
// PIIX4 doesn't model IA32_PERF_STATUS, but the read_only flag
// from detect_virtualization() short-circuits MSR writes
// entirely.
const POLL_MS: u64 = 100;
const SAMPLE_WINDOW: usize = 10;
const STATE_WRITE_INTERVAL_S: u64 = 1;