Thermal Management (열 관리)

Linux 커널 Thermal 서브시스템은 CPU/GPU/SoC 센서 온도를 기반으로 thermal zone, trip point, cooling map을 구성하고 cooling device를 제어해 과열을 방지합니다. step_wise/fair_share/power_allocator governor의 제어 전략, cpufreq/devfreq·fan·throttle 연동, ACPI·Device Tree·hwmon 통합, 열 한계와 성능 사이의 정책 설계, 운영 환경에서의 throttling 원인 분석과 디버깅 절차를 상세히 다룹니다.

전제 조건: 전원관리hwmon 문서를 먼저 읽으세요. Thermal 서브시스템은 온도 센서(hwmon)와 전력 제어(PM/cpufreq)를 연결하는 중간 레이어이므로, 양쪽 개념을 이해해야 전체 동작을 파악할 수 있습니다.
일상 비유: Thermal Management는 에어컨의 자동 온도 조절 시스템과 비슷합니다. 온도 센서(thermal zone)가 현재 실내 온도를 측정하고, 설정한 온도 임계값(trip point)을 초과하면 제어 알고리즘(thermal governor)이 냉각 장치(cooling device: 에어컨 압축기, 팬 속도)를 자동으로 조절합니다.

핵심 요약

  • Thermal Zone — CPU, GPU 등 온도를 측정하는 하드웨어 영역. 온도 센서와 trip point를 포함합니다.
  • Trip Point — 온도 임계값. active, passive, hot, critical 4가지 타입으로 cooling 정책을 다르게 트리거합니다.
  • Cooling Device — 온도를 낮추는 장치. CPU 주파수 제한, 팬 속도 증가, GPU throttling 등.
  • Thermal Governor — thermal zone과 cooling device를 연결하는 정책 알고리즘. step_wise, power_allocator 등.
  • 제어 루프 — 온도 샘플링 → trip 비교 → governor 판단 → cooling 조정 → 온도 하강 → 반복.

단계별 이해

  1. Thermal Zone 확인
    /sys/class/thermal/thermal_zone*/에서 현재 시스템의 온도 센서와 trip point를 확인합니다.
  2. Cooling Device 파악
    /sys/class/thermal/cooling_device*/에서 사용 가능한 cooling 수단과 상태 범위를 확인합니다.
  3. Governor 정책 이해
    step_wise, power_allocator 등 governor 알고리즘이 온도에 따라 cooling을 어떻게 조정하는지 학습합니다.
  4. Tracing으로 동작 추적
    thermal tracepoint를 활성화하여 온도 변화와 cooling 동작을 실시간으로 관찰합니다.
관련 문서: ACPI (ACPI Thermal Zone), hwmon (온도 센서), 전원 관리 (DVFS 통합), CPU 토폴로지 (코어별 온도)

개요

Thermal Management 서브시스템은 하드웨어 과열을 방지하고 성능과 전력 소비를 균형있게 조절하는 커널의 핵심 컴포넌트입니다.

Thermal Zone temp / trip point Thermal Governor step_wise / power_allocator Cooling Device cpufreq / fan / devfreq 하드웨어 상태 온도 하강 / 성능 변화

주요 구성 요소

아키텍처

User Space /sys/class/thermal/thermal_zone* | /sys/class/thermal/cooling_device* Thermal Framework Core thermal_zone_device_register() thermal_cooling_device_register() | thermal_zone_device_update() Thermal Zone Thermal Governor Cooling Device Hardware Drivers ACPI Thermal | hwmon | CPU Freq

Thermal Zone

thermal_zone_device 구조체

struct thermal_zone_device {
    int id;
    char type[THERMAL_NAME_LENGTH];
    struct device device;
    struct thermal_zone_device_ops *ops;
    const struct thermal_zone_params *tzp;
    struct thermal_governor *governor;
    struct list_head thermal_instances;  /* cooling device 바인딩 */
    int temperature;           /* 현재 온도 (milli-Celsius) */
    int last_temperature;      /* 이전 측정 온도 */
    int polling_delay;         /* 폴링 주기 (msec) */
    int passive;               /* passive cooling 활성화 */
    bool forced_passive;
    struct thermal_zone_device_ops *ops;
    struct list_head node;
};

thermal_zone_device_ops

struct thermal_zone_device_ops {
    int (*bind)(struct thermal_zone_device *,
                  struct thermal_cooling_device *);
    int (*unbind)(struct thermal_zone_device *,
                    struct thermal_cooling_device *);
    int (*get_temp)(struct thermal_zone_device *, int *temp);
    int (*set_trips)(struct thermal_zone_device *, int, int);
    int (*get_mode)(struct thermal_zone_device *,
                     enum thermal_device_mode *);
    int (*set_mode)(struct thermal_zone_device *,
                     enum thermal_device_mode);
    int (*get_trip_type)(struct thermal_zone_device *, int,
                           enum thermal_trip_type *);
    int (*get_trip_temp)(struct thermal_zone_device *, int, int *);
    int (*get_crit_temp)(struct thermal_zone_device *, int *);
    int (*notify)(struct thermal_zone_device *, int,
                   enum thermal_trip_type);
};

Trip Points (온도 임계값)

Trip point는 특정 온도에 도달했을 때 cooling action을 트리거하는 임계값입니다.

Trip Type 설명 동작
THERMAL_TRIP_ACTIVE 능동적 냉각 시작 팬 속도 증가, 주파수 감소
THERMAL_TRIP_PASSIVE 수동적 냉각 시작 CPU 주파수 제한, GPU throttling
THERMAL_TRIP_HOT 고온 경고 로그 기록, 경고 알림
THERMAL_TRIP_CRITICAL 임계 온도 시스템 강제 종료 (orderly_poweroff)

Thermal Zone 등록

struct thermal_zone_device *
thermal_zone_device_register(
    const char *type,
    int trips,
    int mask,
    void *devdata,
    struct thermal_zone_device_ops *ops,
    struct thermal_zone_params *tzp,
    int passive_delay,
    int polling_delay
);

/* 예: ACPI Thermal Zone 등록 */
struct thermal_zone_device *tz;
tz = thermal_zone_device_register("acpitz", 4, 0xf, tz_data,
                                     &acpi_thermal_zone_ops,
                                     &acpi_thermal_params,
                                     10000, 0);

Cooling Device

thermal_cooling_device 구조체

struct thermal_cooling_device {
    int id;
    char type[THERMAL_NAME_LENGTH];
    struct device device;
    struct thermal_cooling_device_ops *ops;
    bool updated;
    unsigned long max_state;  /* 최대 cooling level */
    unsigned long cur_state;  /* 현재 cooling level */
    struct list_head node;
};

thermal_cooling_device_ops

struct thermal_cooling_device_ops {
    int (*get_max_state)(struct thermal_cooling_device *,
                         unsigned long *);
    int (*get_cur_state)(struct thermal_cooling_device *,
                         unsigned long *);
    int (*set_cur_state)(struct thermal_cooling_device *,
                         unsigned long);
    int (*get_requested_power)(struct thermal_cooling_device *,
                                struct thermal_zone_device *, u32 *);
    int (*state2power)(struct thermal_cooling_device *,
                        struct thermal_zone_device *,
                        unsigned long, u32 *);
    int (*power2state)(struct thermal_cooling_device *,
                        struct thermal_zone_device *, u32,
                        unsigned long *);
};

Cooling Device 종류

Cooling Device 등록

/* CPUFreq Cooling Device 등록 */
struct thermal_cooling_device *cdev;
struct cpumask clip_cpus;

cpumask_set_cpu(0, &clip_cpus);
cdev = cpufreq_cooling_register(&clip_cpus);

/* Fan Cooling Device 등록 */
struct thermal_cooling_device *fan_cdev;
fan_cdev = thermal_cooling_device_register("Fan", fan_data,
                                              &fan_cooling_ops);

Thermal Governor

Thermal Governor는 thermal zone의 온도에 따라 cooling device를 제어하는 정책 알고리즘입니다.

Governor 종류

Governor 설명 적용 대상
step_wise 온도 변화에 따라 단계적으로 cooling state 조정 범용 (기본값)
fair_share 여러 cooling device에 cooling 부하를 공평하게 분배 다중 cooling device
power_allocator 전력 예산 기반 제어. PID 컨트롤러 사용 모바일 SoC, ARM big.LITTLE
bang_bang On/Off 방식. 임계값 초과 시 full cooling 단순 Fan 제어
user_space userspace 데몬이 cooling 제어 커스텀 열 정책

Step-Wise Governor (기본)

step_wise governor는 온도가 trip point를 초과하면 cooling state를 한 단계씩 증가시키고, 온도가 낮아지면 한 단계씩 감소시킵니다.

/* Step-Wise Governor 알고리즘 */
if (temperature > trip_temp) {
    /* 온도 상승: cooling state 증가 */
    new_state = cur_state + 1;
    if (new_state > max_state)
        new_state = max_state;
} else {
    /* 온도 하강: cooling state 감소 */
    if (cur_state > 0)
        new_state = cur_state - 1;
}
set_cur_state(cdev, new_state);

Power Allocator Governor

ARM 모바일 SoC에서 널리 사용됩니다. PID(Proportional-Integral-Derivative) 컨트롤러를 사용해 전력 예산을 동적으로 할당합니다.

struct thermal_zone_params {
    char governor_name[THERMAL_NAME_LENGTH];
    bool no_hwmon;
    int num_tbps;
    struct thermal_bind_params *tbp;

    /* Power Allocator 전용 */
    s32 k_po;           /* PID proportional gain (overshoot) */
    s32 k_pu;           /* PID proportional gain (undershoot) */
    s32 k_i;            /* PID integral gain */
    s32 k_d;            /* PID derivative gain */
    s32 integral_cutoff;
    int sustainable_power; /* 지속 가능 전력 (mW) */
};

Governor 선택

# sysfs로 governor 변경 */
# cat /sys/class/thermal/thermal_zone0/available_policies
step_wise fair_share power_allocator bang_bang user_space

# echo power_allocator > /sys/class/thermal/thermal_zone0/policy

ACPI Thermal Zone

UEFI/ACPI 플랫폼에서는 ACPI 펌웨어가 thermal zone과 cooling method를 정의합니다.

ACPI Thermal Methods

Method 설명
_TMP 현재 온도 반환 (1/10 Kelvin 단위)
_CRT Critical 온도 임계값
_HOT Hot 온도 임계값
_PSV Passive 온도 임계값
_ACx Active cooling 임계값 (x = 0~9)
_ALx Active cooling 대응 팬 리스트
_PSL Passive cooling 대상 프로세서 리스트
_TC1, _TC2, _TSP Passive cooling 상수

ACPI Thermal Zone 예시

/* ACPI DSDT에서 Thermal Zone 정의 예시 (ASL) */
ThermalZone (TZ00) {
    Method (_TMP, 0) {
        /* EC(Embedded Controller)에서 온도 읽기 */
        Return (\_SB.PCI0.LPCB.EC0.TMP0)  /* 0.1K 단위 */
    }

    Method (_CRT) { Return (3732) }  /* 100°C (373.2K) */
    Method (_PSV) { Return (3632) }  /* 90°C */

    Method (_AC0) { Return (3532) }  /* 80°C */
    Method (_AL0) { Return (Package(){\_SB.FAN0}) }

    Name (_PSL, Package(){\_SB.CPU0, \_SB.CPU1})  /* Passive 대상 CPU */
}

sysfs 인터페이스

Thermal Zone sysfs

Thermal Zone sysfs /sys/class/thermal/thermal_zone0/ 기본 상태/정책 type (예: acpitz) temp (milli-Celsius) mode (enabled/disabled) policy / available_policies passive (지연 msec) Trip/Cooling 바인딩 trip_point_0_type trip_point_0_temp cdev0_trip_point cdev0_weight

Cooling Device sysfs

Cooling Device sysfs /sys/class/thermal/cooling_device0/ 상태 정보 type (Processor/Fan 등) max_state cur_state device -> ../../../devices/... 통계 정보 stats/ (CONFIG_THERMAL_STATISTICS) time_in_state_ms trans_table

sysfs 사용 예시

# 모든 thermal zone 온도 확인
# for tz in /sys/class/thermal/thermal_zone*; do
    echo "$tz: $(cat $tz/type) = $(cat $tz/temp | awk '{print $1/1000}')°C"
done

# Cooling device 상태 확인
# cat /sys/class/thermal/cooling_device0/type
Processor
# cat /sys/class/thermal/cooling_device0/cur_state
0
# cat /sys/class/thermal/cooling_device0/max_state
10

# Governor 변경
# echo power_allocator > /sys/class/thermal/thermal_zone0/policy

hwmon 통합

Thermal 서브시스템은 hwmon 센서와 통합되어 다양한 온도 센서를 thermal zone으로 노출할 수 있습니다.

/* hwmon thermal zone 자동 생성 (CONFIG_THERMAL_HWMON) */
struct thermal_hwmon_device {
    struct device *device;
    int count;
    struct list_head tz_list;
    struct list_head node;
};

/* /sys/class/hwmon/hwmon0/temp1_input과 연동 */

CPU Frequency Cooling

CPUFreq cooling device는 CPU 주파수를 제한하여 온도를 낮춥니다.

CPUFreq Cooling 등록

#include <linux/cpu_cooling.h>

struct thermal_cooling_device *cdev;
struct cpumask clip_cpus;
struct cpufreq_policy *policy;

policy = cpufreq_cpu_get(0);
cpumask_copy(&clip_cpus, policy->related_cpus);
cpufreq_cpu_put(policy);

/* Cooling device 등록 */
cdev = cpufreq_cooling_register(&clip_cpus);
if (IS_ERR(cdev))
    return PTR_ERR(cdev);

/* OPP 기반 cooling (전력 인식) */
cdev = of_cpufreq_cooling_register(np, &clip_cpus);

Cooling State와 주파수 매핑

CPUFreq cooling device는 가용 주파수를 cooling state로 매핑합니다.

/* 예: max_state=10, 가용 주파수가 11개라면 */
State 0: 2400 MHz  /* 최대 주파수 */
State 1: 2200 MHz
State 2: 2000 MHz
...
State 10: 400 MHz  /* 최소 주파수 */

Devfreq Cooling

GPU, Memory Controller 등 devfreq 장치를 cooling device로 등록합니다.

#include <linux/devfreq_cooling.h>

struct thermal_cooling_device *
devfreq_cooling_register(struct devfreq *df,
                          struct devfreq_cooling_power *dfc_power);

/* GPU devfreq cooling 등록 */
struct devfreq *gpu_devfreq;
struct thermal_cooling_device *gpu_cdev;

gpu_cdev = devfreq_cooling_register(gpu_devfreq, NULL);

Thermal Interrupts

일부 하드웨어는 온도 임계값 도달 시 인터럽트를 발생시킵니다.

Thermal IRQ 처리

static irqreturn_t thermal_zone_irq_handler(int irq, void *data)
{
    struct thermal_zone_device *tz = data;

    /* 온도 업데이트 트리거 */
    thermal_zone_device_update(tz, THERMAL_EVENT_UNSPECIFIED);

    return IRQ_HANDLED;
}

/* 인터럽트 등록 */
devm_request_threaded_irq(dev, irq, NULL,
                           thermal_zone_irq_handler,
                           IRQF_ONESHOT, "thermal", tz);

커널 5.9+에서 thermal 이벤트를 netlink로 userspace에 전달합니다.

#include <linux/thermal.h>

/* Thermal Netlink 이벤트 */
enum thermal_notify_event {
    THERMAL_EVENT_UNSPECIFIED,
    THERMAL_EVENT_TEMP_SAMPLE,       /* 온도 샘플링 */
    THERMAL_TRIP_VIOLATED,           /* trip point 초과 */
    THERMAL_TRIP_CHANGED,            /* trip point 변경 */
    THERMAL_DEVICE_DOWN,             /* thermal zone 비활성화 */
    THERMAL_DEVICE_UP,               /* thermal zone 활성화 */
    THERMAL_DEVICE_NEW,              /* 새 thermal zone 등록 */
    THERMAL_DEVICE_DEL,              /* thermal zone 제거 */
};

/* Netlink 그룹: THERMAL_GENL_SAMPLING_GROUP, THERMAL_GENL_EVENT_GROUP */

디버깅 & 모니터링

Tracing

# Thermal tracepoint 활성화
# cd /sys/kernel/debug/tracing
# echo 1 > events/thermal/enable

# 주요 tracepoint
thermal_temperature         # 온도 샘플링
thermal_zone_trip           # trip point 도달
cdev_update                 # cooling device 상태 변경
thermal_power_allocator     # power allocator governor

# trace 출력
# cat trace
     kworker/0:1-123 [000] .... 123.456: thermal_temperature: thermal_zone=acpitz temp=55000

실시간 모니터링

#!/bin/bash
# thermal_monitor.sh - 실시간 온도 모니터링

while true; do
    clear
    echo "===== Thermal Status ====="

    for tz in /sys/class/thermal/thermal_zone*; do
        type=$(cat $tz/type)
        temp=$(cat $tz/temp)
        policy=$(cat $tz/policy 2>/dev/null || echo "N/A")

        printf "%-20s: %6.2f°C  Governor: %s\\n" \
               "$type" $(awk "BEGIN {print $temp/1000}") "$policy"
    done

    echo
    echo "===== Cooling Devices ====="
    for cdev in /sys/class/thermal/cooling_device*; do
        type=$(cat $cdev/type)
        cur=$(cat $cdev/cur_state)
        max=$(cat $cdev/max_state)

        printf "%-20s: %2d / %2d\\n" "$type" "$cur" "$max"
    done

    sleep 1
done

thermald (Thermal Daemon)

Intel thermald는 userspace thermal management 데몬입니다.

# thermald 설치 (Ubuntu/Debian)
# apt install thermald

# 서비스 상태 확인
# systemctl status thermald

# 설정 파일: /etc/thermald/thermal-conf.xml
# 로그: journalctl -u thermald

성능 고려사항

Polling Delay 조정

온도 폴링 주기는 응답 속도와 CPU 오버헤드 사이의 트레이드오프입니다.

/* 폴링 주기 예시 */
passive_delay = 10000;  /* 10초 (passive cooling 시) */
polling_delay = 0;       /* 0 = 인터럽트 기반 */

Hysteresis (히스테리시스)

온도가 임계값 근처에서 진동할 때 cooling device가 계속 on/off되는 것을 방지합니다.

struct thermal_trip {
    int temperature;        /* trip 온도 */
    int hysteresis;         /* 히스테리시스 (milli-Celsius) */
    enum thermal_trip_type type;
};

/* 예: trip_temp=80°C, hysteresis=5°C */
/*   → 85°C 초과 시 cooling 시작 */
/*   → 75°C 이하로 떨어지면 cooling 중단 */

커널 설정

CONFIG_THERMAL=y                       # Thermal 서브시스템
CONFIG_THERMAL_HWMON=y                 # hwmon 통합
CONFIG_THERMAL_GOV_STEP_WISE=y         # Step-Wise Governor
CONFIG_THERMAL_GOV_FAIR_SHARE=y        # Fair-Share Governor
CONFIG_THERMAL_GOV_POWER_ALLOCATOR=y   # Power Allocator Governor
CONFIG_THERMAL_GOV_BANG_BANG=y         # Bang-Bang Governor
CONFIG_THERMAL_GOV_USER_SPACE=y        # Userspace Governor
CONFIG_CPU_THERMAL=y                   # CPUFreq Cooling
CONFIG_DEVFREQ_THERMAL=y               # Devfreq Cooling
CONFIG_THERMAL_EMULATION=y             # 온도 에뮬레이션 (테스트용)
CONFIG_THERMAL_STATISTICS=y            # Cooling 통계

# 플랫폼 특화
CONFIG_ACPI_THERMAL=y                  # ACPI Thermal Zone
CONFIG_INTEL_POWERCLAMP=y              # Intel Idle Injection
CONFIG_X86_PKG_TEMP_THERMAL=y          # Intel Package Temperature
CONFIG_INT340X_THERMAL=y               # Intel INT3400/INT3403 DPTF

Common Issues

주의: Thermal 서브시스템 오류는 하드웨어 손상을 초래할 수 있습니다.
  • Critical 온도 미설정_CRT 메서드 누락 시 시스템이 과열로 손상될 수 있음
  • Passive Cooling 무한 루프 — 너무 짧은 passive_delay로 CPU 부하 증가
  • Cooling Device 미바인딩 — thermal zone과 cooling device가 연결되지 않아 cooling 동작 안 함
  • ACPI Thermal Zone 초기화 실패 — BIOS 버그로 _TMP 메서드 실패

Troubleshooting

# Thermal zone 정보 확인
# cat /sys/class/thermal/thermal_zone0/type
# cat /sys/class/thermal/thermal_zone0/temp
# cat /sys/class/thermal/thermal_zone0/mode

# Cooling device 바인딩 확인
# ls -l /sys/class/thermal/thermal_zone0/cdev*

# ACPI thermal zone 디버깅
# dmesg | grep -i thermal
# dmesg | grep -i acpi

# Thermal emulation (테스트용)
# echo 85000 > /sys/class/thermal/thermal_zone0/emul_temp

참고자료

다음 학습: