RAPL & powercap

Linux powercap 프레임워크와 Intel RAPL의 실전 활용을 다룹니다. package/core/uncore/DRAM 도메인별 에너지 카운터 해석, PL1·PL2·time window 기반 전력 제한 모델, MSR·sysfs·hwmon 인터페이스 사용법, thermal·cpufreq와의 상호작용, 전력 캡 적용 시 성능 회귀 검증, 데이터센터 전력 예산 운영 시나리오와 모니터링 지표까지 종합적으로 정리합니다.

전제 조건: 전원관리Thermal 서브시스템 문서를 먼저 읽으세요. 전력/열 관리(Thermal Management) 주제는 성능과 안정성의 절충이 핵심이므로, 제어 루프와 임계값 정책을 함께 이해해야 운영 사고를 줄일 수 있습니다.
일상 비유: 이 주제는 건물 냉난방과 전력 피크 제어와 비슷합니다. 쾌적함과 전력 비용을 함께 맞추듯이, 커널도 성능과 열 한계를 동시에 고려해 동작합니다.

핵심 요약

  • RAPL (Running Average Power Limit) — Intel/AMD 프로세서의 하드웨어 전력 모니터링 및 제한 인터페이스입니다.
  • powercap 프레임워크 — 커널의 통합 전력 상한 설정 인터페이스. RAPL이 대표적인 백엔드입니다.
  • 전력 도메인(Power Domain) — package(전체 소켓(Socket)), core(CPU 코어), dram(메모리), uncore(iGPU) 등으로 분리하여 측정합니다.
  • PL1/PL2 — 장기(Long-Term) 및 단기(Short-Term) 전력 제한. TDP와 Turbo 성능을 제어합니다.
  • 에너지 카운터 — 마이크로줄(μJ) 단위로 실시간(Real-time) 에너지 소비를 측정하여 전력 효율을 분석합니다.

단계별 이해

  1. 현재 전력 확인cat /sys/class/powercap/intel-rapl:0/energy_uj로 현재 소비 에너지를 확인합니다.

    또는 turbostat --show Package,Core,Uncore --interval 1로 실시간 전력을 모니터링합니다.

  2. 도메인별 측정perf stat -e power/energy-pkg/,power/energy-cores/ ./workload로 워크로드의 에너지 소비를 측정합니다.

    package와 core 도메인을 분리하여 CPU vs 언코어 전력 비중을 파악합니다.

  3. 전력 제한 설정echo 25000000 > /sys/class/powercap/intel-rapl:0/constraint_0_power_limit_uw로 PL1을 25W로 제한합니다.

    열 문제나 배터리 수명 연장이 필요할 때 TDP를 동적으로 조절합니다.

  4. 효과 검증 — 전력 제한 전후로 벤치마크 성능과 온도/전력을 비교합니다.

    stress-ng --cpu 8 --timeout 60s로 부하를 주고 turbostat로 차이를 확인하세요.

관련 표준: Intel SDM Vol.4 (전력 관리 MSR) — RAPL은 Intel/AMD 프로세서의 하드웨어 전력 관리 인터페이스입니다. 종합 목록은 참고자료 — 표준 & 규격 섹션을 참고하세요.
교차 참조: 전원 관리(Power Management) 기초는 전원 관리, MSR 레지스터(Register) 접근은 MSR, CPU 토폴로지(Topology)는 CPU 토폴로지 페이지(Page)를 참조하십시오.

powercap & RAPL

powercap 프레임워크는 전력 상한(power capping)을 설정하는 통합 인터페이스를 제공합니다. 가장 대표적인 백엔드는 Intel/AMD의 RAPL(Running Average Power Limit)로, 프로세서 패키지·코어·메모리 등 전력 도메인별 에너지 소비를 모니터링하고 제한할 수 있습니다.

powercap/RAPL 아키텍처

RAPL은 하드웨어 MSR(또는 TPMI)에서 에너지 카운터와 전력 제한을 읽고 쓰는 커널 드라이버를 통해 powercap 프레임워크에 등록됩니다. 사용자 공간(User Space)은 sysfs 또는 perf 이벤트를 통해 접근합니다.

Userspace perf stat power/ turbostat powertop /sys/class/powercap/ powercap sysfs write powercap Framework (drivers/powercap/powercap_sys.c) intel_rapl_common.c (RAPL 코어 로직) perf_event_intel_rapl.c (PMU 드라이버) powercap_zone ops perf PMU intel_rapl_msr.c intel_rapl_tpmi.c amd_energy.c Hardware MSR (606h, 610h, 619h …) TPMI (Intel Meteor Lake+) MSR (C001_0299h, Family 17h+)

RAPL 도메인

RAPL은 프로세서 내부를 여러 전력 도메인(power domain)으로 분리하여 도메인별 에너지 측정과 전력 제한을 제공합니다. 지원 도메인은 프로세서 세대에 따라 다릅니다.

도메인설명IntelAMD
package소켓 전체 (CPU + 언코어 + iGPU)Sandy Bridge+ (2세대+)Zen (Family 17h+)
core (PP0)CPU 코어만Sandy Bridge+Zen+
uncore (PP1)iGPU / 언코어클라이언트 전용 (Sandy Bridge+)
dram메모리 컨트롤러/DRAM서버 (Sandy Bridge-EP+), 클라이언트 (Haswell+)
psys플랫폼 전체 (SoC + PCH)Skylake+ (모바일/NUC)
참고: psys 도메인은 CPU뿐 아니라 PCH, 온보드 디바이스를 포함한 플랫폼 전체 전력을 측정합니다. 노트북/NUC 등 배터리 기반 시스템에서 전체 시스템 전력 예산(power budget) 관리에 유용합니다.

도메인별 전력 분포

워크로드 유형에 따라 도메인별 전력 소비 비중이 크게 달라집니다. 다음은 실제 측정 데이터입니다:

워크로드PackageCoreUncore (iGPU)DRAM특징
Idle (유휴)8W2W (25%)3W (37%)3W (37%)백그라운드 활동
CPU 집약 (컴파일)65W48W (74%)10W (15%)7W (11%)코어 전력 지배적
메모리 집약 (STREAM)45W20W (44%)8W (18%)17W (38%)DRAM 전력 증가
GPU 렌더링 (iGPU)55W15W (27%)32W (58%)8W (15%)Uncore 전력 급증
혼합 (웹 브라우징)25W12W (48%)8W (32%)5W (20%)균형 분포

측정 환경: Intel Core i7-1165G7 (Tiger Lake, 28W TDP), DDR4-3200 16GB, 유휴 배경 프로세스(Process) 최소화

실무 인사이트:
  • CPU 집약적 워크로드는 Core 도메인이 70% 이상 차지 — CPU 주파수/전압 최적화가 효과적
  • 메모리 집약적 워크로드는 DRAM이 30~40% — 메모리 주파수 낮추기로 절전 가능
  • iGPU 활성 시 Uncore가 50% 이상 — 외장 GPU 사용 시 iGPU 비활성화로 10W 이상 절감
  • Idle 시에도 8W 소비 — C-state 진입 최적화와 디바이스 runtime PM 중요

RAPL MSR 레지스터 완전 참조

RAPL은 MSR(Model-Specific Register)을 통해 에너지 카운터, 전력 제한, 단위 정보에 접근합니다. 각 도메인별로 별도의 MSR 주소가 할당되며, 비트 필드 레이아웃은 도메인 간에 유사한 구조를 공유합니다.

MSR 이름주소도메인읽기쓰기설명
MSR_RAPL_POWER_UNIT0x606공통OX에너지/전력/시간 단위 정의
MSR_PKG_POWER_LIMIT0x610PackageOOPL1/PL2 전력 제한 설정
MSR_PKG_ENERGY_STATUS0x611PackageOX누적 에너지 카운터
MSR_PKG_PERF_STATUS0x613PackageOX전력 제한으로 인한 스로틀 시간
MSR_PKG_POWER_INFO0x614PackageOXTDP, 최소/최대 전력 정보
MSR_DRAM_POWER_LIMIT0x618DRAMOODRAM 전력 제한
MSR_DRAM_ENERGY_STATUS0x619DRAMOXDRAM 에너지 카운터
MSR_PP0_POWER_LIMIT0x638Core (PP0)OO코어 전력 제한
MSR_PP0_ENERGY_STATUS0x639Core (PP0)OX코어 에너지 카운터
MSR_PP1_POWER_LIMIT0x640Uncore (PP1)OOUncore/iGPU 전력 제한
MSR_PP1_ENERGY_STATUS0x641Uncore (PP1)OXUncore 에너지 카운터
MSR_PLATFORM_ENERGY_STATUS0x64DPlatform (psys)OX플랫폼 전체 에너지
MSR_PLATFORM_POWER_LIMIT0x65CPlatform (psys)OO플랫폼 전력 제한

MSR_RAPL_POWER_UNIT (0x606) 비트 필드

비트필드설명기본값 (일반적)
[3:0]Power Units전력 단위: 1 / 2N 와트. N=3이면 1/8 W = 0.125 W3 (0.125 W)
[7:4]Reserved예약
[12:8]Energy Status Units에너지 단위: 1 / 2N 줄. N=16이면 ~15.3 μJ16 (~15.3 μJ)
[15:13]Reserved예약
[19:16]Time Units시간 단위: 1 / 2N 초. N=10이면 ~976 μs10 (~976 μs)
[63:20]Reserved예약

MSR_PKG_POWER_LIMIT (0x610) 비트 필드

비트필드설명
[14:0]PL1 Power Limit장기 전력 제한 (Power Units 단위)
[15]PL1 EnablePL1 활성화 (1=활성)
[16]PL1 Clamping1이면 OS 요청 주파수 이하로도 제한 가능
[23:17]PL1 Time WindowY × 2Z × Time Unit (Y=[23:22], Z=[21:17])
[31:24]Reserved예약
[46:32]PL2 Power Limit단기 전력 제한 (Power Units 단위)
[47]PL2 EnablePL2 활성화
[48]PL2 ClampingPL2 클램핑 활성화
[55:49]PL2 Time WindowPL2 시간 윈도우
[62:56]Reserved예약
[63]Lock1이면 재부팅까지 MSR 쓰기 잠금(Lock)
# MSR 직접 읽기 예제 (msr-tools 패키지 필요)
sudo modprobe msr

# MSR_RAPL_POWER_UNIT 읽기
sudo rdmsr 0x606
# 예: a0e03  →  bits[3:0]=3, bits[12:8]=0xe(14), bits[19:16]=0xa(10)
# Power Unit = 1/2^3 = 0.125 W
# Energy Unit = 1/2^14 = 61.0 μJ (서버)  또는 1/2^16 = 15.3 μJ (클라이언트)
# Time Unit = 1/2^10 = 976.6 μs
# 비트 필드 추출 예제
UNIT=$(sudo rdmsr 0x606)

# Power Unit 추출 (bits 3:0)
POWER_UNIT=$(( 0x${UNIT} & 0xF ))
echo "Power Unit: 1/2^${POWER_UNIT} W = $(echo "scale=4; 1/2^${POWER_UNIT}" | bc) W"

# Energy Unit 추출 (bits 12:8)
ENERGY_UNIT=$(( (0x${UNIT} >> 8) & 0x1F ))
echo "Energy Unit: 1/2^${ENERGY_UNIT} J"

# Time Unit 추출 (bits 19:16)
TIME_UNIT=$(( (0x${UNIT} >> 16) & 0xF ))
echo "Time Unit: 1/2^${TIME_UNIT} s"
# PL1/PL2 비트 필드 조작
PL=$(sudo rdmsr 0x610)

# PL1 값 추출 (bits 14:0)
PL1_RAW=$(( 0x${PL} & 0x7FFF ))
PL1_W=$(echo "scale=2; ${PL1_RAW} * 0.125" | bc)
echo "PL1: ${PL1_W} W (raw: ${PL1_RAW})"

# PL1 Enable 확인 (bit 15)
PL1_EN=$(( (0x${PL} >> 15) & 1 ))
echo "PL1 Enabled: ${PL1_EN}"

# Lock 비트 확인 (bit 63)
LOCK=$(( (0x${PL} >> 63) & 1 ))
echo "Lock: ${LOCK} (1이면 BIOS가 잠금, 수정 불가)"
Lock 비트: BIOS가 MSR_PKG_POWER_LIMIT의 bit[63]을 1로 설정하면 재부팅까지 PL1/PL2 변경이 불가합니다. 이 경우 powercap sysfs 쓰기도 실패합니다. 서버 BIOS에서 "RAPL Lock" 옵션을 비활성화해야 OS 레벨 제어가 가능합니다.

에너지 카운터: 단위 변환·오버플로

RAPL 에너지 카운터(MSR_*_ENERGY_STATUS)는 32비트 카운터로, MSR_RAPL_POWER_UNIT에서 정의된 에너지 단위만큼 증가합니다. 카운터가 최대값에 도달하면 0으로 랩어라운드(wrap-around)하므로, 정확한 에너지 측정을 위해 오버플로 처리가 필수적입니다.

/* 에너지 단위 변환 — MSR 원시 값 → μJ */
static u64 rapl_raw_to_uj(u32 raw, u32 energy_unit)
{
    /*
     * energy_unit = MSR_RAPL_POWER_UNIT bits[12:8]
     * 에너지 단위 = 1 / 2^energy_unit (줄)
     * μJ 변환 = raw × (1 / 2^energy_unit) × 1000000
     *         = raw × 1000000 >> energy_unit
     */
    return (u64)raw * 1000000ULL >> energy_unit;
}

/* 예시: energy_unit=16, raw=0x10000 (65536)
 * = 65536 × 1000000 / 65536 = 1000000 μJ = 1 J */
/* 오버플로 처리 — 32비트 카운터 랩어라운드 감지 */
static u64 rapl_energy_delta(u32 curr, u32 prev, u32 energy_unit)
{
    u32 delta;

    if (curr >= prev) {
        delta = curr - prev;
    } else {
        /* 오버플로 발생: max_value - prev + curr + 1 */
        delta = (0xFFFFFFFF - prev) + curr + 1;
    }

    return rapl_raw_to_uj(delta, energy_unit);
}

/* 커널 intel_rapl_common.c에서의 실제 구현:
 * rapl_compute_energy_delta()는 이전 값과 현재 값을 비교하여
 * 자동으로 오버플로를 감지하고 올바른 delta를 계산합니다. */
# 셸에서 에너지 delta 계산 (오버플로 처리 포함)
MAX_ENERGY=$(cat /sys/class/powercap/intel-rapl:0/max_energy_range_uj)

E1=$(cat /sys/class/powercap/intel-rapl:0/energy_uj)
sleep 5
E2=$(cat /sys/class/powercap/intel-rapl:0/energy_uj)

if [ $E2 -ge $E1 ]; then
    DELTA=$(( E2 - E1 ))
else
    # 오버플로 발생
    DELTA=$(( MAX_ENERGY - E1 + E2 ))
fi

WATTS=$(( DELTA / 5000000 ))
echo "5초간 소비: $(( DELTA / 1000000 )) J, 평균 전력: ${WATTS} W"
전력 수준에너지 단위32비트 오버플로 시간권장 폴링(Polling) 간격
15W (노트북 idle)15.3 μJ~18.3시간60초
65W (데스크톱 TDP)15.3 μJ~4.2시간60초
150W (서버 소켓)61.0 μJ~29분10초
300W (고성능 서버)61.0 μJ~14.5분5초
500W (듀얼소켓)61.0 μJ~8.7분3초
실무 팁: 커널 드라이버(intel_rapl_common)는 내부적으로 64비트 누적 카운터를 유지하여 32비트 오버플로를 자동 처리합니다. 그러나 사용자 공간에서 energy_uj를 직접 폴링하는 경우, max_energy_range_uj에 도달하면 0으로 리셋되므로 폴링 간격을 오버플로 시간의 절반 이하로 설정해야 합니다.

PL1/PL2/PL3/PL4 전력 제한 계층

RAPL은 최대 4단계의 전력 제한(Power Limit)을 제공합니다. 각 단계는 허용 전력과 시간 윈도우가 다르며, 하드웨어가 자율적으로 스로틀링을 적용합니다.

레벨명칭시간 윈도우동작 방식MSR
PL1Long-Term (장기)1~128초 (설정 가능)지속 가능한 TDP. 윈도우 내 평균 전력이 PL1 이하 유지MSR_PKG_POWER_LIMIT [14:0]
PL2Short-Term (단기)1~10ms 수준Turbo Boost 시 허용하는 순간 최대 전력. PL1의 1.2~1.5배MSR_PKG_POWER_LIMIT [46:32]
PL3Peak Power (피크)~10ms배터리 기반 시스템의 순간 피크 제한 (Kaby Lake+)MSR_PL3_CONTROL
PL4Max Power (최대)즉시하드웨어 즉시 차단 — 전류/전력 한계 초과 시 주파수 급강하MSR_VR_CURRENT_CONFIG

PL 전력 제한 타임라인

다음 다이어그램은 워크로드 시작 시 PL1/PL2/PL4가 시간에 따라 어떻게 작동하는지 보여줍니다:

0W 15W 30W 45W 60W 75W 90W 전력 (W) 0s 2s 5s 10s 20s 시간 (초) PL4 (90W) 즉시 차단 PL2 (65W) ~10ms PL1 (45W) 장기 평균 Turbo Boost 워크로드 시작 PL2 윈도우 종료 PL1 수렴 실제 전력 소비 패턴 실제 소비 PL1 (Long-Term) PL2 (Short-Term)
동작 설명: 워크로드 시작 직후 CPU는 Turbo Boost를 활성화하여 PL2(65W) 근처까지 순간 전력을 사용합니다. 약 2초(PL2 시간 윈도우) 후 하드웨어는 전력을 PL1(45W)로 제한하기 시작하며, 10초 정도 지나면 장기 평균 전력이 PL1에 수렴합니다. PL4(90W)는 전류 한계를 넘으면 즉시 주파수를 급강하시키는 보호 메커니즘입니다.
/* powercap sysfs에서 PL1/PL2 확인 및 설정 */

# PL1 (constraint_0) 확인
cat /sys/class/powercap/intel-rapl:0/constraint_0_name          # "long_term"
cat /sys/class/powercap/intel-rapl:0/constraint_0_power_limit_uw  # 현재 PL1 (μW)
cat /sys/class/powercap/intel-rapl:0/constraint_0_time_window_us  # 시간 윈도우 (μs)

# PL2 (constraint_1) 확인
cat /sys/class/powercap/intel-rapl:0/constraint_1_name          # "short_term"
cat /sys/class/powercap/intel-rapl:0/constraint_1_power_limit_uw

# PL1을 15W로 설정 (root 권한 필요)
echo 15000000 > /sys/class/powercap/intel-rapl:0/constraint_0_power_limit_uw
주의: PL1/PL2 값을 무리하게 높이면 과열 및 thermal throttling이 발생합니다. 반대로 PL1을 지나치게 낮추면 성능이 심각하게 저하됩니다. PL3/PL4는 대부분 BIOS/펌웨어(Firmware)가 설정하며 커널에서 직접 제어하지 않습니다.

powercap sysfs 인터페이스

RAPL powercap sysfs 계층 구조 /sys/class/powercap/ intel-rapl:0/ (package-0) 공통 속성 name = "package-0" energy_uj 누적 에너지 (읽기 전용, μJ) max_energy_range_uj 오버플로 범위 enabled 도메인 활성화 여부 (0/1) constraint_0 (long_term = PL1) power_limit_uw time_window_us max_power_uw constraint_1 (short_term = PL2) power_limit_uw time_window_us max_power_uw :0:0/ :0:1/ :0:2/ core (PP0) name="core" energy_uj uncore (PP1) name="uncore" energy_uj dram (PP2) name="dram" energy_uj PL1 / PL2 전력 제한 비교 구분 constraint_0 (PL1) constraint_1 (PL2) 이름 long_term short_term 시간 윈도우 ~28초 (BIOS 기본값) ~2.44ms 용도 지속 전력 제한 (TDP 상당) 순간 버스트 전력 제한 쓰기 예시 echo 65000000 > constraint_0_power_limit_uw echo 95000000 > constraint_1_power_limit_uw

RAPL 커널 드라이버 구조

커널의 RAPL 지원은 공통 로직과 하드웨어 백엔드로 분리된 모듈러 구조입니다.

모듈경로역할
intel_rapl_commondrivers/powercap/intel_rapl_common.cRAPL 도메인 관리, powercap zone 등록, 에너지 단위 변환, PL 읽기/쓰기 공통 로직
intel_rapl_msrdrivers/powercap/intel_rapl_msr.cMSR 기반 백엔드 — 대부분의 Intel/AMD CPU. rdmsr/wrmsr로 RAPL MSR 접근
intel_rapl_tpmidrivers/powercap/intel_rapl_tpmi.cTPMI(Topology Aware Register and PM Capsule Interface) 백엔드 — Meteor Lake+ MMIO 기반
amd_energydrivers/hwmon/amd_energy.cAMD Zen hwmon 드라이버 (powercap 미사용, hwmon으로 에너지 노출)
/* intel_rapl_common.c — 핵심 구조체 */
struct rapl_domain {
    const char          *name;
    enum rapl_domain_type id;        /* RAPL_DOMAIN_PACKAGE, PP0, PP1, DRAM, PLATFORM */
    u64                  energy_unit;  /* 에너지 단위 (MSR_RAPL_POWER_UNIT에서 파생) */
    u64                  power_unit;   /* 전력 단위 */
    struct powercap_zone power_zone;  /* powercap 프레임워크 zone */
    struct rapl_package  *rp;         /* 소속 패키지 */
};

struct rapl_package {
    unsigned int          id;          /* 패키지(소켓) ID */
    unsigned int          nr_domains;  /* 이 패키지의 도메인 수 */
    struct rapl_domain    *domains;    /* 도메인 배열 */
    struct rapl_if_priv  *priv;       /* 백엔드별 private 데이터 */
};
# RAPL 모듈 로드 확인
lsmod | grep rapl
# intel_rapl_msr         20480  0
# intel_rapl_common      36864  1 intel_rapl_msr
# powercap               16384  1 intel_rapl_common

# 에너지 단위 확인 (MSR_RAPL_POWER_UNIT, 606h)
rdmsr 0x606
# 결과 해석: bits[12:8]=에너지 단위, bits[3:0]=전력 단위, bits[19:16]=시간 단위

powercap 드라이버 작성 가이드

커널의 powercap 프레임워크는 RAPL 외에도 커스텀 전력 상한 백엔드를 등록할 수 있는 API를 제공합니다. FPGA 전력 관리, 배터리 기반 시스템, 또는 BMC 연동 전력 제어 등을 구현할 때 powercap 드라이버를 작성하면 표준 sysfs 인터페이스를 자동으로 제공받습니다.

1 module_init() 2 powercap_register_control_type() 3 powercap_register_zone() /sys/class/powercap/my-driver:0/ sysfs 자동 생성 (energy_uj, constraint_*) powercap_zone_ops 콜백 get_energy_uj() get_max_energy_range_uj() set_enable() get_enable() release() 호출 powercap_zone_constraint_ops 콜백 set_power_limit_uw get_power_limit_uw set_time_window_us 4 (cleanup) powercap_unregister_zone/control_type
/* 최소 powercap 드라이버 스켈레톤 */
#include <linux/module.h>
#include <linux/powercap.h>

static struct powercap_control_type *my_ctrl;
static struct powercap_zone my_zone;
static u64 my_energy_uj;
static u64 my_power_limit_uw = 50000000; /* 50W 기본값 */

/* zone ops 구현 */
static int my_get_energy(struct powercap_zone *z, u64 *uj) {
    *uj = my_energy_uj;  /* 실제로는 하드웨어 레지스터 읽기 */
    return 0;
}

static int my_get_max_energy(struct powercap_zone *z, u64 *uj) {
    *uj = 262143328850;  /* 오버플로 범위 */
    return 0;
}

static struct powercap_zone_ops my_zone_ops = {
    .get_energy_uj       = my_get_energy,
    .get_max_energy_range_uj = my_get_max_energy,
};
/* constraint ops 구현 — PL1에 해당 */
static int my_set_power_limit(struct powercap_zone *z, int cid, u64 uw) {
    my_power_limit_uw = uw;
    /* 하드웨어에 전력 제한 적용 */
    pr_info("my_powercap: power limit set to %llu uW\n", uw);
    return 0;
}

static int my_get_power_limit(struct powercap_zone *z, int cid, u64 *uw) {
    *uw = my_power_limit_uw;
    return 0;
}

static const char *my_get_name(struct powercap_zone *z, int cid) {
    return "long_term";
}

static struct powercap_zone_constraint_ops my_const_ops = {
    .set_power_limit_uw  = my_set_power_limit,
    .get_power_limit_uw  = my_get_power_limit,
    .get_name            = my_get_name,
};
/* 모듈 초기화/정리 */
static int __init my_powercap_init(void)
{
    /* 1. control type 등록 */
    my_ctrl = powercap_register_control_type(NULL, "my-driver", NULL);
    if (IS_ERR(my_ctrl))
        return PTR_ERR(my_ctrl);

    /* 2. zone 등록 (부모 zone = NULL → 최상위) */
    if (!powercap_register_zone(&my_zone, my_ctrl,
            "zone-0",     /* zone 이름 */
            NULL,          /* 부모 zone (없으면 최상위) */
            &my_zone_ops,  /* zone 콜백 */
            1,             /* constraint 수 */
            &my_const_ops  /* constraint 콜백 */
    )) {
        powercap_unregister_control_type(my_ctrl);
        return -ENODEV;
    }
    /* → /sys/class/powercap/my-driver:0/ 자동 생성 */
    pr_info("my_powercap: registered\n");
    return 0;
}

static void __exit my_powercap_exit(void)
{
    powercap_unregister_zone(my_ctrl, &my_zone);
    powercap_unregister_control_type(my_ctrl);
}

module_init(my_powercap_init);
module_exit(my_powercap_exit);
MODULE_LICENSE("GPL");
콜백(Callback)필수설명
get_energy_uj필수현재 누적 에너지를 μJ 단위로 반환
get_max_energy_range_uj필수에너지 카운터 오버플로 범위 반환
set_enable / get_enable선택zone 활성화/비활성화 제어
release선택zone 해제 시 리소스 정리
set_power_limit_uw선택전력 제한 설정 (μW)
get_power_limit_uw선택현재 전력 제한 읽기
set_time_window_us선택시간 윈도우 설정 (μs)
get_time_window_us선택현재 시간 윈도우 읽기
get_max_power_uw선택최대 허용 전력 반환
get_name필수constraint 이름 반환 ("long_term" 등)
팁: 서브 zone을 등록하려면 powercap_register_zone()의 부모 zone 인자에 상위 zone 포인터를 전달합니다. 이를 통해 RAPL과 유사한 package → core 계층 구조를 구현할 수 있습니다.

TPMI (Topology Aware Register and PM Capsule Interface)

TPMI는 Intel Meteor Lake(클라이언트, 2023) 및 Sapphire Rapids(서버, 4세대 Xeon) 이후 도입된 MMIO 기반 PM 레지스터 인터페이스입니다. PCIe 표준 기반의 아키텍처 모델로 설계되어, 기존 MSR의 모델별 코드 유지보수 부담을 줄이고 멀티 다이/칩렛 아키텍처에서 다이별(per-die) 세밀한 전력 관리를 지원합니다. Granite Rapids(Xeon 6 P-core), Sierra Forest(Xeon 6 E-core), Clearwater Forest 등 후속 세대에서 전면 채택되었습니다.

핵심 차이: MSR은 CPU별(rdmsr/wrmsr) 직렬 접근이지만, TPMI는 PCI MMIO BAR를 통해 토폴로지 인식(topology-aware) 병렬 접근이 가능합니다. RAPL뿐 아니라 SST, Uncore 주파수 제어, 성능 제한 사유(PLR) 등 다양한 PM 기능이 TPMI를 통해 통합 제공됩니다.

TPMI vs MSR 비교

항목MSR 방식TPMI 방식
접근 방식rdmsr/wrmsr (CPU 명령어)MMIO (readq/writeq, PCI BAR 매핑(Mapping))
토폴로지CPU별 (per-CPU), IPI로 원격 CPU 접근다이별 (per-die), 직접 MMIO 매핑
확장성다이 수 증가 시 MSR 주소 충돌 우려PCI VSEC + PFS로 동적 열거, 다이별 독립 주소 공간(Address Space)
병렬 접근MSR 접근은 직렬화 (serialize)서로 다른 다이의 MMIO에 동시 접근 가능
기능 발견CPUID + MSR 존재 여부 수동 확인PFS(PM Feature Structure)로 자동 열거
디바이스 모델직접 MSR 접근, 플랫폼 디바이스 없음PCI auxiliary 디바이스로 등록, 표준 드라이버 모델
유지보수CPU 모델별 MSR 테이블 유지 필요아키텍처 인터페이스 — 세대 간 호환 유지
토폴로지 계층소켓 → CPU (flat)소켓 → 다이 → 전력 도메인 → 패브릭 클러스터
지원 범위Sandy Bridge (2011) 이후 전 세대Meteor Lake/Sapphire Rapids (2023) 이후

TPMI 아키텍처

TPMI는 PCI VSEC(Vendor Specific Extended Capability, ID=66)를 통해 발견됩니다. Intel VSEC 드라이버(intel_vsec.c)가 OOB(Out-of-Band) PCI 디바이스의 VSEC/DVSEC 구조를 스캔하여 TPMI를 감지하면, auxiliary 버스(Bus)에 TPMI 코어 디바이스를 생성합니다. TPMI 코어는 VSEC 헤더의 tBIR(BAR Indicator Register) 필드로 대상 PCI BAR를 식별하고, Address 필드로 BAR 내 PFS 시작 오프셋(Offset)을 계산합니다.

PCI 열거 단계 PCI VSEC (Vendor Specific) intel_vsec.c (VSEC 드라이버) PCI BAR → MMIO 매핑 TPMI 코어 (drivers/platform/x86/intel/tpmi.c) PFS 파싱 → 기능별 auxiliary 디바이스 생성 PFS (PM Feature Structure) 테이블 Feature ID | MMIO 오프셋 | 크기 | 잠금 상태 — 다이별 독립 엔트리 TPMI Feature 드라이버 (auxiliary_device) intel_rapl_tpmi ID=0 (RAPL) isst_tpmi ID=5 (SST) uncore-freq-tpmi ID=2 (UFS) tpmi_plr ID=8 (PLR) tpmi_power_domains ID=12 (PWR DMN) 사용자 공간 인터페이스 powercap sysfs (RAPL) isst_if sysfs (SST) uncore-freq sysfs debugfs (PLR) Hardware (Meteor Lake+ SoC) Compute Die 0: TPMI MMIO Region (BAR) Compute Die 1: TPMI MMIO Region (BAR) RAPL regs SST regs RAPL regs SST regs

PCI VSEC 발견 및 PFS 파싱

TPMI는 PCIe 설정 공간의 VSEC(Vendor Specific Extended Capability)를 통해 발견됩니다. Intel VSEC 드라이버(intel_vsec.c)가 TPMI 타입의 VSEC를 감지하면 TPMI 코어 드라이버를 로드하고, TPMI 코어는 MMIO에 매핑된 PFS(PM Feature Structure) 테이블을 파싱합니다.

/* PFS (PM Feature Structure) 엔트리 — 하드웨어 비트필드 레이아웃 */
/* drivers/platform/x86/intel/vsec_tpmi.c (커널 6.13+, 이전: tpmi.c) */
struct intel_tpmi_pfs_entry {
    u64 tpmi_id:8;       /* PM 기능 식별자 (0=RAPL, 2=UFS, 5=SST ...) */
    u64 num_entries:8;  /* 인스턴스 수 (전력 도메인/다이 수와 대응) */
    u64 entry_size:16;  /* 인스턴스 MMIO 블록 크기 (32비트 워드 단위) */
    u64 cap_offset:16;  /* PM_Features 베이스로부터 오프셋 (KB 단위) */
    u64 attribute:2;    /* 속성 플래그 (읽기 전용, 잠금 등) */
    u64 reserved:14;
} __packed;

/* TPMI 코어의 PFS 파싱 흐름 */
tpmi_pfs_init(tpmi_info):
    /* 1. PCI BAR0에서 PFS 헤더 읽기 */
    pfs_start = devm_ioremap_resource(dev, &pci_resource);

    /* 2. PFS 엔트리 순회하며 기능 열거 */
    for (i = 0; i < pfs_count; i++) {
        read_pfs_entry(&pfs[i]);
        /* 3. 기능별 MMIO 영역 매핑 */
        feature_mem = pfs_start + pfs[i].cap_offset;
        /* 4. auxiliary 디바이스 생성 (intel_rapl_tpmi, isst_tpmi 등) */
        intel_vsec_add_aux(dev, NULL, &feature_info, name);
    }

TPMI Feature ID 매핑

각 PM 기능은 고유한 TPMI ID를 가지며, PFS 테이블에서 이 ID를 통해 발견됩니다. 커널은 ID에 따라 해당 feature 드라이버의 auxiliary 디바이스를 생성합니다.

ID이름커널 드라이버설명
0RAPLintel_rapl_tpmiMMIO 기반 RAPL 도메인 — 에너지 측정 및 전력 제한
1PEM(커널 내부)Performance and Energy Monitoring — 성능/에너지 모니터링
2UFSuncore-freq-tpmiUncore Frequency Scaling — 다이별 언코어 주파수 제어
5SSTisst_tpmiIntel Speed Select Technology — PP/BF/TF/CP 프로파일
8PLRtpmi_plrPerformance Limit Reasons — 스로틀링 원인 보고 (debugfs)
10UMSuncore-freq-tpmiUncore Mesh/SoC 주파수 제어
12PWR_DMNtpmi_power_domains전력 도메인 파티셔닝
0x81INFO(TPMI 코어 내부)CPU↔PCI 토폴로지 매핑 (패키지 ID, PCI BDF). 실제 PM 기능이 아닌 메타 정보
참고: TPMI_INFO_ID(0x81)는 CPU 소켓과 PCI 디바이스 간의 매핑 정보를 제공하는 특수 pseudo-feature입니다. TPMI 코어가 이 정보를 읽어 intel_tpmi_plat_infopackage_id와 PCI BDF를 채웁니다.

TPMI 코어 구조체(Struct)

/* include/linux/intel_tpmi.h — TPMI API 핵심 구조체 */

/* Feature 드라이버가 TPMI 코어에서 받는 플랫폼 정보 */
struct intel_tpmi_plat_info {
    u8  package_id;        /* CPU 소켓(패키지) ID */
    u8  bus_number;        /* PCI 버스 번호 */
    u8  device_number;     /* PCI 디바이스 번호 */
    u8  function_number;   /* PCI 펑션 번호 */
    u8  segment;           /* PCI 세그먼트 ID */
    u8  partition;          /* 패키지 파티션 ID */
    u16 cdie_mask;          /* 현재 파티션의 컴퓨트 다이 비트맵 */
};

/* TPMI 코어 내부 — 디바이스별 기능 관리 */
struct intel_tpmi_info {
    struct auxiliary_device *vsec_dev;    /* 부모 VSEC auxiliary 디바이스 */
    int                   feature_count;  /* 발견된 PM 기능 수 */
    struct intel_tpmi_pm_feature *tpmi_features; /* PM 기능 배열 */
};

/* PM 기능 인스턴스 정보 */
struct intel_tpmi_pm_feature {
    struct intel_tpmi_pfs_entry pfs_header;  /* 하드웨어 PFS 헤더 */
    unsigned int                vsec_offset; /* MMIO 시작 주소 (바이트) */
    /* vsec_offset = VSEC Address + cap_offset(KB) * 1024 */
};

/* CPU↔PCI 토폴로지 매핑 헤더 (TPMI_INFO_ID=0x81에서 읽음) */
struct tpmi_info_header {
    u64 fn:3;         /* PCI Function 번호 */
    u64 dev:5;        /* PCI Device 번호 */
    u64 bus:8;        /* PCI Bus 번호 */
    u64 pkg:8;        /* CPU Package ID */
    u64 reserved:40;
} __packed;

/* Feature 드라이버가 사용하는 TPMI API (include/linux/intel_tpmi.h) */
struct intel_tpmi_plat_info *tpmi_get_platform_data(
    struct auxiliary_device *adev);     /* 플랫폼 정보 반환 */
int tpmi_get_resource_count(
    struct auxiliary_device *adev);     /* MMIO 인스턴스 수 반환 */
struct resource *tpmi_get_resource_at_index(
    struct auxiliary_device *adev,
    int index);                          /* 인덱스별 MMIO resource 반환 */
int tpmi_get_feature_status(
    struct auxiliary_device *adev,
    int feature_id,
    bool *read_blocked,
    bool *write_blocked);               /* 기능 잠금/비활성 상태 확인 */

RAPL over TPMI (intel_rapl_tpmi.c)

Meteor Lake+에서 RAPL 레지스터는 MSR 대신 TPMI MMIO를 통해 접근합니다. intel_rapl_tpmi 드라이버는 TPMI 코어에서 RAPL 기능(ID=0)의 MMIO 영역을 받아, 기존 intel_rapl_common의 powercap 프레임워크에 MMIO 백엔드로 등록합니다. 각 RAPL 도메인의 MMIO 블록 크기는 128바이트(TPMI_RAPL_DOMAIN_SIZE)이며, 각 Power Limit이 개별 레지스터를 가집니다(기존 MSR은 PL1+PL2가 하나의 64비트 MSR에 패킹).

등록 흐름: ① TPMI 코어가 PFS에서 TPMI_ID_RAPL=0 발견 → ② auxiliary 디바이스 intel_vsec.tpmi-rapl.N 생성 → ③ intel_rapl_tpmi probe → ④ tpmi_get_resource_at_index()로 MMIO 매핑 → ⑤ rapl_add_package()로 powercap zone 등록 → ⑥ /sys/class/powercap/intel-rapl:* 노출

/* intel_rapl_tpmi.c — MMIO 기반 RAPL 백엔드 */

/* TPMI RAPL MMIO 레지스터 오프셋 (MSR 주소 대신 MMIO 오프셋 사용) */
#define TPMI_RAPL_REG_HEADER          0x00
#define TPMI_RAPL_REG_UNIT            0x08   /* 에너지/전력/시간 단위 */
#define TPMI_RAPL_REG_PL1             0x10   /* Package Power Limit 1 */
#define TPMI_RAPL_REG_PL2             0x18   /* Package Power Limit 2 */
#define TPMI_RAPL_REG_PL4             0x20   /* Package Power Limit 4 */
#define TPMI_RAPL_REG_ENERGY_STATUS   0x28   /* 에너지 카운터 */
#define TPMI_RAPL_REG_PERF_STATUS    0x30   /* 성능 스로틀 상태 */
#define TPMI_RAPL_REG_POWER_INFO     0x38   /* TDP, min/max 전력 */

/* 디바이스별 RAPL TPMI 패키지 구조체 */
struct tpmi_rapl_package {
    struct rapl_if_priv          priv;       /* RAPL 인터페이스 private */
    struct intel_tpmi_plat_info *tpmi_info; /* TPMI 플랫폼 정보 */
    struct rapl_package         *rp;        /* RAPL 패키지 포인터 */
    void __iomem               *base;      /* MMIO 베이스 주소 */
};

/* MMIO 기반 읽기 — IPI 없이 직접 접근 */
static int tpmi_rapl_read_raw(int id, struct reg_action *ra)
{
    ra->value = readq(base + ra->reg.mmio_offset);
    ra->value &= ra->mask;   /* 마스크 적용 */
    return 0;
}

/* MMIO 기반 쓰기 — read-modify-write 패턴 */
static int tpmi_rapl_write_raw(int id, struct reg_action *ra)
{
    u64 val;
    val = readq(base + ra->reg.mmio_offset);
    val &= ~ra->mask;                 /* 대상 비트 클리어 */
    val |= ra->value & ra->mask;      /* 새 값 삽입 */
    writeq(val, base + ra->reg.mmio_offset);
    return 0;
}

/* rapl_if_priv — intel_rapl_common에 TPMI 백엔드 등록 */
static struct rapl_if_priv tpmi_rapl_priv = {
    .type           = RAPL_IF_TPMI,
    .read_raw       = tpmi_rapl_read_raw,
    .write_raw      = tpmi_rapl_write_raw,
    .control_type   = NULL,    /* powercap에서 설정 */
    .reg_unit       = { .mmio_offset = TPMI_RAPL_REG_UNIT },
    .regs           = {       /* 도메인별 레지스터 매핑 */
        [RAPL_DOMAIN_PACKAGE] = {
            .pl1    = { .mmio_offset = TPMI_RAPL_REG_PL1 },
            .pl2    = { .mmio_offset = TPMI_RAPL_REG_PL2 },
            .pl4    = { .mmio_offset = TPMI_RAPL_REG_PL4 },
            .energy = { .mmio_offset = TPMI_RAPL_REG_ENERGY_STATUS },
            .info   = { .mmio_offset = TPMI_RAPL_REG_POWER_INFO },
        },
    },
};
투명한 전환: TPMI 기반 RAPL은 동일한 intel_rapl_common 프레임워크를 사용하므로, 사용자 공간에서는 기존과 동일한 /sys/class/powercap/intel-rapl:* 경로로 접근합니다. MSR→TPMI 전환은 커널 내부에서 투명하게 처리됩니다.

SST (Speed Select Technology) over TPMI

Intel Speed Select Technology(SST)는 동일 CPU 내에서 코어별 차등 성능 프로파일을 제공합니다. Meteor Lake+에서 SST는 TPMI(Feature ID=5)를 통해 접근합니다.

SST 기능설명사용 사례
SST-PPPerformance Profile — 미리 정의된 주파수/TDP 프로파일 전환워크로드에 따라 코어 수 vs 주파수 트레이드오프
SST-BFBase Frequency — 특정 코어의 기본 주파수를 상향지연(Latency)시간에 민감한 코어에 높은 보장 주파수 할당
SST-TFTurbo Frequency — 특정 코어에 터보 주파수 우선 배분고성능 요구 스레드(Thread)에 터보 주파수 집중
SST-CPCore Power — 코어별 전력 우선순위(Priority) 설정중요 코어에 전력 예산 우선 배정
# intel-speed-select CLI 도구로 SST 상태 확인
intel-speed-select --info
intel-speed-select perf-profile info        # SST-PP 프로파일 정보
intel-speed-select base-freq info           # SST-BF 지원 코어 확인
intel-speed-select turbo-freq info          # SST-TF 상태
intel-speed-select core-power info          # SST-CP 우선순위

# SST-CP로 특정 코어에 높은 우선순위 부여
intel-speed-select core-power assoc --clos 0 --core 0,1,2,3   # 고성능 그룹
intel-speed-select core-power assoc --clos 3 --core 4,5,6,7   # 저전력 그룹

Uncore 주파수 제어 over TPMI

TPMI 이전에는 Uncore 주파수가 패키지/다이 단위로만 제어 가능했습니다. TPMI(Feature ID=2)는 패브릭 클러스터(fabric cluster) 단위의 세밀한 Uncore 주파수 제어를 지원합니다.

Uncore 주파수 토폴로지 계층 (TPMI 기반) Package → Die → Power Domain → Fabric Cluster 기존 per-die 인터페이스 (TPMI 이전) /sys/devices/system/cpu/intel_uncore_frequency/ package_00_die_00/ initial_max_freq_khz 초기 최대 주파수 (읽기 전용) initial_min_freq_khz 초기 최소 주파수 (읽기 전용) max_freq_khz 현재 최대 주파수 (쓰기 가능) min_freq_khz 현재 최소 주파수 (쓰기 가능) 패키지 전체 die 단위 제어 — 단일 주파수 TPMI 추가: 클러스터 레벨 제어 /sys/devices/system/cpu/intel_uncore_frequency/ uncore00/ (Fabric Cluster 0) package_id 소켓(패키지) ID domain_id 전력 도메인 ID fabric_cluster_id 패브릭 클러스터 ID current_freq_khz 현재 실제 주파수 (읽기 전용) max_freq_khz 최대 주파수 (쓰기 가능) min_freq_khz 최소 주파수 (쓰기 가능) Fabric Cluster 단위 세밀한 제어 — Meteor Lake+ TPMI 확장 TPMI Uncore 토폴로지 계층 Package (소켓) Die (다이) Power Domain (전력 도메인) cluster 0 cluster 1 ... cluster N 개별 주파수 제어
활용 예시: 멀티 다이 Xeon 6 서버에서 메모리 집약적 워크로드가 특정 다이에 집중된 경우, 해당 다이의 패브릭 클러스터 Uncore 주파수를 높이고 나머지를 낮추어 전력 효율을 최적화할 수 있습니다.

PLR (Performance Limit Reasons) over TPMI

PLR(Feature ID=8)은 CPU 성능이 제한(스로틀링)되는 원인을 실시간으로 보고합니다. TPMI를 통해 debugfs에 노출되며, 성능 문제 진단에 활용됩니다.

# PLR 상태 확인 (debugfs)
ls /sys/kernel/debug/tpmi-plr/
# die0/  die1/  ...

cat /sys/kernel/debug/tpmi-plr/die0/status
# 각 비트가 스로틀링 원인을 나타냄:
# - thermal: 열 제한
# - power_limit_pl1: PL1(장기 전력) 초과
# - power_limit_pl2: PL2(단기 전력) 초과
# - electrical_design_point: 전류 한계 도달
# - turbo_transition_attenuation: 터보 전환 감쇠
# - prochot: 외부 PROCHOT# 신호

# PLR 스티키 비트 클리어 (해당 파일에 0 쓰기)
echo 0 > /sys/kernel/debug/tpmi-plr/die0/status
주의: PLR은 진단 전용 인터페이스입니다. 스티키 비트는 마지막 클리어 이후 발생한 모든 스로틀링 원인을 누적하므로, 주기적으로 클리어하면서 모니터링해야 정확한 시점을 파악할 수 있습니다.

TPMI 커널 설정

# TPMI 관련 Kconfig 옵션
CONFIG_INTEL_VSEC=m            # Intel Vendor Specific Extended Capabilities (필수)
CONFIG_INTEL_TPMI=m            # TPMI 코어 드라이버
CONFIG_INTEL_RAPL_TPMI=m       # RAPL over TPMI 백엔드
CONFIG_INTEL_UNCORE_FREQ_TPMI=m  # Uncore 주파수 제어 over TPMI
CONFIG_INTEL_SPEED_SELECT_INTERFACE=m  # SST over TPMI

# 로드된 TPMI 모듈 확인
lsmod | grep tpmi
# intel_rapl_tpmi        16384  0
# intel_uncore_freq_tpmi 16384  0
# isst_tpmi              20480  0
# intel_tpmi             24576  3 intel_rapl_tpmi,intel_uncore_freq_tpmi,isst_tpmi
# intel_vsec             16384  1 intel_tpmi

# TPMI 디바이스 확인 (PCI VSEC)
lspci -d 8086: -vvv | grep -A5 "Vendor Specific"

TPMI 소스 트리 구조

파일역할
include/linux/intel_tpmi.hTPMI API 헤더 — Feature ID 상수, 플랫폼 정보 구조체, 헬퍼 함수
drivers/platform/x86/intel/vsec.cPCI VSEC 드라이버 — TPMI 타입 감지 및 코어 디바이스 생성
drivers/platform/x86/intel/tpmi.cTPMI 코어 — PFS 파싱, MMIO 매핑, auxiliary 디바이스 생성, debugfs (커널 6.13+에서 vsec_tpmi.c로 개명)
drivers/powercap/intel_rapl_tpmi.cRAPL TPMI 백엔드 — MMIO 기반 에너지/전력 레지스터 접근
drivers/platform/x86/intel/uncore-frequency/Uncore 주파수 제어 (TPMI + MSR 백엔드)
drivers/platform/x86/intel/speed_select_if/SST 인터페이스 (TPMI + MMIO + MSR 백엔드)

TPMI debugfs 인터페이스

TPMI 코어 드라이버는 debugfs를 통해 PFS 테이블 덤프(Dump)와 Feature별 MMIO 원시 읽기/쓰기를 제공합니다. 주로 디버깅(Debugging)과 펌웨어 설정 확인에 사용됩니다.

# TPMI debugfs 구조
/sys/kernel/debug/tpmi-<N>/
    ├── pfs_dump                     # PFS 테이블 전체 엔트리 출력
    ├── tpmi-id-<feature_id>/
    │   ├── mem_dump                 # Feature MMIO 영역 원시 덤프 (읽기 전용)
    │   └── mem_write                # 특정 오프셋에 MMIO 쓰기 (디버그용)
    └── ...

# PFS 엔트리 확인 (어떤 PM 기능이 지원되는지)
cat /sys/kernel/debug/tpmi-0/pfs_dump

# RAPL MMIO 레지스터 원시 값 확인
cat /sys/kernel/debug/tpmi-0/tpmi-id-0/mem_dump

TPMI 커널 머지 타임라인

커널 버전TPMI 마일스톤
6.3TPMI 기본 열거 드라이버 병합 (tpmi.c)
6.4RAPL TPMI 드라이버 (intel_rapl_tpmi.c) 병합
6.5Uncore 주파수 TPMI 지원, SST via TPMI
6.5~6.6TPMI debugfs, 기능 잠금 상태 인터페이스
6.6+CPU 토폴로지/도메인 매핑, 클러스터 레벨 제어
6.13드라이버 tpmi.cvsec_tpmi.c 개명, Clearwater Forest ID 추가

AMD RAPL 지원

AMD는 Zen 아키텍처(Family 17h, Ryzen 1000/EPYC 7001) 이후로 RAPL 호환 MSR을 제공합니다. 커널 intel_rapl_msr 드라이버가 AMD CPU도 지원하여 동일한 powercap sysfs 인터페이스로 접근 가능합니다.

항목Intel RAPLAMD RAPL
지원 시작Sandy Bridge (2세대, 2011)Zen (Family 17h, 2017)
도메인package, core, uncore, dram, psyspackage, core (Zen 2+에서 확장)
MSR 주소606h, 610h, 611h, 619h, 641h 등C001_0299h (core), C001_029Ah (pkg) 등
전력 제한 쓰기PL1/PL2 쓰기 가능읽기 전용 (에너지 측정만, 전력 제한 설정 불가)
커널 드라이버intel_rapl_msr / intel_rapl_tpmiintel_rapl_msr (AMD 지원 포함)
perf 이벤트power/energy-pkg,cores,ram/power/energy-pkg,cores/

Zen 세대별 RAPL 지원 차이

세대Family/Model제품RAPL 도메인특이사항
Zen (2017)17h/01hRyzen 1000, EPYC 7001package만core 에너지 미지원, 정확도 낮음
Zen+ (2018)17h/08hRyzen 2000, EPYC 7002package, corecore 도메인 추가
Zen 2 (2019)17h/31hRyzen 3000, EPYC 7002package, core에너지 정확도 향상, 칩렛 구조 반영
Zen 3 (2020)19h/01hRyzen 5000, EPYC 7003package, core통합 CCX 구조, 전력 효율 개선
Zen 4 (2022)19h/61hRyzen 7000, EPYC 9004package, core5nm, iGPU 전력 포함 (package 도메인)
Zen 5 (2024)1AhRyzen 9000, EPYC 9005package, core하이브리드 코어, 향상된 전력 센서

AMD PPT/STAPM 전력 관리 모델

AMD 프로세서는 Intel의 PL1/PL2와 다른 전력 관리 모델을 사용합니다. PPT(Package Power Tracking)는 소켓 전체의 전력 상한이고, STAPM(Skin Temperature Aware Power Management)는 노트북의 외부 온도(skin temperature)를 고려한 지속 전력 제한입니다. 이 값들은 RAPL MSR이 아닌 SMU(System Management Unit) 펌웨어를 통해 제어됩니다.

AMD 전력 제한 계층 PPT 패키지 전력 상한 STAPM 지속 전력 (노트북) EDC 피크 전류 한계 TDC 지속 전류 한계 THM 온도 제한 SMU (System Management Unit) 펌웨어 기반 전력/열/전류 제어 amd_pstate 드라이버 intel_rapl_msr (AMD 지원) amd_energy (hwmon) RAPL MSR (C001_0299h, C001_029Ah) 에너지 카운터 (읽기 전용) /sys/class/powercap/intel-rapl:*/ /sys/class/hwmon/hwmonN/

amd_energy hwmon 드라이버

amd_energy 드라이버는 powercap 프레임워크를 사용하지 않고 hwmon 인터페이스로 에너지 정보를 노출합니다. 소켓별, 코어별 에너지 소비를 /sys/class/hwmon/에서 확인할 수 있습니다.

# amd_energy 모듈 로드 (Family 17h/19h)
sudo modprobe amd_energy

# hwmon 인터페이스 확인
for hw in /sys/class/hwmon/hwmon*/; do
    if [ "$(cat ${hw}/name)" = "amd_energy" ]; then
        echo "Found amd_energy at ${hw}"
        ls ${hw}/energy*_input
        # energy1_input: 소켓 에너지 (μJ)
        # energy2_input ~ energyN_input: 코어별 에너지
    fi
done

# 소켓 전력 계산 (5초 간격)
E1=$(cat /sys/class/hwmon/hwmon*/energy1_input)
sleep 5
E2=$(cat /sys/class/hwmon/hwmon*/energy1_input)
echo "소켓 전력: $(( (E2 - E1) / 5000000 )) W"
참고: AMD의 RAPL MSR은 에너지 측정(energy counter)만 지원하며, Intel처럼 전력 상한(power limit)을 설정할 수 없습니다. AMD 시스템에서 전력 제한은 BIOS/UEFI의 PPT(Package Power Tracking) 설정이나 amd_pstate 드라이버의 EPP(Energy Performance Preference)를 통해 관리합니다.

Intel vs AMD 전력 관리 종합 비교

Intel과 AMD는 서로 다른 전력 관리 철학과 아키텍처를 채택하고 있습니다. Intel은 RAPL을 통한 OS 레벨의 세밀한 전력 제어를 제공하는 반면, AMD는 SMU 펌웨어 기반의 자율적 전력 관리에 초점을 맞춥니다.

Intel sysfs: powercap / perf / turbostat powercap Framework intel_rapl_msr intel_rapl_tpmi PL1/PL2/PL3/PL4 (읽기+쓰기) 5개 도메인 (pkg/core/uncore/dram/psys) MSR + TPMI MMIO OS 레벨 전력 제어 중심 AMD sysfs: powercap / hwmon / perf intel_rapl_msr amd_energy SMU (System Management Unit) PPT/STAPM/EDC/TDC (BIOS 설정) 2개 도메인 (pkg/core, 읽기 전용) MSR (C001_0299h, C001_029Ah) 펌웨어 자율 제어 중심
# Intel: PL1을 25W로 설정 (OS 레벨 제어)
echo 25000000 > /sys/class/powercap/intel-rapl:0/constraint_0_power_limit_uw
cat /sys/class/powercap/intel-rapl:0/constraint_0_power_limit_uw
# 25000000 → 즉시 적용

# AMD: PPT는 BIOS에서만 설정 가능 (OS에서 읽기 전용)
cat /sys/class/powercap/intel-rapl:0/constraint_0_power_limit_uw
# 0 또는 고정값 → 쓰기 불가
# AMD에서 전력 제한은 amd_pstate EPP 또는 BIOS PPT 설정 사용
echo "power" > /sys/devices/system/cpu/cpu*/cpufreq/energy_performance_preference
기능IntelAMD
전력 제한 계층PL1 (장기), PL2 (단기), PL3 (피크), PL4 (즉시)PPT (패키지), STAPM (지속), EDC (피크 전류), TDC (지속 전류)
OS 전력 제어PL1/PL2 sysfs 쓰기 가능읽기 전용 (BIOS/SMU만 제어)
에너지 측정 도메인package, core, uncore, dram, psyspackage, core
커널 드라이버intel_rapl_msr, intel_rapl_tpmiintel_rapl_msr, amd_energy
전력 제어 주체OS (커널 드라이버) + 하드웨어SMU 펌웨어 (하드웨어 자율)
인터페이스MSR + TPMI MMIOMSR (에너지), SMU mailbox (전력 제한)
DRAM 에너지지원 (서버: Sandy Bridge-EP+, 클라이언트: Haswell+)미지원
플랫폼 전력psys 도메인 (Skylake+ 모바일)미지원
Intel MSR주소AMD 대응주소
MSR_RAPL_POWER_UNIT0x606MSR_AMD_RAPL_POWER_UNIT0xC001_0299
MSR_PKG_ENERGY_STATUS0x611MSR_AMD_PKG_ENERGY_STATUS0xC001_029B
MSR_PP0_ENERGY_STATUS0x639MSR_AMD_CORE_ENERGY_STATUS0xC001_029A
MSR_PKG_POWER_LIMIT0x610(해당 없음)SMU 펌웨어 제어
MSR_DRAM_ENERGY_STATUS0x619(미지원)
실무 요약: Intel 시스템에서는 RAPL PL1/PL2를 직접 조정하여 전력을 동적으로 제어할 수 있지만, AMD 시스템에서는 에너지 모니터링만 가능하고 전력 제한은 BIOS의 PPT/STAPM 설정이나 amd_pstate 드라이버의 EPP를 통해 간접적으로 관리해야 합니다.

perf 전력 이벤트 및 모니터링 도구

