thermal-conf.xml(5)
๐ thermal-conf.xml โ the thermal daemon's config file, bestie ๐
okay so this is the manual page for thermal-conf.xml, section 5 (File Formats Manual). It's giving config-file energy, and you're gonna slay it. ๐
๐ NAME ๐
thermal-conf.xml โ Configuration file for thermal daemon.
โจ SYNOPSIS โจ
$(TDCONFDIR)/etc/thermald/thermal-conf.xml
๐ธ DESCRIPTION ๐ธ
okay so thermal-conf.xml is a configuration file for the thermal daemon. It is used to configure thermal sensors, zone and cooling devices. The location of this file depends on the configuration option used during build time.
lowkey the terminology used in this file conforms to "Advanced Configuration and Power Interface Specification". The ACPI thermal model is based around conceptual platform regions called thermal zones that physically contain devices, thermal sensors, and cooling controls. For example of a thermal zone can be a CPU or a laptop cover. A zone can contain multiple sensors for monitoring temperature. A cooling device provides interface to reduce the temperature of a source device, which causes increase in the temperature. An example of a cooling device is a FAN or some Linux driver which can throttle the source device.
highkey, a thermal zone configuration includes one or more trip points. A trip point is a temperature at which a cooling device needs to be activated.
a cooling device can be either active or passive. An example of an active device is a FAN, which will not reduce performance at the cost of consuming more power and noise. A passive device uses performance throttling to control temperature. In addition to cooling devices present in the thermal sysfs, the following cooling devices are built into the thermald, which can be used as valid cooling device type:
rapl_controllerintel_pstatecpufreqLCD
the thermal sysfs under Linux (/sys/class/thermal) provides a way to represent per platform ACPI configuration. The kernel thermal governor uses this data to keep the platform thermals under control. But there are some limitations, which thermald tries to resolve. For example:
- If the ACPI data is not optimized or buggy. In this case
thermal-conf.xmlcan be used to correct the behavior without change in BIOS. - There may be thermal zones exposed by the thermal sysfs without associated cooling actions. In this case
thermal conf.xmlcan be used to tie the cooling devices to those zones. - The best cooling method may not be in the thermal sysfs. In this case
thermal-conf.xmlcan be used to bind a zone to an external cooling device. - Specify thermal relationships. A zone can be influenced by multiple source devices with varying degrees. In this case
thermal-conf.xmlcan be used to define the relative influence for apply compensation.
๐ FILE FORMAT ๐
the configuration file format conforms to XML specifications. A set of tags defined to define platform, sensors, zones, cooling devices and trip points.
virtual sensors support two XML forms:
SensorLinkdefines a simple linear transform using one linked sensor:virtual_temp = linked_sensor * Multiplier + OffsetLinkSensordefines one contribution to an advanced virtual sensor. MultipleLinkSensorentries may be provided and their contributions are summed. For each entry:avg = Offset * current_sample + (1 - Offset) * previous_averagecontribution = Coeff * avgvirtual_temp = sum of all contributions
for advanced virtual sensors, when PowerSensor is 0, the linked sensor temperature is converted from milli-degree Celsius to degree Celsius before the averaging and coefficient calculations are applied. Optional PollingTableEntry elements can be used to change the virtual sensor polling period based on the current virtual temperature.
<ThermalConfiguration>
<Platform>
<Name>Example Platform Name</Name>
<!-- UUID is optional, if present this will be matched. Both product
name and UUID can contain wild card "*", which matches any
platform. -->
<UUID>Example UUID</UUID>
<!-- configuration file format conforms to XML specifications. A
set of tags defined to define platform, sensors, zones, cooling
devices and trip points. -->
<ProductName>Example Product Name</ProductName>
<!-- SoCModel is optional. When present, thermald reads the board
model string from /sys/firmware/devicetree/base/model and
checks whether it starts with this value (prefix match).
This is intended for ARM/device-tree platforms such as
Qualcomm SoCs. Example: a SoCModel of
"Qualcomm Technologies, Inc. Glymur" will match a board
reporting "Qualcomm Technologies, Inc. Glymur CRD". -->
<SoCModel>Example SoC Model Prefix</SoCModel>
<Preference>QUIET|PERFORMANCE</Preference>
<!-- Quiet mode will only use passive cooling device. "PERFORMANCE"
will only select active devices. -->
<ThermalSensors>
<ThermalSensor>
<!-- New Sensor with a type and path -->
<Type>example_sensor_1</Type>
<Path>/some_path</Path>
<AsyncCapable>0</AsyncCapable>
</ThermalSensor>
<ThermalSensor>
<!-- Already present in thermal sysfs, enable this or
add/change config For example, here we are indicating
that sensor can do async events to avoid polling. -->
<Type>example_thermal_sysfs_sensor</Type>
<!-- If async capable, then we don't need to poll. -->
<AsyncCapable>1</AsyncCapable>
</ThermalSensor>
<ThermalSensor>
<!-- Simple virtual sensor form. Result is:
example_sensor_1 * 0.5 + 10.
Formula:
virtual_temp = linked_sensor * Multiplier + Offset. -->
<Type>example_virtual_sensor</Type>
<Virtual>1</Virtual>
<SensorLink>
<SensorType>example_sensor_1</SensorType>
<Multiplier> 0.5 </Multiplier>
<Offset> 10 </Offset>
</SensorLink>
</ThermalSensor>
<ThermalSensor>
<!-- Advanced virtual sensor form using multiple linked
sensors and optional polling-table entries.
For each LinkSensor entry:
avg = Offset * current_sample + (1 - Offset) * previous_average
contribution = Coeff * avg
virtual_temp = sum of all contributions.
When PowerSensor is 0, the linked thermal sensor value is
converted from milli-degree C to degree C before applying
the formula. -->
<Type>example_virtual_sensor_advanced</Type>
<Virtual>1</Virtual>
<LinkSensor>
<SensorType>example_sensor_1</SensorType>
<Coeff> 0.7 </Coeff>
<Offset> 0.2 </Offset>
<PowerSensor> 0 </PowerSensor>
</LinkSensor>
<LinkSensor>
<SensorType>rapl_pkg_power</SensorType>
<Coeff> 0.3 </Coeff>
<Offset> 0.5 </Offset>
<PowerSensor> 1 </PowerSensor>
</LinkSensor>
<PollingTableEntry>
<VirtualTemp> 45000 </VirtualTemp>
<SamplePeriod> 10 </SamplePeriod>
</PollingTableEntry>
<PollingTableEntry>
<VirtualTemp> 70000 </VirtualTemp>
<SamplePeriod> 2 </SamplePeriod>
</PollingTableEntry>
</ThermalSensor>
</ThermalSensors>
<ThermalZones>
<ThermalZone>
<Type>Example Zone type</Type>
<TripPoints>
<TripPoint>
<SensorType>example_sensor_1</SensorType>
<!-- Temperature at which to take action. -->
<Temperature> 75000 </Temperature>
<!-- max/passive/active If a MAX type is specified, then
daemon will use PID control to aggressively throttle
to avoid reaching this temp. -->
<type>max</type>
<!-- SEQUENTIAL | PARALLEL. When a trip point temp is
violated, then number of cooling devices can be
activated. If control type is SEQUENTIAL then, it
will exhaust first cooling device
before trying next. -->
<ControlType>SEQUENTIAL</ControlType>
<CoolingDevice>
<index>1</index>
<type>example_cooling_device</type>
<!-- Influence will be used order cooling devices. First
cooling device will be used, which has highest
influence. -->
<influence> 100 </influence>
<!-- Delay in using this cdev, this takes some time too
actually cool a zone. -->
<SamplingPeriod> 12 </SamplingPeriod>
<!-- Set a specific state of this cooling device when this
trip is violated. -->
<TargetState> 6 </TargetState>
<!-- Optional per-trip clamp range. Use one or both.
When omitted, cooling device MinState/MaxState is
used. -->
<TargetMinState> 2 </TargetMinState>
<TargetMaxState> 8 </TargetMaxState>
</CoolingDevice>
</TripPoint>
</TripPoints>
</ThermalZone>
</ThermalZones>
<CoolingDevices>
<CoolingDevice>
<!-- Cooling device can be specified by a type and optionally
a sysfs path. If the type is already present in thermal
sysfs, there is no need of a path. Compensation can use
min/max and step size to increasing cool the system.
Debounce period can be used to force a waiting period
for action. -->
<Type>example_cooling_device</Type>
<MinState>0</MinState>
<IncDecStep>10</IncDecStep>
<ReadBack> 0 </ReadBack>
<MaxState>50</MaxState>
<DebouncePeriod>5000</DebouncePeriod>
<!-- If there are no PID parameters, compensation increase step
wise and exponentially (if single step is not able to
change trend).
Alternatively a PID parameters can be specified then next
step will use PID calculation using provided PID
constants. -->
<PidControl>
<kp>0.001</kp>
<kd>0.0001</kd>
<ki>0.0001</ki>
</PidControl>
<!-- Write some prefix attached to state value, like below the
prefix is "level ". It will preserve spaces as entered
when writing to sysfs. -->
<WritePrefix>level </WritePrefix>
</CoolingDevice>
</CoolingDevices>
</Platform>
</ThermalConfiguration>
๐ EXAMPLE CONFIGURATIONS ๐
ok bestie, this is the fun part โ actual real-world configs you can copy-paste and vibe with. each one is a whole little story ๐
โจ Example 1 โจ
This is a very simple configuration, to change the passive limit on the CPU. Instead of the default, this new temperature 86C in the configuration is used. This will start cooling once the temperature reaches 86C. no cap, that's the whole thing ๐ฅถ
<?xml version="1.0"?>
<ThermalConfiguration>
<Platform>
<Name>Override CPU default passive</Name>
<ProductName>*</ProductName>
<Preference>QUIET</Preference>
<ThermalZones>
<ThermalZone>
<Type>cpu</Type>
<TripPoints>
<TripPoint>
<Temperature>86000</Temperature>
<type>passive</type>
</TripPoint>
</TripPoints>
</ThermalZone>
</ThermalZones>
</Platform>
</ThermalConfiguration>
โจ Example 2 โจ
In this configuration, we are controlling the backlight when some sensor "SEN2" reaches 60C. Here "LCD" is a standard cooling device, which uses the Linux backlight sysfs interface. "LCD_Zone" is a valid thermal zone in Linux thermal sysfs on the test platform, hence we don't need to provide a path for sysfs for "LCD_Zone". The Linux thermal sysfs is already parsed and loaded by the thermald program. so we just trust it ๐
<?xml version="1.0"?>
<ThermalConfiguration>
<Platform>
<Name>Change Backlight</Name>
<ProductName>*</ProductName>
<Preference>QUIET</Preference>
<ThermalZones>
<ThermalZone>
<Type>LCD_Zone</Type>
<TripPoints>
<TripPoint>
<SensorType>SEN2</SensorType>
<Temperature>60000</Temperature>
<type>passive</type>
<CoolingDevice>
<Type>LCD</Type>
</CoolingDevice>
</TripPoint>
</TripPoints>
</ThermalZone>
</ThermalZones>
</Platform>
</ThermalConfiguration>
โจ Example 3 โจ
In this example, a Lenovo Thinkpad X220 and its fan speed are controlled. Here a cooling device "_Fan" can be controlled via sysfs /sys/devices/platform/thinkpad_hwmon/pwm1. When x86_pkg_temp reaches 45C, the Fan is started with increasing speeds, if the temperature can't be controlled at 45C. like it's literally trying its best ๐ญ
<?xml version="1.0"?>
<ThermalConfiguration>
<Platform>
<Name>Lenovo ThinkPad X220</Name>
<ProductName>*</ProductName>
<Preference>QUIET</Preference>
<ThermalZones>
<ThermalZone>
<Type>x86_pkg_temp</Type>
<TripPoints>
<TripPoint>
<SensorType>x86_pkg_temp</SensorType>
<Temperature>45000</Temperature>
<type>passive</type>
<ControlType>SEQUENTIAL</ControlType>
<CoolingDevice>
<index>1</index>
<type>_Fan</type>
<influence> 100 </influence>
<SamplingPeriod> 12 </SamplingPeriod>
</CoolingDevice>
</TripPoint>
</TripPoints>
</ThermalZone>
</ThermalZones>
<CoolingDevices>
<CoolingDevice>
<Type>_Fan</Type>
<Path>/sys/devices/platform/thinkpad_hwmon/pwm1</Path>
<MinState>0</MinState>
<IncDecStep>30</IncDecStep>
<ReadBack> 0 </ReadBack>
<MaxState>255</MaxState>
<DebouncePeriod>5</DebouncePeriod>
</CoolingDevice>
</CoolingDevices>
</Platform>
</ThermalConfiguration>
โจ Example 4 โจ
The following example shows how PID can be used. Here, once the temperature exceeds 80C, compensation is calculated using PID using 80C as the set point of PID. The compensation depends on the error from the set point. Here the default built-in processor cooling device is used with min state as 0 and max state as 10. math girlies rise ๐งฎโจ
<?xml version="1.0"?>
<ThermalConfiguration>
<Platform>
<Name>Use PID param </Name>
<ProductName>*</ProductName>
<Preference>QUIET</Preference>
<ThermalZones>
<ThermalZone>
<Type>x86_pkg_temp</Type>
<TripPoints>
<TripPoint>
<SensorType>x86_pkg_temp</SensorType>
<Temperature>80000</Temperature>
<type>passive</type>
<ControlType>SEQUENTIAL</ControlType>
<CoolingDevice>
<type>Processor</type>
</CoolingDevice>
</TripPoint>
</TripPoints>
</ThermalZone>
</ThermalZones>
<CoolingDevices>
<CoolingDevice>
<Type>Processor</Type>
<PidControl>
<kp>0.0002</kp>
<kd>0</kd>
<ki>0</ki>
</PidControl>
</CoolingDevice>
</CoolingDevices>
</Platform>
</ThermalConfiguration>
โจ Example 5 โจ
The following example shows how to control a Fan when the sysfs expects some string prefix. For example, instead of just writing a number to the fan control sysfs, the interface requires "level " in front of the speed index value. it's giving โจfancyโจ energy
<?xml version="1.0"?>
<ThermalConfiguration>
<Platform>
<Name>Use Fan control first then CPU throttle </Name>
<ProductName>*</ProductName>
<Preference>QUIET</Preference>
<ThermalZones>
<ThermalZone>
<Type>x86_pkg_temp</Type>
<TripPoints>
<TripPoint>
<SensorType>x86_pkg_temp</SensorType>
<Temperature>80000</Temperature>
<type>passive</type>
<ControlType>SEQUENTIAL</ControlType>
<CoolingDevice>
<type>_fan_</type>
</CoolingDevice>
</TripPoint>
</TripPoints>
</ThermalZone>
</ThermalZones>
<CoolingDevices>
<CoolingDevice>
<Type>_fan_</Type>
<Path>/proc/acpi/ibm/fan</Path>
<WritePrefix>level </WritePrefix>
<MinState>0</MinState>
<MaxState>5</MaxState>
<DebouncePeriod>10</DebouncePeriod>
</CoolingDevice>
</CoolingDevices>
</Platform>
</ThermalConfiguration>
โจ Example 6 โจ
Similar to Example 5, but write different speeds at different temperatures. multi-speed slay ๐ ๐ฅ
<?xml version="1.0"?>
<ThermalConfiguration>
<Platform>
<Name>Use Fan control first then CPU throttle </Name>
<ProductName>*</ProductName>
<Preference>QUIET</Preference>
<ThermalZones>
<ThermalZone>
<Type>x86_pkg_temp</Type>
<TripPoints>
<TripPoint>
<SensorType>x86_pkg_temp</SensorType>
<Temperature>80000</Temperature>
<type>passive</type>
<CoolingDevice>
<type>_fan_</type>
<TargetState>1</TargetState>
</CoolingDevice>
</TripPoint>
<TripPoint>
<SensorType>x86_pkg_temp</SensorType>
<Temperature>85000</Temperature>
<type>passive</type>
<CoolingDevice>
<type>_fan_</type>
<TargetState>2</TargetState>
</CoolingDevice>
</TripPoint>
</TripPoints>
</ThermalZone>
</ThermalZones>
<CoolingDevices>
<CoolingDevice>
<Type>_fan_</Type>
<Path>/proc/acpi/ibm/fan</Path>
<WritePrefix>level </WritePrefix>
<MinState>0</MinState>
<MaxState>5</MaxState>
<DebouncePeriod>10</DebouncePeriod>
</CoolingDevice>
</CoolingDevices>
</Platform>
</ThermalConfiguration>
โจ Example 7 โจ
Use RAPL power limits to control. โก๐
okay bestie, buckle up, here's the next config in the lineup ๐ this one is all about RAPL power limits โ and yes the comments are doing the explaining for us, love that for us:
<?xml version="1.0"?>
<!-- BEGIN -->
<ThermalConfiguration>
<Platform>
<Name> TEST </Name>
<ProductName>Example_RAPL_Power </ProductName>
<Preference>QUIET</Preference>
<PPCC>
<!--
Specify the Maximum/Minimum RAPL power limit for the
platform. The limits are in milli watts.
The step size to reduce/increase for each sampling interval
Time window in miili seconds.
-->
<PowerLimitIndex>0</PowerLimitIndex>
<PowerLimitMaximum>15000</PowerLimitMaximum>
<PowerLimitMinimum>2000</PowerLimitMinimum>
<TimeWindowMinimum>20</TimeWindowMinimum>
<TimeWindowMaximum>30</TimeWindowMaximum>
<StepSize>1000</StepSize>
</PPCC>
<ThermalZones>
<ThermalZone>
<Type>TestZone</Type>
<TripPoints>
<TripPoint>
<SensorType>SEN3</SensorType>
<Temperature>50000</Temperature>
<Type>Passive</Type>
<CoolingDevice>
<Type>B0D4</Type>
<SamplingPeriod>3</SamplingPeriod>
<TargetState>2147483647</TargetState>
<!--
This setting means that when SEN3 reaches 50C, set the RAPL
max power limit to whatever the maximum power limit of the
platform.
-->
</CoolingDevice>
</TripPoint>
<TripPoint>
<SensorType>SEN3</SensorType>
<Temperature>52000</Temperature>
<Type>Passive</Type>
<CoolingDevice>
<Type>B0D4</Type>
<SamplingPeriod>3</SamplingPeriod>
<TargetState>8500000</TargetState>
<!--
This setting means that when SEN3 reaches 52C, set the RAPL
max power limit to 8.5W.
-->
</CoolingDevice>
</TripPoint>
<TripPoint>
<SensorType>SEN3</SensorType>
<Temperature>60000</Temperature>
<Type>Passive</Type>
<CoolingDevice>
<Type>B0D4</Type>
<SamplingPeriod>3</SamplingPeriod>
<TargetState>4500000</TargetState>
<!--
This setting means that when SEN3 reaches 60C, set the RAPL
max power limit to 4.5W.
-->
</CoolingDevice>
</TripPoint>
<TripPoint>
<SensorType>SEN3</SensorType>
<Temperature>65000</Temperature>
<Type>Passive</Type>
<CoolingDevice>
<Type>B0D4</Type>
<SamplingPeriod>3</SamplingPeriod>
<!--
This setting means that when SEN3 reaches 65C, set the RAPL
max power limit to minimum power limit for the platform.
-->
</CoolingDevice>
</TripPoint>
</TripPoints>
</ThermalZone>
</ThermalZones>
</Platform>
</ThermalConfiguration>
Example 8: AMD Ryzen / k10temp configuration ๐ฆ
okay so this one is a whole situation and I need you to focus, bestie ๐ญ
On AMD platforms, the CPU temperature sensor (k10temp) is exposed via hwmon sysfs but it does not have an associated thermal_zone in /sys/class/thermal. The way that it just... doesn't show up there?? rude honestly ๐
Which means thermald cannot auto-discover it, and the default CPU DTS monitoring will report:
"No coretemp sysfs found""No Zones present"
so yeah, not the vibe. ๐
The fix, bestie: a custom sensor must be defined with the hwmon path, and the CPU ID check must be bypassed using the --ignore-cpuid-check command line option. slay, we're doing it manually.
To find the correct hwmon path, run:
find /sys/class/hwmon/ -exec echo -n "{}: " \; -exec cat {}/name \;
Then identify the k10temp entry and its Tctl sensor. For example, if k10temp is hwmon2, the Tctl path is /sys/class/hwmon/hwmon2/temp1_input. got it? got it. โจ
<?xml version="1.0"?>
<ThermalConfiguration>
<Platform>
<Name>AMD Ryzen (k10temp via hwmon)</Name>
<UUID>*</UUID>
<ProductName>*</ProductName>
<Preference>QUIET</Preference>
<ThermalSensors>
<ThermalSensor>
<!-- Define a custom sensor name and point it at the
k10temp hwmon path. The name must NOT match any
auto-discovered hwmon driver name (do not use
"k10temp" here); use a unique name instead. -->
<Type>amd_cpu_temp</Type>
<Path>/sys/class/hwmon/hwmon2/temp1_input</Path>
<AsyncCapable>0</AsyncCapable>
</ThermalSensor>
</ThermalSensors>
<ThermalZones>
<ThermalZone>
<Type>cpu</Type>
<TripPoints>
<TripPoint>
<SensorType>amd_cpu_temp</SensorType>
<Temperature>85000</Temperature>
<type>passive</type>
<CoolingDevice>
<type>cpufreq</type>
<influence>100</influence>
<SamplingPeriod>1</SamplingPeriod>
</CoolingDevice>
</TripPoint>
<TripPoint>
<SensorType>amd_cpu_temp</SensorType>
<Temperature>95000</Temperature>
<type>passive</type>
<CoolingDevice>
<type>cpufreq</type>
<influence>100</influence>
<SamplingPeriod>1</SamplingPeriod>
</CoolingDevice>
</TripPoint>
</TripPoints>
</ThermalZone>
</ThermalZones>
</Platform>
</ThermalConfiguration>
bestie, remember the rule: the<Type>you pick for that custom sensor must NOT match any auto-discovered hwmon driver name โ do not use"k10temp"there. Use a unique name instead. that part is not optional ๐
and that's the whole page, bestie ๐ซถ go forth and thermal-configure responsibly, no cap. this one's dated Dec 18, 2018 and lives in the man pages as thermal-conf.xml(5) ๐โจ
๐ฆ where this page comes from
- centos-stream 10: thermald 2.5.13-1.el10 ยท GPLv2+
- fedora 43: thermald 2.5.13-1.fc43 ยท GPL-2.0-or-later
- fedora 44: thermald 2.5.13-1.fc44 ยท GPL-2.0-or-later
- nixpkgs unstable: thermald 2.5.13
- Copyright (C) 2012 Intel Corporation. All rights reserved
- ๐ girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms