RAPL & powercap
Linux powercap 프레임워크와 Intel RAPL의 실전 활용을 다룹니다. package/core/uncore/DRAM 도메인별 에너지 카운터 해석, PL1·PL2·time window 기반 전력 제한 모델, MSR·sysfs·hwmon 인터페이스 사용법, thermal·cpufreq와의 상호작용, 전력 캡 적용 시 성능 회귀 검증, 데이터센터 전력 예산 운영 시나리오와 모니터링 지표까지 종합적으로 정리합니다.
핵심 요약
- 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) 에너지 소비를 측정하여 전력 효율을 분석합니다.
단계별 이해
- 현재 전력 확인 —
cat /sys/class/powercap/intel-rapl:0/energy_uj로 현재 소비 에너지를 확인합니다.또는
turbostat --show Package,Core,Uncore --interval 1로 실시간 전력을 모니터링합니다. - 도메인별 측정 —
perf stat -e power/energy-pkg/,power/energy-cores/ ./workload로 워크로드의 에너지 소비를 측정합니다.package와 core 도메인을 분리하여 CPU vs 언코어 전력 비중을 파악합니다.
- 전력 제한 설정 —
echo 25000000 > /sys/class/powercap/intel-rapl:0/constraint_0_power_limit_uw로 PL1을 25W로 제한합니다.열 문제나 배터리 수명 연장이 필요할 때 TDP를 동적으로 조절합니다.
- 효과 검증 — 전력 제한 전후로 벤치마크 성능과 온도/전력을 비교합니다.
stress-ng --cpu 8 --timeout 60s로 부하를 주고turbostat로 차이를 확인하세요.
powercap & RAPL
powercap 프레임워크는 전력 상한(power capping)을 설정하는 통합 인터페이스를 제공합니다. 가장 대표적인 백엔드는 Intel/AMD의 RAPL(Running Average Power Limit)로, 프로세서 패키지·코어·메모리 등 전력 도메인별 에너지 소비를 모니터링하고 제한할 수 있습니다.
powercap/RAPL 아키텍처
RAPL은 하드웨어 MSR(또는 TPMI)에서 에너지 카운터와 전력 제한을 읽고 쓰는 커널 드라이버를 통해 powercap 프레임워크에 등록됩니다. 사용자 공간(User Space)은 sysfs 또는 perf 이벤트를 통해 접근합니다.
RAPL 도메인
RAPL은 프로세서 내부를 여러 전력 도메인(power domain)으로 분리하여 도메인별 에너지 측정과 전력 제한을 제공합니다. 지원 도메인은 프로세서 세대에 따라 다릅니다.
| 도메인 | 설명 | Intel | AMD |
|---|---|---|---|
| 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) 관리에 유용합니다.도메인별 전력 분포
워크로드 유형에 따라 도메인별 전력 소비 비중이 크게 달라집니다. 다음은 실제 측정 데이터입니다:
| 워크로드 | Package | Core | Uncore (iGPU) | DRAM | 특징 |
|---|---|---|---|---|---|
| Idle (유휴) | 8W | 2W (25%) | 3W (37%) | 3W (37%) | 백그라운드 활동 |
| CPU 집약 (컴파일) | 65W | 48W (74%) | 10W (15%) | 7W (11%) | 코어 전력 지배적 |
| 메모리 집약 (STREAM) | 45W | 20W (44%) | 8W (18%) | 17W (38%) | DRAM 전력 증가 |
| GPU 렌더링 (iGPU) | 55W | 15W (27%) | 32W (58%) | 8W (15%) | Uncore 전력 급증 |
| 혼합 (웹 브라우징) | 25W | 12W (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_UNIT | 0x606 | 공통 | O | X | 에너지/전력/시간 단위 정의 |
MSR_PKG_POWER_LIMIT | 0x610 | Package | O | O | PL1/PL2 전력 제한 설정 |
MSR_PKG_ENERGY_STATUS | 0x611 | Package | O | X | 누적 에너지 카운터 |
MSR_PKG_PERF_STATUS | 0x613 | Package | O | X | 전력 제한으로 인한 스로틀 시간 |
MSR_PKG_POWER_INFO | 0x614 | Package | O | X | TDP, 최소/최대 전력 정보 |
MSR_DRAM_POWER_LIMIT | 0x618 | DRAM | O | O | DRAM 전력 제한 |
MSR_DRAM_ENERGY_STATUS | 0x619 | DRAM | O | X | DRAM 에너지 카운터 |
MSR_PP0_POWER_LIMIT | 0x638 | Core (PP0) | O | O | 코어 전력 제한 |
MSR_PP0_ENERGY_STATUS | 0x639 | Core (PP0) | O | X | 코어 에너지 카운터 |
MSR_PP1_POWER_LIMIT | 0x640 | Uncore (PP1) | O | O | Uncore/iGPU 전력 제한 |
MSR_PP1_ENERGY_STATUS | 0x641 | Uncore (PP1) | O | X | Uncore 에너지 카운터 |
MSR_PLATFORM_ENERGY_STATUS | 0x64D | Platform (psys) | O | X | 플랫폼 전체 에너지 |
MSR_PLATFORM_POWER_LIMIT | 0x65C | Platform (psys) | O | O | 플랫폼 전력 제한 |
MSR_RAPL_POWER_UNIT (0x606) 비트 필드
| 비트 | 필드 | 설명 | 기본값 (일반적) |
|---|---|---|---|
| [3:0] | Power Units | 전력 단위: 1 / 2N 와트. N=3이면 1/8 W = 0.125 W | 3 (0.125 W) |
| [7:4] | Reserved | 예약 | — |
| [12:8] | Energy Status Units | 에너지 단위: 1 / 2N 줄. N=16이면 ~15.3 μJ | 16 (~15.3 μJ) |
| [15:13] | Reserved | 예약 | — |
| [19:16] | Time Units | 시간 단위: 1 / 2N 초. N=10이면 ~976 μs | 10 (~976 μs) |
| [63:20] | Reserved | 예약 | — |
MSR_PKG_POWER_LIMIT (0x610) 비트 필드
| 비트 | 필드 | 설명 |
|---|---|---|
| [14:0] | PL1 Power Limit | 장기 전력 제한 (Power Units 단위) |
| [15] | PL1 Enable | PL1 활성화 (1=활성) |
| [16] | PL1 Clamping | 1이면 OS 요청 주파수 이하로도 제한 가능 |
| [23:17] | PL1 Time Window | Y × 2Z × Time Unit (Y=[23:22], Z=[21:17]) |
| [31:24] | Reserved | 예약 |
| [46:32] | PL2 Power Limit | 단기 전력 제한 (Power Units 단위) |
| [47] | PL2 Enable | PL2 활성화 |
| [48] | PL2 Clamping | PL2 클램핑 활성화 |
| [55:49] | PL2 Time Window | PL2 시간 윈도우 |
| [62:56] | Reserved | 예약 |
| [63] | Lock | 1이면 재부팅까지 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가 잠금, 수정 불가)"
에너지 카운터: 단위 변환·오버플로
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 |
|---|---|---|---|---|
| PL1 | Long-Term (장기) | 1~128초 (설정 가능) | 지속 가능한 TDP. 윈도우 내 평균 전력이 PL1 이하 유지 | MSR_PKG_POWER_LIMIT [14:0] |
| PL2 | Short-Term (단기) | 1~10ms 수준 | Turbo Boost 시 허용하는 순간 최대 전력. PL1의 1.2~1.5배 | MSR_PKG_POWER_LIMIT [46:32] |
| PL3 | Peak Power (피크) | ~10ms | 배터리 기반 시스템의 순간 피크 제한 (Kaby Lake+) | MSR_PL3_CONTROL |
| PL4 | Max Power (최대) | 즉시 | 하드웨어 즉시 차단 — 전류/전력 한계 초과 시 주파수 급강하 | MSR_VR_CURRENT_CONFIG |
PL 전력 제한 타임라인
다음 다이어그램은 워크로드 시작 시 PL1/PL2/PL4가 시간에 따라 어떻게 작동하는지 보여줍니다:
/* 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
powercap sysfs 인터페이스
RAPL 커널 드라이버 구조
커널의 RAPL 지원은 공통 로직과 하드웨어 백엔드로 분리된 모듈러 구조입니다.
| 모듈 | 경로 | 역할 |
|---|---|---|
| intel_rapl_common | drivers/powercap/intel_rapl_common.c | RAPL 도메인 관리, powercap zone 등록, 에너지 단위 변환, PL 읽기/쓰기 공통 로직 |
| intel_rapl_msr | drivers/powercap/intel_rapl_msr.c | MSR 기반 백엔드 — 대부분의 Intel/AMD CPU. rdmsr/wrmsr로 RAPL MSR 접근 |
| intel_rapl_tpmi | drivers/powercap/intel_rapl_tpmi.c | TPMI(Topology Aware Register and PM Capsule Interface) 백엔드 — Meteor Lake+ MMIO 기반 |
| amd_energy | drivers/hwmon/amd_energy.c | AMD 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 인터페이스를 자동으로 제공받습니다.
/* 최소 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" 등) |
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 등 후속 세대에서 전면 채택되었습니다.
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 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 | 이름 | 커널 드라이버 | 설명 |
|---|---|---|---|
| 0 | RAPL | intel_rapl_tpmi | MMIO 기반 RAPL 도메인 — 에너지 측정 및 전력 제한 |
| 1 | PEM | (커널 내부) | Performance and Energy Monitoring — 성능/에너지 모니터링 |
| 2 | UFS | uncore-freq-tpmi | Uncore Frequency Scaling — 다이별 언코어 주파수 제어 |
| 5 | SST | isst_tpmi | Intel Speed Select Technology — PP/BF/TF/CP 프로파일 |
| 8 | PLR | tpmi_plr | Performance Limit Reasons — 스로틀링 원인 보고 (debugfs) |
| 10 | UMS | uncore-freq-tpmi | Uncore Mesh/SoC 주파수 제어 |
| 12 | PWR_DMN | tpmi_power_domains | 전력 도메인 파티셔닝 |
| 0x81 | INFO | (TPMI 코어 내부) | CPU↔PCI 토폴로지 매핑 (패키지 ID, PCI BDF). 실제 PM 기능이 아닌 메타 정보 |
TPMI_INFO_ID(0x81)는 CPU 소켓과 PCI 디바이스 간의 매핑 정보를 제공하는 특수 pseudo-feature입니다. TPMI 코어가 이 정보를 읽어 intel_tpmi_plat_info의 package_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 },
},
},
};
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-PP | Performance Profile — 미리 정의된 주파수/TDP 프로파일 전환 | 워크로드에 따라 코어 수 vs 주파수 트레이드오프 |
| SST-BF | Base Frequency — 특정 코어의 기본 주파수를 상향 | 지연(Latency)시간에 민감한 코어에 높은 보장 주파수 할당 |
| SST-TF | Turbo Frequency — 특정 코어에 터보 주파수 우선 배분 | 고성능 요구 스레드(Thread)에 터보 주파수 집중 |
| SST-CP | Core 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 주파수 제어를 지원합니다.
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
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.h | TPMI API 헤더 — Feature ID 상수, 플랫폼 정보 구조체, 헬퍼 함수 |
drivers/platform/x86/intel/vsec.c | PCI VSEC 드라이버 — TPMI 타입 감지 및 코어 디바이스 생성 |
drivers/platform/x86/intel/tpmi.c | TPMI 코어 — PFS 파싱, MMIO 매핑, auxiliary 디바이스 생성, debugfs (커널 6.13+에서 vsec_tpmi.c로 개명) |
drivers/powercap/intel_rapl_tpmi.c | RAPL 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.3 | TPMI 기본 열거 드라이버 병합 (tpmi.c) |
| 6.4 | RAPL TPMI 드라이버 (intel_rapl_tpmi.c) 병합 |
| 6.5 | Uncore 주파수 TPMI 지원, SST via TPMI |
| 6.5~6.6 | TPMI debugfs, 기능 잠금 상태 인터페이스 |
| 6.6+ | CPU 토폴로지/도메인 매핑, 클러스터 레벨 제어 |
| 6.13 | 드라이버 tpmi.c → vsec_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 RAPL | AMD RAPL |
|---|---|---|
| 지원 시작 | Sandy Bridge (2세대, 2011) | Zen (Family 17h, 2017) |
| 도메인 | package, core, uncore, dram, psys | package, core (Zen 2+에서 확장) |
| MSR 주소 | 606h, 610h, 611h, 619h, 641h 등 | C001_0299h (core), C001_029Ah (pkg) 등 |
| 전력 제한 쓰기 | PL1/PL2 쓰기 가능 | 읽기 전용 (에너지 측정만, 전력 제한 설정 불가) |
| 커널 드라이버 | intel_rapl_msr / intel_rapl_tpmi | intel_rapl_msr (AMD 지원 포함) |
| perf 이벤트 | power/energy-pkg,cores,ram/ | power/energy-pkg,cores/ |
Zen 세대별 RAPL 지원 차이
| 세대 | Family/Model | 제품 | RAPL 도메인 | 특이사항 |
|---|---|---|---|---|
| Zen (2017) | 17h/01h | Ryzen 1000, EPYC 7001 | package만 | core 에너지 미지원, 정확도 낮음 |
| Zen+ (2018) | 17h/08h | Ryzen 2000, EPYC 7002 | package, core | core 도메인 추가 |
| Zen 2 (2019) | 17h/31h | Ryzen 3000, EPYC 7002 | package, core | 에너지 정확도 향상, 칩렛 구조 반영 |
| Zen 3 (2020) | 19h/01h | Ryzen 5000, EPYC 7003 | package, core | 통합 CCX 구조, 전력 효율 개선 |
| Zen 4 (2022) | 19h/61h | Ryzen 7000, EPYC 9004 | package, core | 5nm, iGPU 전력 포함 (package 도메인) |
| Zen 5 (2024) | 1Ah | Ryzen 9000, EPYC 9005 | package, 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_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_pstate 드라이버의 EPP(Energy Performance Preference)를 통해 관리합니다.Intel vs AMD 전력 관리 종합 비교
Intel과 AMD는 서로 다른 전력 관리 철학과 아키텍처를 채택하고 있습니다. Intel은 RAPL을 통한 OS 레벨의 세밀한 전력 제어를 제공하는 반면, AMD는 SMU 펌웨어 기반의 자율적 전력 관리에 초점을 맞춥니다.
# 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
| 기능 | Intel | AMD |
|---|---|---|
| 전력 제한 계층 | PL1 (장기), PL2 (단기), PL3 (피크), PL4 (즉시) | PPT (패키지), STAPM (지속), EDC (피크 전류), TDC (지속 전류) |
| OS 전력 제어 | PL1/PL2 sysfs 쓰기 가능 | 읽기 전용 (BIOS/SMU만 제어) |
| 에너지 측정 도메인 | package, core, uncore, dram, psys | package, core |
| 커널 드라이버 | intel_rapl_msr, intel_rapl_tpmi | intel_rapl_msr, amd_energy |
| 전력 제어 주체 | OS (커널 드라이버) + 하드웨어 | SMU 펌웨어 (하드웨어 자율) |
| 인터페이스 | MSR + TPMI MMIO | MSR (에너지), SMU mailbox (전력 제한) |
| DRAM 에너지 | 지원 (서버: Sandy Bridge-EP+, 클라이언트: Haswell+) | 미지원 |
| 플랫폼 전력 | psys 도메인 (Skylake+ 모바일) | 미지원 |
| Intel MSR | 주소 | AMD 대응 | 주소 |
|---|---|---|---|
| MSR_RAPL_POWER_UNIT | 0x606 | MSR_AMD_RAPL_POWER_UNIT | 0xC001_0299 |
| MSR_PKG_ENERGY_STATUS | 0x611 | MSR_AMD_PKG_ENERGY_STATUS | 0xC001_029B |
| MSR_PP0_ENERGY_STATUS | 0x639 | MSR_AMD_CORE_ENERGY_STATUS | 0xC001_029A |
| MSR_PKG_POWER_LIMIT | 0x610 | (해당 없음) | SMU 펌웨어 제어 |
| MSR_DRAM_ENERGY_STATUS | 0x619 | (미지원) | — |
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 J | 100% (기준) | 45W | 1.0× |
| 25W 제한 | ~900 J | ~85% | 25W | 1.4× |
| 15W 제한 | ~750 J | ~65% | 15W | 1.6× |
예제 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가 원래대로 복구
전력 제한 스로틀링 디버깅
시스템 성능이 예상보다 낮을 때, 원인이 열 제한인지 전력 제한인지를 구별하는 것이 중요합니다. Intel CPU는 MSR_CORE_PERF_LIMIT_REASONS(0x64F)와 MSR_RING_PERF_LIMIT_REASONS(0x6B1) 레지스터를 통해 스로틀링 원인을 비트 단위로 보고합니다.
# 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
| 비트 | 이름 | 원인 | 대응 |
|---|---|---|---|
| 0 | PROCHOT Status | 외부 PROCHOT# 신호 (VR 과열 등) | VRM 쿨링, 보드 점검 |
| 1 | Thermal Status | CPU 코어 온도 Tj_max 도달 | 쿨러 성능 개선, 써멀 페이스트 |
| 5 | RAPL Thermal | 이동 평균 열 제한 | 장시간 부하 시 쿨링 부족 |
| 6 | VR Thermal Alert | 전압 레귤레이터 과열 | VRM 방열판, 에어플로우 |
| 10 | PL1 Power Limit | 장기 전력 제한 초과 | PL1 상향 또는 워크로드 조정 |
| 11 | PL2 Power Limit | 단기 전력 제한 초과 | PL2 상향, Turbo 시간 부족 |
| 12 | Max Turbo Limit | 최대 터보 주파수 도달 | 정상 (설계 한계) |
| 13 | Turbo 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 PkgWatt | PL1 이하 |
| TPMI PLR | cat /sys/kernel/debug/tpmi-plr/die0/status | 0 (제한 없음) |
turbostat의 Throttle 컬럼과 rdmsr 0x64F의 스티키 비트(bit[16~25])를 함께 확인하면, 현재 상태와 과거에 발생한 스로틀링 이벤트를 모두 파악할 수 있습니다. 벤치마크 시작 전에 wrmsr 0x64F 0으로 스티키 비트를 클리어하면 정확한 진단이 가능합니다.RAPL과 thermal 서브시스템 연계
Linux thermal 프레임워크는 CPU 온도가 임계값에 도달하면 cooling device를 활성화하여 발열을 제어합니다. RAPL의 전력 제한(PL1)은 가장 효과적인 cooling 수단 중 하나이며, thermal 서브시스템과의 연계를 통해 자동화된 전력-열 관리가 가능합니다.
# 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 cooling | PL1 하향 → 하드웨어 전력 제한 | 절대 전력 상한 보장 | 랙 전력 예산 관리 |
| intel_powerclamp | 강제 idle 삽입 → CPU 점유율 제한 | 워크로드 독립적 제어 | 긴급 과열 대응 |
| power_allocator | PID 제어기로 전력 예산 동적 배분 | 최적 성능/열 균형 | 모바일/임베디드 SoC |
RAPL 정확도·보안·제한사항
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-8694 | PLATYPUS | 2020 | 비특권 RAPL 읽기로 SGX enclave 내 AES 키 추출 | 커널 5.10: energy_uj root 제한 |
| CVE-2020-8695 | PLATYPUS | 2020 | Intel SGX 환경에서 세밀한 전력 분석으로 비밀 키 복원 | 마이크로코드 업데이트 + 커널 패치(Patch) |
| CVE-2022-23823 | Hertzbleed | 2022 | CPU 주파수 변동을 통한 암호 키 추출 (RAPL 간접 활용) | 상수 시간 암호 구현 |
| CVE-2023-20583 | Collide+Power | 2023 | 데이터 종속적 전력 소비를 이용한 사이드 채널 | 소프트웨어 완화 (제한적) |
SGX와 RAPL의 보안 관계
Intel SGX(Software Guard Extensions) 환경에서 RAPL은 특별한 보안 위험을 가집니다. SGX enclave는 메모리 암호화(Encryption)로 보호되지만, enclave 내부 연산의 전력 소비 패턴은 RAPL 카운터에 반영됩니다. PLATYPUS 공격은 이 점을 악용하여 enclave 내 AES-NI 명령어의 라운드별 전력 차이를 분석하고, 통계적 방법으로 128비트 AES 키를 복원합니다.
energy_uj가 world-readable(644)이었으나, PLATYPUS 공격 이후 root 전용(400)으로 변경되었습니다. 인텔 마이크로코드 업데이트는 에너지 카운터의 해상도를 의도적으로 낮추어 공격 정밀도를 감소시킵니다. 커널 6.1+에서는 CAP_PERFMON capability로 세분화된 접근 제어(Access Control)가 가능합니다.접근 제어 발전 이력
| 커널 버전 | energy_uj 권한 | perf power/ 권한 | 비고 |
|---|---|---|---|
| < 5.10 | 644 (world-readable) | paranoid ≤ 2 허용 | PLATYPUS 취약 |
| 5.10 | 400 (root only) | CAP_SYS_RAWIO 또는 root | PLATYPUS 대응 |
| 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)하여 차단합니다. 이는 호스트의 전력 정보가 게스트에 노출되어 사이드 채널 공격에 악용될 수 있기 때문입니다. 그러나 클라우드 환경에서도 전력 모니터링이 필요한 경우가 있어, 제한적인 패스스루 방법이 제공됩니다.
# 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/QEMU | MSR 필터로 선택적 허용 | -cpu host + MSR filter ioctl | 에너지 카운터만 허용, PL 쓰기 차단 권장 |
| Xen | dom0만 기본 허용 | domU에서는 vpmu 옵션 필요 | PLATYPUS 이후 기본 비활성화 |
| VMware ESXi | 제한적 | ESXi 7.0+에서 호스트 레벨 전력 관리만 지원 | 게스트 접근 불가 |
| Hyper-V | 미지원 | 호스트 PowerShell로만 전력 모니터링 | MSR 에뮬레이션 없음 |
서버 전력 예산 관리 실전
데이터센터에서 전력은 가장 중요한 운영 비용 중 하나입니다. RAPL의 PL1/PL2 제어를 활용하면 랙·서버·소켓 단위의 세밀한 전력 예산(power budget) 관리가 가능합니다. 시설 전력(facility power), PDU(Power Distribution Unit), 랙, 서버, CPU 소켓까지의 계층적 전력 배분이 핵심입니다.
#!/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 설정 | 성능 비율 | 사용 사례 |
|---|---|---|---|
| Full | TDP (200W) | 100% | 피크 시간 외 또는 전력 여유 시 |
| Normal | TDP 80% (160W) | ~95% | 일반 운영 (대부분의 시간) |
| Reduced | TDP 60% (120W) | ~85% | 전력 경고 1단계 |
| Emergency | TDP 40% (80W) | ~65% | 전력 긴급 상황 (UPS 전환 등) |
| 효율 지표 | 계산 | 목표값 |
|---|---|---|
| PUE (Power Usage Effectiveness) | 시설 총 전력 / IT 장비 전력 | < 1.2 |
| Performance per Watt | 벤치마크 점수 / 평균 전력 | 최대화 |
| RAPL Headroom | (PL1 - 실제 전력) / PL1 × 100 | > 10% |
| Stranded Power | 할당 전력 - 실제 사용 전력 | 최소화 |
Kubernetes/컨테이너 전력 관리
클라우드 네이티브 환경에서 컨테이너별 전력 소비를 측정하고 탄소 인식 스케줄링(carbon-aware scheduling)을 구현하는 것은 지속 가능한 컴퓨팅의 핵심 과제입니다. Kepler (Kubernetes-based Efficient Power Level Exporter)는 RAPL 에너지 카운터와 eBPF를 결합하여 컨테이너/파드 단위의 전력 소비를 추정합니다.
# 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
| 도구 | 방식 | 수준 | 장단점 |
|---|---|---|---|
| Kepler | RAPL + eBPF + ML 모델 | 컨테이너/파드 | 가장 정밀한 컨테이너 레벨 추정, CNCF 프로젝트 |
| Scaphandre | RAPL + procfs | 프로세스 | 경량, 컨테이너 환경 지원, Prometheus exporter |
| PowerAPI | RAPL + 소프트웨어 모델 | 프로세스/VM | 학술 연구 기반, 정밀한 전력 모델링 |
| Intel RAPL 직접 | sysfs/perf | 도메인 | 가장 정확하나 프로세스 분리 불가 |
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_POWERCAP | powercap | 필수 | powercap 프레임워크 코어 |
CONFIG_INTEL_RAPL_CORE | intel_rapl_common | 필수 | RAPL 공통 로직 (도메인 관리, 단위 변환) |
CONFIG_INTEL_RAPL_MSR | intel_rapl_msr | Intel/AMD | MSR 기반 RAPL 백엔드 |
CONFIG_INTEL_RAPL_TPMI | intel_rapl_tpmi | MTL+ | TPMI MMIO 기반 백엔드 |
CONFIG_PERF_EVENTS_INTEL_RAPL | (빌트인) | 선택 | perf power/ 이벤트 지원 |
CONFIG_SENSORS_AMD_ENERGY | amd_energy | AMD | AMD hwmon 에너지 드라이버 |
| 배포판 | RAPL MSR | RAPL TPMI | perf RAPL | AMD Energy | 비고 |
|---|---|---|---|---|---|
| Ubuntu 22.04+ | m | m (24.04+) | y | m | 자동 로드, energy_uj 접근 root 필요 |
| Fedora 38+ | m | m | y | m | SELinux 정책으로 추가 제한 가능 |
| RHEL 9 | m | m (9.3+) | y | m | perf_event_paranoid=2 기본 |
| Debian 12 | m | m | y | m | 자동 로드 |
| Arch Linux | m | m | y | m | 최신 커널, 자동 로드 |
| 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 잠금 우회)
energy_uj 읽기에 root 권한이 필요합니다. 일반 사용자가 접근하려면 CAP_SYS_RAWIO capability를 부여하거나, udev 규칙으로 파일 권한을 변경할 수 있습니다.참고 자료
커널 공식 문서
- Power Capping Framework — powercap sysfs 인터페이스 설계
- Intel RAPL Driver — RAPL 커널 드라이버 관리자 가이드
- Dynamic Thermal Power Management (DTPM) — 동적 열 전력 관리
- Power Allocator Governor — IPA와 전력 제한 연동
LWN.net 기사
- The power capping framework — powercap 프레임워크 도입 배경
- RAPL and running average power — RAPL MSR 활용과 전력 측정
- RAPL and power side channels — PLATYPUS 공격과 RAPL 보안 제한
- DTPM — Dynamic Thermal Power Management — 소프트웨어 기반 전력 할당
하드웨어 벤더 문서
- Intel RAPL Energy Reporting — Intel RAPL MSR 레지스터 사양 및 보안 가이드
- AMD Developer Resources — AMD RAPL 호환 MSR 문서
도구
- powercap userspace library — powercap sysfs C 라이브러리
- Scaphandre — RAPL 기반 에너지 소비 모니터링 에이전트
turbostat— Intel CPU 전력/주파수/C-state 실시간 모니터 (tools/power/x86/turbostat/)perf stat -e power/energy-pkg/— perf로 RAPL 에너지 카운터 읽기
커널 소스
drivers/powercap/powercap_sys.c— powercap sysfs 코어drivers/powercap/intel_rapl_common.c— Intel RAPL 공통 로직drivers/powercap/intel_rapl_msr.c— RAPL MSR 백엔드drivers/powercap/intel_rapl_tpmi.c— RAPL TPMI 백엔드 (최신 플랫폼)drivers/powercap/dtpm.c— DTPM 프레임워크arch/x86/include/asm/msr-index.h— RAPL MSR 주소 정의