# RAPL 전력 측정 (perf) — 5초간 에너지 소비 측정
perf stat -e power/energy-pkg/,power/energy-cores/,power/energy-ram/ sleep 5

# 특정 프로세스의 전력 소비 프로파일링
perf stat -e power/energy-pkg/,power/energy-cores/ -- make -j$(nproc)

# turbostat — 실시간 전력/주파수/온도 모니터링
turbostat --show Package,Core,CPU,Avg_MHz,Busy%,PkgWatt,CorWatt,RAMWatt --interval 1

# powertop — 전력 소비 분석 + 절전 추천
powertop --auto-tune    # 자동 절전 최적화 적용
powertop --csv=report.csv --time=30   # 30초 측정 후 CSV 리포트

# powercap 에너지 직접 읽기 (커스텀 스크립트용)
E1=$(cat /sys/class/powercap/intel-rapl:0/energy_uj)
sleep 5
E2=$(cat /sys/class/powercap/intel-rapl:0/energy_uj)
echo "5초간 소비: $(( (E2 - E1) / 1000000 )) J, 평균: $(( (E2 - E1) / 5000000 )) W"

실전 예제: PL1 제한 효과 측정

전력 제한(PL1)을 적용했을 때 성능과 전력의 트레이드오프를 실제로 측정해봅니다.

예제 1: PL1 제한 전후 벤치마크

#!/bin/bash
# PL1 제한 효과 비교 스크립트

# 1. 기본 PL1 확인 및 저장
RAPL_PATH="/sys/class/powercap/intel-rapl:0"
ORIG_PL1=$(cat ${RAPL_PATH}/constraint_0_power_limit_uw)
echo "원래 PL1: $(( ORIG_PL1 / 1000000 )) W"

# 2. 제한 없음 (기본값) 테스트
echo "=== 기본 설정 테스트 ==="
perf stat -e power/energy-pkg/,power/energy-cores/ \
    stress-ng --cpu 8 --timeout 30s 2>&1 | grep energy

# 3. PL1 25W로 제한
echo 25000000 > ${RAPL_PATH}/constraint_0_power_limit_uw
echo "=== PL1 25W 제한 테스트 ==="
perf stat -e power/energy-pkg/,power/energy-cores/ \
    stress-ng --cpu 8 --timeout 30s 2>&1 | grep energy

# 4. PL1 15W로 강제 제한
echo 15000000 > ${RAPL_PATH}/constraint_0_power_limit_uw
echo "=== PL1 15W 제한 테스트 ==="
perf stat -e power/energy-pkg/,power/energy-cores/ \
    stress-ng --cpu 8 --timeout 30s 2>&1 | grep energy

# 5. 원래 설정 복원
echo ${ORIG_PL1} > ${RAPL_PATH}/constraint_0_power_limit_uw
echo "PL1 복원 완료"

예상 결과:

PL1 설정Package 에너지성능 (작업 완료)평균 전력효율
기본 (45W)~1350 J100% (기준)45W1.0×
25W 제한~900 J~85%25W1.4×
15W 제한~750 J~65%15W1.6×
실무 적용: 노트북/태블릿에서 배터리 수명을 늘리거나, 데이터센터에서 랙 단위 전력 예산을 맞출 때 PL1을 동적으로 조절합니다. 대부분의 워크로드는 25W 제한에서도 85% 이상 성능을 유지하므로, 에너지 효율이 크게 향상됩니다.

예제 2: 프로그램별 에너지 프로파일링(Profiling)

# 컴파일 vs 압축 vs 암호화 — 에너지 소비 비교

# 컴파일 (CPU intensive)
perf stat -e power/energy-pkg/,power/energy-cores/ -- \
    make -j$(nproc) clean all

# 압축 (메모리 대역폭 intensive)
perf stat -e power/energy-pkg/,power/energy-ram/ -- \
    tar -czf archive.tar.gz /usr/share/doc

# 암호화 (CPU + 일부 메모리)
perf stat -e power/energy-pkg/,power/energy-cores/ -- \
    openssl enc -aes-256-cbc -in largefile -out largefile.enc -k password

# 결과 비교 예시:
# 컴파일:  Package 2500J, Cores 1800J, RAM 200J  → CPU 중심
# 압축:    Package 1200J, Cores  600J, RAM 400J  → 메모리 대역폭 비중 큼
# 암호화:  Package 1800J, Cores 1500J, RAM 100J  → CPU 집약적

예제 3: turbostat으로 실시간 전력 추적

# turbostat으로 PL1 제한 효과 실시간 관찰
# 터미널 1: turbostat 실행
sudo turbostat --show Package,Core,CPU,Avg_MHz,Busy%,PkgWatt,CorWatt,GFXWatt --interval 1

# 터미널 2: 부하 적용 후 PL1 변경
stress-ng --cpu 8 --timeout 120s &
sleep 30
echo 25000000 > /sys/class/powercap/intel-rapl:0/constraint_0_power_limit_uw
# → turbostat에서 PkgWatt가 즉시 25W 이하로 떨어지는 것 확인
# → Avg_MHz도 함께 감소 (스로틀링)

sleep 30
echo ${ORIG_PL1} > /sys/class/powercap/intel-rapl:0/constraint_0_power_limit_uw
# → PkgWatt와 Avg_MHz가 원래대로 복구
주의: PL1 제한은 즉시 적용되지만, 하드웨어가 시간 윈도우 내 평균 전력을 제어하므로 수 초간 초과할 수 있습니다. 또한 PL1을 너무 낮게 설정하면 시스템이 불안정해지거나 응답성이 크게 저하될 수 있으니, 최소 TDP의 50% 이상으로 유지하세요.

전력 제한 스로틀링 디버깅

시스템 성능이 예상보다 낮을 때, 원인이 열 제한인지 전력 제한인지를 구별하는 것이 중요합니다. Intel CPU는 MSR_CORE_PERF_LIMIT_REASONS(0x64F)와 MSR_RING_PERF_LIMIT_REASONS(0x6B1) 레지스터를 통해 스로틀링 원인을 비트 단위로 보고합니다.

성능 저하 감지 turbostat --show PkgWatt,Throttle MSR 0x64F 확인 (rdmsr 0x64F) bit[0]=1? Thermal 제한 쿨링 솔루션 점검 써멀 페이스트 교체 fan curve 조정 bit[10]=1? PL1 전력 제한 PL1 값 상향 time window 조정 워크로드 분산 bit[11]=1? PL2 전력 제한 Turbo 시간 부족 PL2 상향 검토 VR 전류 한계 확인 모든 비트 확인 후 → 원인별 대응 → 재측정으로 검증
# MSR_CORE_PERF_LIMIT_REASONS (0x64F) 읽기
sudo rdmsr 0x64F
# 결과를 비트별로 해석:
# bit[0]:  PROCHOT 상태 (외부 열 제한 신호)
# bit[1]:  Thermal 상태 (내부 온도 제한)
# bit[4]:  Residency State 제한
# bit[5]:  Running Average Thermal 제한
# bit[6]:  VR Thermal Alert
# bit[8]:  VR Thermal Design Current
# bit[10]: PL1 (Long-Term) 전력 제한 활성
# bit[11]: PL2 (Short-Term) 전력 제한 활성
# bit[12]: Max Turbo Limit 제한
# bit[13]: Turbo Transition Attenuation
# bit[16~25]: 로그 비트 (스티키 — 마지막 클리어 이후 누적)
# turbostat으로 스로틀링 원인 확인
sudo turbostat --show Package,Core,CPU,Avg_MHz,Busy%,PkgWatt,PkgTmp,Throttle --interval 1
# Throttle 컬럼에 표시되는 값:
# 0x0000 = 스로틀링 없음
# 0x0400 = PL1 제한
# 0x0800 = PL2 제한
# 0x0001 = PROCHOT
# 0x0002 = Thermal
# perf로 전력 제한 이벤트 추적
sudo perf trace -e power:cpu_frequency,thermal:thermal_zone_trip -- sleep 30

# ftrace로 RAPL 전력 제한 디버깅
echo 1 > /sys/kernel/debug/tracing/events/power/cpu_frequency/enable
echo 1 > /sys/kernel/debug/tracing/events/thermal/thermal_zone_trip/enable
cat /sys/kernel/debug/tracing/trace_pipe
#!/bin/bash
# 자동 스로틀링 진단 스크립트

echo "=== RAPL 스로틀링 진단 ==="

# 1. MSR 스로틀 이유 확인
LIMIT_REASONS=$(sudo rdmsr 0x64F)
echo "MSR 0x64F: 0x${LIMIT_REASONS}"

if (( 0x${LIMIT_REASONS} & 0x01 )); then echo "  [!] PROCHOT 활성"; fi
if (( 0x${LIMIT_REASONS} & 0x02 )); then echo "  [!] Thermal 제한"; fi
if (( 0x${LIMIT_REASONS} & 0x400 )); then echo "  [!] PL1 전력 제한"; fi
if (( 0x${LIMIT_REASONS} & 0x800 )); then echo "  [!] PL2 전력 제한"; fi

# 2. 현재 PL1/PL2 확인
echo "PL1: $(cat /sys/class/powercap/intel-rapl:0/constraint_0_power_limit_uw) μW"
echo "PL2: $(cat /sys/class/powercap/intel-rapl:0/constraint_1_power_limit_uw) μW"

# 3. 현재 온도
for zone in /sys/class/thermal/thermal_zone*/; do
    echo "  $(cat ${zone}/type): $(cat ${zone}/temp)m°C"
done
비트이름원인대응
0PROCHOT Status외부 PROCHOT# 신호 (VR 과열 등)VRM 쿨링, 보드 점검
1Thermal StatusCPU 코어 온도 Tj_max 도달쿨러 성능 개선, 써멀 페이스트
5RAPL Thermal이동 평균 열 제한장시간 부하 시 쿨링 부족
6VR Thermal Alert전압 레귤레이터 과열VRM 방열판, 에어플로우
10PL1 Power Limit장기 전력 제한 초과PL1 상향 또는 워크로드 조정
11PL2 Power Limit단기 전력 제한 초과PL2 상향, Turbo 시간 부족
12Max Turbo Limit최대 터보 주파수 도달정상 (설계 한계)
13Turbo Attenuation터보 전환 감쇠코어 수 대비 주파수 한계
진단 항목확인 명령어정상 기준
CPU 온도cat /sys/class/thermal/thermal_zone0/temp< Tj_max - 10°C
현재 주파수turbostat --show Avg_MHz --interval 1터보 주파수 근처
PL1 제한 상태rdmsr 0x64F bit[10]0 (미활성)
PROCHOT 신호rdmsr 0x64F bit[0]0 (미활성)
에너지 소비율turbostat --show PkgWattPL1 이하
TPMI PLRcat /sys/kernel/debug/tpmi-plr/die0/status0 (제한 없음)
팁: turbostat의 Throttle 컬럼과 rdmsr 0x64F의 스티키 비트(bit[16~25])를 함께 확인하면, 현재 상태와 과거에 발생한 스로틀링 이벤트를 모두 파악할 수 있습니다. 벤치마크 시작 전에 wrmsr 0x64F 0으로 스티키 비트를 클리어하면 정확한 진단이 가능합니다.

RAPL과 thermal 서브시스템 연계

Linux thermal 프레임워크는 CPU 온도가 임계값에 도달하면 cooling device를 활성화하여 발열을 제어합니다. RAPL의 전력 제한(PL1)은 가장 효과적인 cooling 수단 중 하나이며, thermal 서브시스템과의 연계를 통해 자동화된 전력-열 관리가 가능합니다.

Thermal Zone CPU 온도 센서 Thermal Governor step_wise / power_allocator Cooling Devices cpufreq RAPL PL1 fan powerclamp trip cool RAPL powercap Framework PL1 동적 조정 → 전력 감소 → 발열 감소 CPU (전력 소비 → 발열) PL1 적용 피드백: 온도 감소 → thermal trip 해제 → PL1 복원
# intel_powerclamp — 강제 idle 삽입으로 CPU 전력/발열 감소
modprobe intel_powerclamp

# 현재 powerclamp 상태 확인
cat /sys/class/thermal/cooling_device*/type | grep -n powerclamp
# intel_powerclamp

# 최대 20% idle 시간 강제 삽입
echo 20 > /sys/class/thermal/cooling_device*/cur_state
# → CPU 사용률 최대 80%로 제한, 전력/온도 감소

# powerclamp 해제
echo 0 > /sys/class/thermal/cooling_device*/cur_state
# thermal zone과 RAPL cooling device 연계 확인
for zone in /sys/class/thermal/thermal_zone*/; do
    echo "=== $(cat ${zone}/type) ==="
    echo "  온도: $(cat ${zone}/temp) m°C"
    echo "  정책: $(cat ${zone}/policy)"
    for trip in ${zone}/trip_point_*_type; do
        idx=$(echo $trip | grep -oP 'trip_point_\K[0-9]+')
        echo "  trip ${idx}: $(cat ${trip}) @ $(cat ${zone}/trip_point_${idx}_temp)m°C"
    done
done
# power_allocator governor 사용 (IPA — Intelligent Power Allocation)
# 여러 cooling device 간 전력 예산을 비례 배분

# thermal zone에 power_allocator 정책 설정
echo "power_allocator" > /sys/class/thermal/thermal_zone0/policy

# sustainable_power 설정 (mW 단위) — 목표 열 평형 전력
echo 15000 > /sys/class/thermal/thermal_zone0/sustainable_power

# 결과: governor가 cpufreq, RAPL, fan 등에 전력을 비례 배분하여
# 목표 온도를 유지하면서 성능을 최대화
연계 방식매커니즘장점적용 시나리오
cpufreq cooling주파수 감소 → 전력/발열 감소빠른 응답, 세밀한 제어일반적인 thermal throttling
RAPL PL1 coolingPL1 하향 → 하드웨어 전력 제한절대 전력 상한 보장랙 전력 예산 관리
intel_powerclamp강제 idle 삽입 → CPU 점유율 제한워크로드 독립적 제어긴급 과열 대응
power_allocatorPID 제어기로 전력 예산 동적 배분최적 성능/열 균형모바일/임베디드 SoC
교차 참조: thermal 서브시스템의 상세 동작은 Thermal 서브시스템 페이지를, cpufreq cooling device는 CPU 주파수 스케일링(Frequency Scaling) 페이지를 참조하십시오.

RAPL 정확도·보안·제한사항

보안 경고 — PLATYPUS 공격 (CVE-2020-8694, CVE-2020-8695): RAPL 에너지 카운터의 높은 해상도를 악용하여 비특권 프로세스가 AES 키 등 민감한 데이터를 추출할 수 있는 사이드 채널 공격이 2020년에 공개되었습니다. 이에 따라 Linux 커널 5.10+에서는 energy_uj 및 perf power 이벤트 접근에 CAP_SYS_RAWIO 또는 root 권한이 필요하도록 변경되었습니다.
항목설명
에너지 해상도약 15.3μJ (2-16 J × 에너지 단위). 실제 정확도는 ±5~10% 수준으로 절대 전력 측정보다는 상대 비교에 적합
카운터 오버플로32비트 에너지 카운터는 max_energy_range_uj 도달 시 0으로 랩어라운드. 고부하 서버에서 ~60초마다 발생 가능 — 폴링 간격 주의
접근 권한 (5.10+)/sys/class/powercap/*/energy_uj: root 또는 CAP_SYS_RAWIO. perf power 이벤트: perf_event_paranoid ≤ 0 또는 CAP_PERFMON
가상화(Virtualization) 환경VM에서는 RAPL MSR 접근이 차단됨 (hypervisor가 trap). KVM -cpu host로 패스스루 가능하나 보안상 비권장
컨테이너(Container)cgroup v2의 perf 이벤트 네임스페이스(Namespace)와 결합하여 컨테이너별 에너지 측정 가능 (Kepler 프로젝트 등 활용)

RAPL 관련 CVE 및 사이드 채널 공격

CVE공격명연도영향완화
CVE-2020-8694PLATYPUS2020비특권 RAPL 읽기로 SGX enclave 내 AES 키 추출커널 5.10: energy_uj root 제한
CVE-2020-8695PLATYPUS2020Intel SGX 환경에서 세밀한 전력 분석으로 비밀 키 복원마이크로코드 업데이트 + 커널 패치(Patch)
CVE-2022-23823Hertzbleed2022CPU 주파수 변동을 통한 암호 키 추출 (RAPL 간접 활용)상수 시간 암호 구현
CVE-2023-20583Collide+Power2023데이터 종속적 전력 소비를 이용한 사이드 채널소프트웨어 완화 (제한적)

SGX와 RAPL의 보안 관계

Intel SGX(Software Guard Extensions) 환경에서 RAPL은 특별한 보안 위험을 가집니다. SGX enclave는 메모리 암호화(Encryption)로 보호되지만, enclave 내부 연산의 전력 소비 패턴은 RAPL 카운터에 반영됩니다. PLATYPUS 공격은 이 점을 악용하여 enclave 내 AES-NI 명령어의 라운드별 전력 차이를 분석하고, 통계적 방법으로 128비트 AES 키를 복원합니다.

완화 조치 발전: 커널 5.10 이전에는 energy_uj가 world-readable(644)이었으나, PLATYPUS 공격 이후 root 전용(400)으로 변경되었습니다. 인텔 마이크로코드 업데이트는 에너지 카운터의 해상도를 의도적으로 낮추어 공격 정밀도를 감소시킵니다. 커널 6.1+에서는 CAP_PERFMON capability로 세분화된 접근 제어(Access Control)가 가능합니다.

접근 제어 발전 이력

커널 버전energy_uj 권한perf power/ 권한비고
< 5.10644 (world-readable)paranoid ≤ 2 허용PLATYPUS 취약
5.10400 (root only)CAP_SYS_RAWIO 또는 rootPLATYPUS 대응
5.13+400 (root only)CAP_PERFMON 지원세분화된 접근 제어
6.1+400 (root only)CAP_PERFMON + BPF 연계Kepler 등 에너지 모니터링 도구 호환
# 현재 perf 접근 권한 확인
cat /proc/sys/kernel/perf_event_paranoid
# 4: 모든 perf 이벤트 제한 (기본값, 일부 배포판)
# 2: 커널 이벤트 제한 (기본값)
# 1: CPU 이벤트 제한
# 0: 제한 없음
# -1: 모든 접근 허용

# RAPL 에너지 읽기가 Permission denied인 경우
sudo sysctl kernel.perf_event_paranoid=0  # 임시 해제 (재부팅 시 초기화)

# 오버플로 범위 확인
cat /sys/class/powercap/intel-rapl:0/max_energy_range_uj
# 예: 262143328850 (≈262 kJ, 150W 시 ~29분마다 오버플로)

가상화 환경 RAPL

가상머신(VM)에서 RAPL MSR에 접근하면 기본적으로 하이퍼바이저(Hypervisor)가 트랩(trap)하여 차단합니다. 이는 호스트의 전력 정보가 게스트에 노출되어 사이드 채널 공격에 악용될 수 있기 때문입니다. 그러나 클라우드 환경에서도 전력 모니터링이 필요한 경우가 있어, 제한적인 패스스루 방법이 제공됩니다.

Guest VM rdmsr 0x611 perf power/energy-pkg/ powercap sysfs 읽기 turbostat KVM / Hypervisor (MSR Filter Layer) MSR trap → #GP (기본 차단) MSR filter → 선택적 허용 vPMU 에뮬레이션 Host Kernel (intel_rapl_msr / powercap) Hardware MSR (RAPL Energy Counters, Power Limits) VM Exit 허용된 MSR만 전달
# KVM MSR 필터 설정 — RAPL MSR 패스스루 (QEMU 6.0+)
# 주의: 보안상 프로덕션에서는 비권장
qemu-system-x86_64 \
    -cpu host \
    -accel kvm \
    # RAPL MSR 패스스루를 위한 KVM 매개변수
    -device intel-rapl,id=rapl0

# KVM ioctl을 통한 MSR 필터 설정 (커널 5.10+)
# KVM_X86_SET_MSR_FILTER로 특정 MSR만 허용
# MSR 0x611 (PKG_ENERGY_STATUS) → 읽기 허용
# MSR 0x619 (DRAM_ENERGY_STATUS) → 읽기 허용
# MSR 0x610 (PKG_POWER_LIMIT) → 차단 유지
# 게스트 VM에서 RAPL 사용 가능 여부 확인
lsmod | grep rapl
# 모듈이 없거나 에너지 값이 0이면 → 하이퍼바이저가 차단 중

cat /sys/class/powercap/intel-rapl:0/energy_uj
# Permission denied 또는 파일 미존재 → MSR 패스스루 필요

# Xen에서 RAPL 확인
xl dmesg | grep -i rapl
# Xen은 dom0에서만 RAPL 접근 허용, domU는 기본 차단
하이퍼바이저RAPL 지원패스스루 방법보안 고려
KVM/QEMUMSR 필터로 선택적 허용-cpu host + MSR filter ioctl에너지 카운터만 허용, PL 쓰기 차단 권장
Xendom0만 기본 허용domU에서는 vpmu 옵션 필요PLATYPUS 이후 기본 비활성화
VMware ESXi제한적ESXi 7.0+에서 호스트 레벨 전력 관리만 지원게스트 접근 불가
Hyper-V미지원호스트 PowerShell로만 전력 모니터링MSR 에뮬레이션 없음
VM 격리(Isolation) 주의: RAPL 에너지 카운터를 VM에 패스스루하면 게스트가 호스트의 물리적 전력 소비 패턴을 관찰할 수 있습니다. 멀티테넌트 클라우드 환경에서는 PLATYPUS 유사 공격의 위험이 있으므로, 신뢰할 수 있는 단일 테넌트 환경에서만 사용하세요.

서버 전력 예산 관리 실전

데이터센터에서 전력은 가장 중요한 운영 비용 중 하나입니다. RAPL의 PL1/PL2 제어를 활용하면 랙·서버·소켓 단위의 세밀한 전력 예산(power budget) 관리가 가능합니다. 시설 전력(facility power), PDU(Power Distribution Unit), 랙, 서버, CPU 소켓까지의 계층적 전력 배분이 핵심입니다.

Facility (10 MW) PDU A (2.5 MW) PDU B (2.5 MW) Rack 1 (20 kW) Rack 2 (20 kW) Rack N (20 kW) Server (500 W) Socket 0 Socket 1 RAPL PL1: 150W/socket DRAM: 50W/socket RAPL 기반 전력 예산 제어 1. 시설 전력 모니터링 (DCIM/BMS) 2. 랙 전력 임계값 초과 감지 (PDU 센서) 3. 서버 RAPL PL1 동적 감소 (BMC/IPMI) 4. 전력 여유 확보 시 PL1 복원 피드백 루프: 전력 초과 → PL1 감소 → 안정화 → PL1 복원
#!/bin/bash
# 랙 전력 예산 관리 스크립트 — RAPL PL1 동적 조정

RACK_BUDGET_W=18000      # 랙 전력 예산 (18 kW)
MARGIN_W=2000             # 안전 마진 (2 kW)
MIN_PL1_UW=80000000       # 최소 PL1 (80W)
SERVERS=("srv01" "srv02" "srv03" "srv04")

# IPMI로 현재 랙 전력 읽기
get_rack_power() {
    local total=0
    for srv in "${SERVERS[@]}"; do
        pw=$(ipmitool -H ${srv}-bmc -U admin -P pass sdr get "Total_Power" | \
             awk '/Sensor Reading/{print $4}')
        total=$(( total + pw ))
    done
    echo $total
}

# PL1 동적 감소
reduce_pl1() {
    local target_uw=$1
    for srv in "${SERVERS[@]}"; do
        ssh ${srv} "echo ${target_uw} > /sys/class/powercap/intel-rapl:0/constraint_0_power_limit_uw"
        ssh ${srv} "echo ${target_uw} > /sys/class/powercap/intel-rapl:1/constraint_0_power_limit_uw"
    done
}

# 메인 루프
while true; do
    current=$(get_rack_power)
    if [ $current -gt $(( RACK_BUDGET_W - MARGIN_W )) ]; then
        echo "[WARN] 랙 전력 ${current}W — 예산 초과 임박, PL1 감소"
        reduce_pl1 $MIN_PL1_UW
    fi
    sleep 10
done
# Redfish API로 서버 전력 제한 (BMC 지원 필요)
curl -k -u admin:pass \
  -X PATCH https://bmc-ip/redfish/v1/Chassis/1/Power \
  -H "Content-Type: application/json" \
  -d '{"PowerControl":[{"PowerLimit":{"LimitInWatts": 300}}]}'

# IPMI로 서버 전력 캡 설정
ipmitool -H bmc-ip -U admin -P pass power cap set 300
ipmitool -H bmc-ip -U admin -P pass power cap enable

# Redfish 전력 상태 조회
curl -k -u admin:pass \
  https://bmc-ip/redfish/v1/Chassis/1/Power | jq '.PowerControl[0]'
# RAPL + IPMI 통합 전력 프로파일링
# 서버 총 전력 (IPMI) vs CPU 전력 (RAPL) 비교

IPMI_POWER=$(ipmitool sdr get "Total_Power" | awk '/Reading/{print $4}')
RAPL_PKG0=$(cat /sys/class/powercap/intel-rapl:0/energy_uj)
sleep 5
RAPL_PKG0_2=$(cat /sys/class/powercap/intel-rapl:0/energy_uj)
CPU_POWER=$(( (RAPL_PKG0_2 - RAPL_PKG0) / 5000000 ))

echo "서버 총 전력: ${IPMI_POWER}W, CPU 전력: ${CPU_POWER}W"
echo "비-CPU 전력 (디스크, NIC, 팬 등): $(( IPMI_POWER - CPU_POWER ))W"
전력 예산 티어PL1 설정성능 비율사용 사례
FullTDP (200W)100%피크 시간 외 또는 전력 여유 시
NormalTDP 80% (160W)~95%일반 운영 (대부분의 시간)
ReducedTDP 60% (120W)~85%전력 경고 1단계
EmergencyTDP 40% (80W)~65%전력 긴급 상황 (UPS 전환 등)
효율 지표계산목표값
PUE (Power Usage Effectiveness)시설 총 전력 / IT 장비 전력< 1.2
Performance per Watt벤치마크 점수 / 평균 전력최대화
RAPL Headroom(PL1 - 실제 전력) / PL1 × 100> 10%
Stranded Power할당 전력 - 실제 사용 전력최소화
실무 팁: 랙 전력 예산의 10~15%를 안전 마진으로 확보하고, RAPL PL1을 4단계(Full/Normal/Reduced/Emergency)로 사전 정의해 두면 전력 긴급 상황에 자동 대응할 수 있습니다. BMC의 Redfish/IPMI 인터페이스와 RAPL sysfs를 조합하면 OS 레벨에서 정밀한 전력 제어가 가능합니다.

Kubernetes/컨테이너 전력 관리

클라우드 네이티브 환경에서 컨테이너별 전력 소비를 측정하고 탄소 인식 스케줄링(carbon-aware scheduling)을 구현하는 것은 지속 가능한 컴퓨팅의 핵심 과제입니다. Kepler (Kubernetes-based Efficient Power Level Exporter)는 RAPL 에너지 카운터와 eBPF를 결합하여 컨테이너/파드 단위의 전력 소비를 추정합니다.

Hardware RAPL MSR (에너지 카운터) CPU perf_event (HPC) GPU (NVML / ROCm) Linux Kernel (eBPF + perf_event + cgroup) Kepler Exporter (DaemonSet) eBPF → cgroup별 에너지 분배 → Prometheus 메트릭 모니터링 & 의사결정 Prometheus Grafana 대시보드 Carbon-Aware Scheduler KEDA Autoscaler 파드별 전력 메트릭 수집 → 대시보드 시각화 전력/탄소 기반 스케줄링 최적화
# Kepler DaemonSet 배포 (Helm)
# helm repo add kepler https://sustainable-computing-io.github.io/kepler-helm-chart
# helm install kepler kepler/kepler --namespace kepler --create-namespace

# 또는 직접 매니페스트 배포
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: kepler-exporter
  namespace: kepler
spec:
  selector:
    matchLabels:
      app: kepler
  template:
    spec:
      containers:
      - name: kepler
        image: quay.io/sustainable_computing_io/kepler:latest
        securityContext:
          privileged: true   # RAPL MSR + eBPF 접근 필요
        volumeMounts:
        - name: modules
          mountPath: /lib/modules
        - name: powercap
          mountPath: /sys/class/powercap
          readOnly: true
      volumes:
      - name: modules
        hostPath: { path: /lib/modules }
      - name: powercap
        hostPath: { path: /sys/class/powercap }
# Kepler PromQL 쿼리 — 파드별 전력 소비 (W)
# 네임스페이스별 총 전력
sum by (container_namespace) (
  rate(kepler_container_joules_total[5m])
)

# 상위 10개 파드 전력 소비
topk(10, sum by (pod_name) (
  rate(kepler_container_joules_total{container_namespace="production"}[5m])
))
# cgroup perf_event를 통한 컨테이너 에너지 측정 (수동)
# 컨테이너 cgroup 경로 확인
CGROUP=$(docker inspect --format '{{.State.Pid}}' mycontainer)
cat /proc/${CGROUP}/cgroup | grep perf_event

# cgroup v2에서 perf로 에너지 측정
perf stat -e power/energy-pkg/ --cgroup /sys/fs/cgroup/system.slice/docker-*.scope -- sleep 10
도구방식수준장단점
KeplerRAPL + eBPF + ML 모델컨테이너/파드가장 정밀한 컨테이너 레벨 추정, CNCF 프로젝트
ScaphandreRAPL + procfs프로세스경량, 컨테이너 환경 지원, Prometheus exporter
PowerAPIRAPL + 소프트웨어 모델프로세스/VM학술 연구 기반, 정밀한 전력 모델링
Intel RAPL 직접sysfs/perf도메인가장 정확하나 프로세스 분리 불가
탄소 인식 스케줄링: Kepler의 전력 데이터와 전력 그리드 탄소 강도(carbon intensity) API를 결합하면, 저탄소 시간대/리전으로 워크로드를 자동 이동시키는 carbon-aware scheduling이 가능합니다. CNCF TAG Environmental Sustainability에서 관련 표준을 개발 중입니다.

RAPL 커널 설정 및 배포판 기본값

RAPL 기능을 사용하려면 커널에서 관련 Kconfig 옵션이 활성화되어 있어야 합니다. 대부분의 주요 배포판은 RAPL을 모듈로 포함하고 있으나, 임베디드나 커스텀 커널에서는 수동 설정이 필요합니다.

# RAPL 관련 Kconfig 옵션 (make menuconfig)

# 필수
CONFIG_POWERCAP=y|m          # powercap 프레임워크 (Device Drivers → Power supply support → Power capping)
CONFIG_INTEL_RAPL_CORE=m     # RAPL 공통 코어 (intel_rapl_common)
CONFIG_INTEL_RAPL_MSR=m      # MSR 기반 백엔드 (대부분의 Intel/AMD CPU)

# 선택적
CONFIG_INTEL_RAPL_TPMI=m     # TPMI 기반 백엔드 (Meteor Lake+, Sapphire Rapids+)
CONFIG_PERF_EVENTS_INTEL_RAPL=y|m  # perf power/energy-*/ 이벤트 (CPU_SUP_INTEL 필요)
CONFIG_SENSORS_AMD_ENERGY=m  # AMD hwmon 에너지 드라이버 (HWMON 필요)

