Reproducing Windows-style PL1 control (skin + CPU) with thermal-conf.xml: full release below the trip causes a PL1 sawtooth
Nessuno ha ancora preso questa issue.
Valutazione
- Difficoltà
- 5/5
- Tempo stimato
- Più di una settimana
- Idoneità per principianti
- 35/100
Direzione di ricerca
Start by reading cthd_zone::add_trip() and the passive-trip activation and deactivation code, including the incremental PID work in #587; the issue says deactivation restores min_state. Compare that behavior with the reported PL1 sawtooth and consider whether a setpoint-style mode should adjust the limit in both directions. Done means the maintainers decide whether to support that behavior and document or implement the chosen approach.
Scritto dal modello di indicizzazione a partire dal testo della issue.
Descrizione
Summary
I'm trying to reproduce on Linux what Windows does on a Surface Book 3: a slow, temperature-driven package PL1 with a CPU target and a skin limit. Without DPTF tables, the obvious tool is thermald with a thermal-conf.xml. I ran three configurations on thermald 2.5.6 and compared them with a small userspace PI controller under the same load. On average thermald can come close. But because a passive trip releases the cooling device completely when the temperature drops below the trip (or below trip − hyst), PL1 saws between the floor and the maximum, and the CPU keeps hitting TjMax. I also hit two configuration pitfalls and a missing PL2 control. Details and data are below. I read the current master, including the incremental PID from #587, and as far as I can tell the release behaviour is the same there.
I'm not a thermal engineer, just someone with a control background trying to get this laptop to behave. Please correct me where I misread the code.
Device and what Windows does
- Surface Book 3 15", i7-1065G7 (Ice Lake). No DPTF/GDDV in the firmware, so
--adaptivehas nothing to work with. - The skin sensor
I_VTS1comes from the Surface EC through thesurface_temphwmon driver. The SB3 node currently has to be registered from outside the kernel registry. That part is a linux-surface topic: https://github.com/linux-surface/kernel/issues/117 - The firmware sets psys to 25/40 W. For all runs below, psys was raised to 60/60 W by a separate script so that only package PL1 limits.
- Windows (Surface SMF driver, no Intel DTT), measured with HWiNFO under the same x265 load:
- The boost starts at PL1/PL2 30/61 W and runs for 0.5–2.5 min at 95–100 °C.
- Then PL1 drops to 21 W.
- After that PL1 ramps down in steps of ~0.5–1 W every 10 s and settles after 5–8 min.
- Steady state is 14–18 W at 75–88 °C.
- The fine steps follow the CPU temperature, with a zero crossing around 75 °C. The skin limit is about 45 °C.
Test
- Same load profile for every run, 47 min in total: full load 5 min, idle 7 min, full load 5 min, idle 5 min, half load 5 min, full load 15 min, idle 5 min.
- Profile performance, full brightness, on AC.
- thermald 2.5.6 (Ubuntu 24.04) ran with
--no-daemon --config-file=… --loglevel=info, without--adaptive.
| PI controller (userspace) | thermald v1 | thermald v2 | thermald v3b | |
|---|---|---|---|---|
| Config | PI on skin (with slope prediction) + I on CPU, min of both, every 10 s; PL2 lowered at TjMax | passive trips: CPU 75 °C (x86_pkg_temp), skin 45 °C (I_VTS1), rapl_controller default |
as v1 + PID per trip, range 30→8 W, skin trip 44 °C | stepwise, Hyst (skin 45→43.5 °C, CPU 76→71 °C), range 30→8 W, PL2 via generic sysfs cdev in its own zone |
| Mean package power under load | 15.8 W | 15.8 W | 21.9 W (aborted after 10 min) | 16.3 W |
Time with I_VTS1 > 45 °C |
0 s (max 44.5 °C) | 1534 s (max 46.0 °C) | 100 s (max 46.5 °C) | 35 s (max 45.4 °C) |
| Time with CPU ≥ 99 °C | 11 s | 21 s | 69 s in 10 min | 40 s |
| PL1 during the long full-load phase | 14.2–14.8 W | 15.0 W (stuck at floor) | – | 8–30 W sawtooth |
What limits thermald here
-
Full release on deactivation. When a passive trip turns off, the cdev goes back to
min_state, which is 30 W forrapl_controller. Inside the hysteresis band the state is held, but it is never raised step by step. The incremental PID from #587 also says "Deactivating (state=0): Restore to min_state". The result is a sawtooth: throttle down step by step, hold, release to 30 W, boost, hit TjMax, throttle down again. #315 and #484 describe the same symptom ("PL1 briefly drops … before quickly rising to 20, 22, 25 again"). A setpoint controller needs to move the limit up and down around the target.
Suggestion: an option to keep the PID running while the trip is on and inside the hysteresis band, i.e. using negative error to raise the limit gradually, and to release with a bounded rate instead of jumping tomin_state. -
Only one passive trip per zone.
cthd_zone::add_trip()replaces an existing trip of the same type without a warning. In my v3a the 99 °C PL2 trip silently replaced the 76 °C CPU trip, so PL1 stayed at 30 W for the whole run. Putting the second trip into its own zone works.
Suggestion: allow several passive trips per zone, or at least log a warning. -
No control of PL2 / the RAPL budget. After idle, the package may run at PL2 (61 W) for about 60 s, until the running average catches up with PL1. A PL1 drop at TjMax therefore has almost no effect for that minute (cold start with the fan still at 0 rpm: ~25 s at TjMax with PL1 already at 21 W). Windows' drop to 21 W bites immediately, so it presumably lowers PL2 as well.
- My workaround: a generic sysfs cdev on
constraint_1_power_limit_uw(61 → 21 W) on a 99 °C trip. - With a 9 K hysteresis it chattered every ~5 s (155 changes in 4 min), because the CPU falls below 90 °C as soon as PL2 bites, and the next release brings back the full budget. With 25 K (release below 74 °C) it holds.
DebouncePeriodonly delays repeated activation, not release.
Suggestion: a PL2 option for
rapl_controller, or a release condition based on package power ≤ PL1 rather than temperature only. - My workaround: a generic sysfs cdev on
-
Default floor of
rapl_controller. The range was 30 → 15 W (50 %) unless overridden in<CoolingDevices>. With full display brightness the skin limit needs ~14.5 W here, so v1 sat at the floor with the skin at 45.5 °C. Overriding works fine, it's just not obvious from the man page. -
PID sign on 2.5.6. On 2.5.6 the PID needed negative gains for the inverted RAPL range. With per-trip reset on release, it turned into a limit cycle (v2: PL1 jumping between ~30 W and 8–16 W every 10 s). #587 fixes the inverted range, which is great. Point 1 still applies, though.
What I'd like to ask
- Is a setpoint-style mode for passive trips (point 1) something you would consider? I'd be happy to test patches on this machine, and I can share the scripts and raw data (1 s CSV logs of PL1/PL2, package and system power, CPU temperature,
I_VTS1, fan). - Is there a recommended way to handle the RAPL budget / PL2 (point 3) that I missed?
- If it helps other Surface devices, I can contribute the working v3b config as an example once the sensor registration is upstream.
- Lingua principale
- C++
- Stelle
- 667
- Fork
- 149
- Merge medio
- 6g 4h
- PR unite (30g)
- 2
Preparare l'ambiente
- Nessun Dockerfile né file Docker Compose
- Nessun modello di pull request
- Leggi la guida per i contributori
Come iniziare
- Leggi tutta la issue e poi la guida ai contributi del progetto.
- Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
- Fai un fork del repository e lavora su un branch.
- Apri una pull request che faccia riferimento al numero della issue.
Altre issue di intel/thermal_daemon
-
Difficoltà 4/5 3-5 giorni Idoneità per principianti 44/100
intel/thermal_daemon#612 · 1 commento ·
-
Difficoltà 5/5 Più di una settimana Idoneità per principianti 12/100
intel/thermal_daemon#606 · 5 commenti ·
-
Difficoltà 4/5 3-5 giorni Idoneità per principianti 35/100
intel/thermal_daemon#605 · 1 commento ·
Tutte le issue di intel/thermal_daemon
Issue simili
-
runtime: lf_f128_mod is documented as fmodq (truncating) but implements floor-based modulo; unusedApertainternal correctness low priority rt_lib
Difficoltà 2/5 1-3 ore Idoneità per principianti 72/100
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 1/5 Meno di un'ora Idoneità per principianti 87/100
-
PriorityNotificationQueue::wakeUpAll() loses the wake-up for a thread that is not waiting yetForse già presa @matejk l’ha presa oggi. Apertabug
Difficoltà 2/5 1-3 ore Idoneità per principianti 78/100
pocoproject/poco#5674 ·
I maintainer di solito rispondono entro 2 giorni
-
bug docs GUI
Difficoltà 2/5 1-3 ore Idoneità per principianti 62/100
sonic-pi-net/sonic-pi#3609 ·
-
Unreachable code warningApertabug
Difficoltà 2/5 1-3 ore Idoneità per principianti 70/100
SanderMertens/flecs#2395 ·
I maintainer di solito rispondono entro 1 giorno