Repository navigation
j613: CPU thermal zones and SoC die sensors (MacBook Air 13" M3) - #146
Conversation
T8122's OPP tables have no opp-microwatt, so its CPUs have no energy
model. The power allocator thermal governor then has no power actors
("is not a power actor") and cannot throttle, and the scheduler cannot
place tasks by energy.
Add per-CPU power for every OPP of both clusters, measured on a J613
(MacBook Air 13", M3) through the SMC's cluster power keys: the cluster
pinned to the state, its four CPUs busy minus the cluster idle, divided
by four. The values are fitted curves so that they rise monotonically.
Above 3288 MHz the P cluster's power stays at about 11 W with all four
CPUs busy, and work per clock at 4056 MHz is 8-10% below 3420 MHz even
with one CPU busy: the hardware limits the top states itself. Those
states get the extrapolated curve.
Assisted-by: Claude:claude-opus-5-5
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017YMqWu7A3VwEYtHaA1TusK
Signed-off-by: Marius Gehrmann <marius@gehrmann.solutions>
…ensors Make the CPUs cooling devices (apple-soc-cpufreq registers them when the CPU nodes have #cooling-cells) and add six SMC die temperature sensors as the first temperature channels of the SMC hwmon, so that board thermal zones can refer to them by index, as on t8140. The keys were picked on a J613 (MacBook Air 13", M3) from the SMC key list by loading one CPU at a time: Te05 and Te0P for the two E-cluster sensor groups, and for each P core the key that rose most with only that core busy (Tp05, Tp0L, Tp0b, Tp0r for cpu@10100..10103). Each P key has a twin that reads about 6.5 C lower and follows it; these are the hotter ones. Assisted-by: Claude:claude-opus-5-5 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017YMqWu7A3VwEYtHaA1TusK Signed-off-by: Marius Gehrmann <marius@gehrmann.solutions>
Nothing limits the J613's CPU temperature: with the four P cores busy at 4056 MHz the die sensors pass 107 C at full clock and reach 111 C after two minutes, still rising. T8122 has no fast die-temperature limit (apple,fast-die-effort) and the SMC's thermal pressure is not acted on. Add one thermal zone per CPU die sensor, each throttling both clusters through the power allocator, as on the fanless J700: switch-on 58 C, control 95 C, critical 110 C, E cluster weighted three to one and capped at cooling state 3 (2004 MHz). sustainable-power is 6 W from load tests on a J613: it held the four busy P cores at 90-95 C and 2.6-3.0 GHz, where the J700's 1.5 W held 72 C at 2.1 GHz and 7.5 W oscillated. Assisted-by: Claude:claude-opus-5-5 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017YMqWu7A3VwEYtHaA1TusK Signed-off-by: Marius Gehrmann <marius@gehrmann.solutions>
The J613 has no entry in the board table, so the GPU's thermal limit finds no SoC die temperature zone: a performance cap above state 2 (asahi.t8122_pstate_cap) runs the fanless GPU with no temperature feedback. Give the J613 its die keys: the six Tg keys that rose most (about 50 C) with only the GPU busy, and the CPU die keys the board's device tree uses for its CPU thermal zones (Te05, Te0P, and Tp05, Tp0L, Tp0b, Tp0r, one per P core). The Tg keys read 0 C or slightly below while the GPU is powered off; the zone reads the hottest key, so the CPU keys carry it then. Also expose the thermal pressure level (mTPL), which the J613's SMC has. Assisted-by: Claude:claude-opus-5-5 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017YMqWu7A3VwEYtHaA1TusK Signed-off-by: Marius Gehrmann <marius@gehrmann.solutions>
|
Follow-up on the cap-3 test: on release 20 + #127 + #135 + this PR, (Test and text by TARS, my Claude Code agent.) |
|
Independent J613 test on the older 14.x firmware profile: the DT changes from head All six CPU keys are readable floats on this machine. Six 6 W I also checked the automatic path with temperature emulation, keeping actual TCMz below 73°C:
These are kernel energy-model estimates and QoS ceilings, not independent electrical-power/effective-frequency measurements. This does not qualify sustained regulation at real high temperatures, sensor accuracy, critical shutdown, or higher GPU states. GPU ceiling stayed at state 2 / 618 MHz. This was a DT-only one-boot trial: the existing built-in hwmon driver and explicit Selected native evidence, source/build/boot preflight. Tests and this report were performed/written with Codex; Toni operated the laptop and approved OS authentication. Sleep follow-up: a 128.66-second lid sleep/resume passed, with suspend success +1 and no failure. All six CPU zones remained readable and bound to both cooling devices through matched pre/resume and30/60/120-second samples. Sensor values continued changing. Sleep evidence. Post-resume actuator retests also passed: P ceiling4056→3960→4056MHz and E2748→2556→2748MHz; both cooling states restored to zero. The original stage2 hash was verified again. Automatic thermal regulation after resume was not retested. Bounded native-input response on Aurora .20The retained DT-only trial from this PR head Observed QoS ceilings reached P=2808 MHz and E=2004 MHz (maximum cooling states 11 and 3). These are requested limits, not independently measured frequencies. The independent 75 C guard stopped the worker after 8.099 seconds at a maximum reported zone temperature of 75.890 C; CPU-zone peak was 62.410 C. The target did not settle, so this is not a stable-regulation pass or qualification of the normal 95 C control point. Original 58/95 C trips and 4056/2748 MHz ceilings were restored, both cooling states returned to zero, and the worker/rollback timer are inactive. Sustained real-temperature regulation, sensor accuracy and critical shutdown remain unqualified. Selected evidence. TCMz versus the proposed default key list (20 October)A read-only comparison on J613, This does not establish that TCMz is faulty or validate replacing it. Is its omission from the proposed defaults intentional for a known sensor/aggregation reason, or is the list simply based on the CPU/GPU load-response selection described above? It matters when comparing temperatures between the override and default-key test reports. Selected paired evidence. Comparison and update performed with Codex on Toni's machine. Passive numeric sensor readings (21 October)Same J613 / T8122, The exact release-20 hwmon source preserves the float sign, propagates read errors separately, and accepts -40 to 150 C in the hottest-channel aggregate. These numeric values therefore do not themselves make the aggregate fail. This is not proof of physical accuracy, a bad TCMz sensor, or power-gating behaviour. No keys or guard thresholds were changed. A separate single-E-core build attempt was stopped by the independent 75 C guard after four seconds; it produced no module. Passive ranges and pinned source audit, guarded-build stop. This supplements the TCMz/default-key question above; it does not qualify higher GPU states or alter the proposed defaults. Observations and source audit performed with Codex on Toni's machine. |
|
Independent full-kernel J613 / 8-core M3 Air boot check with release 20 ( Booted
GPU ceiling remained state 2 / 618 MHz throughout this first boot. This confirms the default sensor mapping is exposed and consumed on this machine; it does not yet qualify higher GPU states, automatic CPU cooling under sustained heat, sensor calibration, critical shutdown, or suspend/resume. The firmware's instantaneous MHz field still reports zero, so 618 MHz refers to the configured state ceiling. Test work and this report performed with Codex; Gary operated the laptop and authorized the test installation and reboot. Higher-clock testing will follow separately. |
|
Further full-kernel J613 / 8-core M3 Air testing on release 20 + #135 + this PR, using the default SMC die-key mapping without Boot policy retained Repeated shader workload: identical
State 4 averaged 11.4% above state 3. State 5 averaged 10.6% above state 4 and 23.2% above state 3 in this shader workload. These are small, separate-boot synthetic comparisons, not general desktop or performance-per-watt measurements. Earlier 618/796 MHz glmark2 refract/terrain samples overlapped; I do not infer a reliable gain from those. OpenGL red/blue and Vulkan compute readback passed before and after each state's load test. A further 90-second GPU workload at each ceiling, including the fallback trials below, completed with exit 0 and no observed GPU job fault, timeout or over-cap failure. Physical die-key peaks during those runs were 54.166°C (state 3), 53.213°C (state 4), and 56.807°C (state 5). Live #135 fallback checks at each of states 3, 4 and 5, while GPU jobs ran:
Emulation was cleared after every trial. The six CPU zones and physical hwmon channels retained native readings throughout. This checks hot/invalid-input response; it does not test sensor disconnection, sensor calibration, real high-temperature regulation, critical shutdown or suspend/resume. The stock kernel remains the default boot choice; higher-state tests use separate retained entries. Tests/report performed with Codex; Gary operated the laptop and authorized authentication and reboots. Installation/ceiling follow-up: a subsequent attempt with The failed boot also had missing Wi-Fi/zram and other kernel modules. The stock boot at 20:48 local ran Packaged state-6 retest (subsequent to the failed attempt above): the install now uses a separate, pacman-owned This retest adds a local experimental guard patch beyond #135 and #146. Base Same packaged kernel, GPU workload binary and settings as above, on battery, separate boots, no Chromium processes running during either isolated comparison:
State 6 averaged 9.5% higher in this shader workload. Firmware peak-state telemetry reached 6; instantaneous MHz still reads zero, so this is a table-state result rather than a continuous frequency measurement. Earlier background-contended state-5 samples (138.7, 109.3, 110.2 FPS) were excluded from this isolated comparison. Small separate-boot samples do not establish general desktop performance, thermal efficiency or performance per watt. A further 90-second state-6 load, including the fallback trials, exited 0; all twelve physical SoC die channels remained native, with sampled peak 58.245°C. Kernel logs show direct These remain bounded tests with simulated sensor input. Real hot regulation, sensor calibration/disconnection, critical shutdown, suspend/resume and daily-use stability remain unqualified. Tests/report performed with Codex; Gary operated the machine and authorized the work. Extended state-6 follow-up, same packaged kernel and local admission patch described above:
The experimental state-6 kernel remains running, with stock retained as the next-boot default. These additional checks improve the evidence for this exact setup; they do not establish general daily-use stability. Real hot regulation, sensor calibration/disconnection, critical shutdown, repeated/long suspend and broader application coverage remain outstanding. No state-7 entry has been enabled. State-7 bounded follow-up on the same J613 / 8-core M3 Air: a separate pacman-owned Same shader binary/settings, 5-second warm-up followed by three 20-second runs, on battery with no Chromium processes running:
That is 7.9% higher in this shader workload. This comparison spans separate boots and different kernel images (the reviewed state-7 admission delta, identical kernel config), so it remains a small synthetic comparison rather than a same-image controlled result or a general desktop/per-watt claim. Firmware peak-state telemetry reached 7; instantaneous MHz remains unavailable/zero, so MHz denotes the configured firmware table entry. A further 90-second load, including live fallback checks, exited 0; sampled native physical die peak was 58.927°C. Logs confirm direct State 7 has not yet received the 15-minute load/browser/suspend qualification described above for state 6. Sustained heat, state-7 suspend/resume, real hot regulation, sensor disconnection/calibration, critical shutdown and daily-use stability remain unqualified. No state-8 test entry is enabled. Tests/report performed with Codex; Gary operated the laptop and authorized the work. State-8 bounded follow-up (2026-10-20), same J613 / 8-core M3 Air: kernel The highest operating point in this machine's raw Apple ADT PMGR voltage tables is 1338 MHz / 935 mV (secondary frequency 1204 MHz). Those raw entries match the live GPU OPP data. This is model-specific firmware evidence, not a direct macOS frequency measurement. Firmware peak-state telemetry reached 8; instantaneous MHz telemetry is unavailable/zero, so MHz here names the configured table entry. Same shader binary/settings, on battery, no Chromium processes running: 5-second warm-up then three 20-second runs gave 187.3, 187.1, 189.8 FPS, mean 188.07 FPS, sampled aggregate die peak 55.934°C. This is 5.2% above the prior state-7 mean of 178.77 FPS. Separate boots and different kernel images, same kernel config/workload: a small synthetic comparison, not a general desktop or per-watt claim. A complete 90-second GPU load with 52 sampled seconds of live fallback testing exited 0. Simulated 84°C and invalid 1°C each caused direct Near the end of the successful final load, native physical Post-load OpenGL/Vulkan hardware checks, Wi-Fi connectivity, zram, package ownership and module loading passed; no GPU faults/timeouts were observed. The experimental cap8 kernel is running; stock is the next-boot default. State-8 15-minute load, browser/video, suspend/resume, sensor calibration/disconnection and daily-use qualification remain outstanding. This update supersedes the earlier “no state-8 entry” status. Tests/report performed with Codex; Gary operated the laptop and authorized the work. Follow-up: higher GPU states 6–8 now have a dedicated tracking issue, #164, including the exact local patch, tested results and remaining qualification. This comment retains the historical evidence; future higher-state updates will continue there. Sensor/CPU thermal-zone validation remains on #146. |
|
Thank you @tonibergholm and @garymeyerca for the independent J613 tests. Between them they cover the DT-only path on the older 14.x firmware profile (including lid sleep and a bounded native low-trip run) and the full kernel with the default die-key mapping and no On the stale "no SoC die temperature zone" warning that Gary also saw for caps above 2: I offered a follow-up for it above, but none is needed on the current base. On This PR still merges cleanly onto that base (checked locally with (Checked and written by TARS, my Claude Code agent.) |
chriskearney
left a comment
There was a problem hiding this comment.
Reviewed exact head 8fd1bf481afe6fcadaa04001b2bcd435616b705b: all three changed files, the current thermal/hwmon/cpufreq consumers, and the effective merge onto 0571e8d7. Source review supports an integration merge subject to required CI and the full merge queue.
DT controls built all seven affected T8122 boards plus a J700 control against the current tree and merge result; existing dtc warnings were unchanged apart from line numbers, and J700 was byte-identical. Sensor indices remain stable when a key is missing; the cooling maps and default power_allocator path resolve as intended. Shared cooling devices select the most restrictive zone target rather than adding targets.
This changes runtime policy: J613/J613-25g83 gain six CPU zones and a 110 C critical trip; all T8122 boards gain the energy model/EAS and hwmon channel declarations. Under heavy load, the allocator can reduce clocks below the 95 C control point. Existing public J613 evidence is on 7.1.12 and the older firmware profile; it is not a merged-7.2 or 25G83 qualification.
The unanswered TCMz/default-key discrepancy and the existence/meaning of these keys on 25G83 remain explicit hardware/release limitations. Byte-identical hwmon code establishes the read path, not firmware sensor semantics or calibration. No physical boot, sensor-accuracy or critical-shutdown pass is claimed by this review. Higher GPU-state admission remains out of scope.
8f96afe
Nothing limits the J613's CPU temperature today. With the four P cores busy at 4056 MHz, the die sensors pass 107 °C at full clock and reach 111 °C after two minutes, still rising. T8122 has no fast die-temperature limit (
apple,fast-die-effort), and nothing acts on the SMC's thermal pressure. The GPU's thermal limit also finds no SoC die zone on J613, so a performance cap above state 2 runs the fanless GPU with no temperature feedback.What
opp-microwatt). Without it,power_allocatorhas no power actors ("is not a power actor") and cannot throttle. The values are measured on a J613 through the SMC's cluster power keys (cluster pinned to the state, four CPUs busy minus cluster idle, divided by four) and fitted so that they rise monotonically. Side effect: T8122 gets an energy model for EAS too.#cooling-cellson the CPU nodes, and six SMC die sensors as the first temperature channels of the SMC hwmon, as on t8140. Te05/Te0P cover the E-cluster groups. Tp05/Tp0L/Tp0b/Tp0r are, for each P core, the key that rose most with only that core busy.power_allocator, as on the fanless J700: switch-on 58 °C, control 95 °C, critical 110 °C, E cluster weighted 3:1 and capped at cooling state 3 (2004 MHz).sustainable-poweris 6 W from load tests (below).mTPL. With it,macsmc_soc_dieexists and the GPU's thermal limit gets a reading.Other boards are unchanged. The DT patches need the new DTBs (boot loader / installer); the hwmon entry only matches
apple,j613.Tested (J613, MacBook Air 13" M3, 16 GB)
Load tests, 10 min each, with patches 1-3 on our daily kernel (2026-10-14):
With 6 W, all 8 cores busy: 92 °C (peak 96 °C), P cluster 2.2-2.4 GHz, E cluster at full clock. P cores + GPU together: peak 97 °C. E cores only: 74 °C. No trip near 110 °C in any run.
In daily use since 2026-10-15 on our daily kernels, and since today on our test kernel (release 20
5d570a78+ #127 + #135 + these patches):cpu-*-thermalzones onpower_allocator,sustainable_power6000 from the DTcpufreq-cpu0(20 states) andcpufreq-cpu1(7)macsmc_soc_diewith 12 of 12 keys; the GPU reads "SoC die temperature … from zones: macsmc_soc_die"On that kernel the GPU reads it and stays at cap 2 ("SoC die 60.5 C, runtime cap 2 (618 MHz) of 2..=2"). Running above state 2 on this base with
asahi.t8122_pstate_cap=3is my next test. Our earlier kernels did it with an extra GPU patch that is not part of this PR, so I make no performance claim here.Build: W=1 of
t8122-j613.dtb(only the two existingsimple_bus_regwarnings for avd/fifo in t8122.dtsi) and ofmacsmc-hwmon.o(clean). checkpatch is clean apart from the trailers.Notes
t8122_start.rsstill says "J613/J615 have no SoC die temperature zone yet" and warns about it whenpstate_capis above 2. With patch 4 that is no longer true for J613. I can send a follow-up for the warning if you want it in the same series.soc_die_keys=override.(Measurements, patches and this text by TARS, my Claude Code agent, with me running the machine and reviewing; Signed-off-by is mine.)
🤖 Generated with Claude Code
https://claude.ai/code/session_017YMqWu7A3VwEYtHaA1TusK