# TPMI 의존성
CONFIG_INTEL_VSEC=m          # Intel Vendor Specific Extended Capabilities
CONFIG_INTEL_TPMI=m          # TPMI 코어 드라이버
# 현재 커널의 RAPL 설정 확인
zgrep -E "RAPL|POWERCAP|AMD_ENERGY" /proc/config.gz
# 또는
grep -E "RAPL|POWERCAP|AMD_ENERGY" /boot/config-$(uname -r)

# 모듈 로드 상태 확인
lsmod | grep -E "rapl|powercap"

# 수동 모듈 로드
sudo modprobe intel_rapl_msr
sudo modprobe intel_rapl_common

# 부팅 시 자동 로드 설정
echo "intel_rapl_msr" | sudo tee /etc/modules-load.d/rapl.conf
Kconfig 옵션모듈명필수 여부설명
CONFIG_POWERCAPpowercap필수powercap 프레임워크 코어
CONFIG_INTEL_RAPL_COREintel_rapl_common필수RAPL 공통 로직 (도메인 관리, 단위 변환)
CONFIG_INTEL_RAPL_MSRintel_rapl_msrIntel/AMDMSR 기반 RAPL 백엔드
CONFIG_INTEL_RAPL_TPMIintel_rapl_tpmiMTL+TPMI MMIO 기반 백엔드
CONFIG_PERF_EVENTS_INTEL_RAPL(빌트인)선택perf power/ 이벤트 지원
CONFIG_SENSORS_AMD_ENERGYamd_energyAMDAMD hwmon 에너지 드라이버
배포판RAPL MSRRAPL TPMIperf RAPLAMD Energy비고
Ubuntu 22.04+mm (24.04+)ym자동 로드, energy_uj 접근 root 필요
Fedora 38+mmymSELinux 정책으로 추가 제한 가능
RHEL 9mm (9.3+)ymperf_event_paranoid=2 기본
Debian 12mmym자동 로드
Arch Linuxmmym최신 커널, 자동 로드
Alpine Linux미포함미포함미포함미포함커스텀 커널 빌드 필요
# 문제 해결: RAPL이 동작하지 않는 경우

# 1. CPU 지원 확인
grep -c rapl /proc/cpuinfo
cat /proc/cpuinfo | head -20 | grep "model name"

# 2. 모듈 로드 실패 → dmesg 확인
dmesg | grep -i rapl
# "intel_rapl_common: Found RAPL domain package" → 정상
# "intel_rapl_msr: no valid RAPL domains" → CPU 미지원 또는 BIOS 비활성화

# 3. BIOS에서 RAPL 비활성화된 경우
# → BIOS Setup → Advanced → Power Management → RAPL → Enable

# 4. 부팅 매개변수로 강제 활성화
# GRUB_CMDLINE_LINUX에 추가:
# intel_rapl.enable=1  (일부 BIOS 잠금 우회)
참고: 커널 5.10 이후 보안 강화로 energy_uj 읽기에 root 권한이 필요합니다. 일반 사용자가 접근하려면 CAP_SYS_RAWIO capability를 부여하거나, udev 규칙으로 파일 권한을 변경할 수 있습니다.

참고 자료

커널 공식 문서

LWN.net 기사

하드웨어 벤더 문서

도구

커널 소스