Reproducing Windows-style PL1 control (skin + CPU) with thermal-conf.xml: full release below the trip causes a PL1 sawtooth

Aperta
#616 0 commenti 0 reazioni 0 assegnatari Vedi su GitHub

Nessuno ha ancora preso questa issue.

Valutazione

Difficoltà
5/5
Tempo stimato
Più di una settimana
Idoneità per principianti
35/100
Tipo di issue
Funzionalità
Chiarezza
Abbastanza chiara
Stato di attività
Attiva
Stack tecnologico
cpp, linux
Ambito
backend, devtools

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 --adaptive has nothing to work with.
  • The skin sensor I_VTS1 comes from the Surface EC through the surface_temp hwmon 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

  1. Full release on deactivation. When a passive trip turns off, the cdev goes back to min_state, which is 30 W for rapl_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 to min_state.

  2. 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.

  3. 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.
    • DebouncePeriod only 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.

  4. 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.

  5. 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

Come iniziare

  1. Leggi tutta la issue e poi la guida ai contributi del progetto.
  2. Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
  3. Fai un fork del repository e lavora su un branch.
  4. Apri una pull request che faccia riferimento al numero della issue.

Altre issue di intel/thermal_daemon

Tutte le issue di intel/thermal_daemon

Issue simili

Altre issue su C++

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.