요약·해설과 원문, 전문 번역을 서로 분리했습니다. API 이름, symbol, source path는 원문 표기를 사용합니다.
1. 요약·해설
원문의 핵심 논리와 kernel programming 관점의 보충 설명입니다. 아래의 전문 번역과는 별도로 작성했습니다.
2. 영어 원문 전체
번역 기준이 된 Linux v6.18.37 원문입니다. 줄 번호는 이 버전의 파일 좌표입니다.
원문 전체 펼치기
.. SPDX-License-Identifier: GPL-2.0
.. _vpa-dtl:
===================================
DTL (Dispatch Trace Log)
===================================
Athira Rajeev, 19 April 2025
.. contents::
:depth: 3
Basic overview
==============
The pseries Shared Processor Logical Partition(SPLPAR) machines can
retrieve a log of dispatch and preempt events from the hypervisor
using data from Disptach Trace Log(DTL) buffer. With this information,
user can retrieve when and why each dispatch & preempt has occurred.
The vpa-dtl PMU exposes the Virtual Processor Area(VPA) DTL counters
via perf.
Infrastructure used
===================
The VPA DTL PMU counters do not interrupt on overflow or generate any
PMI interrupts. Therefore, hrtimer is used to poll the DTL data. The timer
nterval can be provided by user via sample_period field in nano seconds.
vpa dtl pmu has one hrtimer added per vpa-dtl pmu thread. DTL (Dispatch
Trace Log) contains information about dispatch/preempt, enqueue time etc.
We directly copy the DTL buffer data as part of auxiliary buffer and it
will be processed later. This will avoid time taken to create samples
in the kernel space. The PMU driver collecting Dispatch Trace Log (DTL)
entries makes use of AUX support in perf infrastructure. On the tools side,
this data is made available as PERF_RECORD_AUXTRACE records.
To correlate each DTL entry with other events across CPU's, an auxtrace_queue
is created for each CPU. Each auxtrace queue has a array/list of auxtrace buffers.
All auxtrace queues is maintained in auxtrace heap. The queues are sorted
based on timestamp. When the different PERF_RECORD_XX records are processed,
compare the timestamp of perf record with timestamp of top element in the
auxtrace heap so that DTL events can be co-related with other events
Process the auxtrace queue if the timestamp of element from heap is
lower than timestamp from entry in perf record. Sometimes it could happen that
one buffer is only partially processed. if the timestamp of occurrence of
another event is more than currently processed element in the queue, it will
move on to next perf record. So keep track of position of buffer to continue
processing next time. Update the timestamp of the auxtrace heap with the timestamp
of last processed entry from the auxtrace buffer.
This infrastructure ensures dispatch trace log entries can be correlated
and presented along with other events like sched.
vpa-dtl PMU example usage
=========================
.. code-block:: sh
# ls /sys/devices/vpa_dtl/
events format perf_event_mux_interval_ms power subsystem type uevent
To capture the DTL data using perf record:
.. code-block:: sh
# ./perf record -a -e sched:\*,vpa_dtl/dtl_all/ -c 1000000000 sleep 1
The result can be interpreted using perf record. Snippet of perf report -D
.. code-block:: sh
# ./perf report -D
There are different PERF_RECORD_XX records. In that records corresponding to
auxtrace buffers includes:
1. PERF_RECORD_AUX
Conveys that new data is available in AUX area
2. PERF_RECORD_AUXTRACE_INFO
Describes offset and size of auxtrace data in the buffers
3. PERF_RECORD_AUXTRACE
This is the record that defines the auxtrace data which here in case of
vpa-dtl pmu is dispatch trace log data.
Snippet from perf report -D showing the PERF_RECORD_AUXTRACE dump
.. code-block:: sh
0 0 0x39b10 [0x30]: PERF_RECORD_AUXTRACE size: 0x690 offset: 0 ref: 0 idx: 0 tid: -1 cpu: 0
.
. ... VPA DTL PMU data: size 1680 bytes, entries is 35
. 00000000: boot_tb: 21349649546353231, tb_freq: 512000000
. 00000030: dispatch_reason:decrementer interrupt, preempt_reason:H_CEDE, enqueue_to_dispatch_time:7064, ready_to_enqueue_time:187, waiting_to_ready_time:6611773
. 00000060: dispatch_reason:priv doorbell, preempt_reason:H_CEDE, enqueue_to_dispatch_time:146, ready_to_enqueue_time:0, waiting_to_ready_time:15359437
. 00000090: dispatch_reason:decrementer interrupt, preempt_reason:H_CEDE, enqueue_to_dispatch_time:4868, ready_to_enqueue_time:232, waiting_to_ready_time:5100709
. 000000c0: dispatch_reason:priv doorbell, preempt_reason:H_CEDE, enqueue_to_dispatch_time:179, ready_to_enqueue_time:0, waiting_to_ready_time:30714243
. 000000f0: dispatch_reason:priv doorbell, preempt_reason:H_CEDE, enqueue_to_dispatch_time:197, ready_to_enqueue_time:0, waiting_to_ready_time:15350648
. 00000120: dispatch_reason:priv doorbell, preempt_reason:H_CEDE, enqueue_to_dispatch_time:213, ready_to_enqueue_time:0, waiting_to_ready_time:15353446
. 00000150: dispatch_reason:priv doorbell, preempt_reason:H_CEDE, enqueue_to_dispatch_time:212, ready_to_enqueue_time:0, waiting_to_ready_time:15355126
. 00000180: dispatch_reason:decrementer interrupt, preempt_reason:H_CEDE, enqueue_to_dispatch_time:6368, ready_to_enqueue_time:164, waiting_to_ready_time:5104665
Above is representation of dtl entry of below format:
struct dtl_entry {
u8 dispatch_reason;
u8 preempt_reason;
u16 processor_id;
u32 enqueue_to_dispatch_time;
u32 ready_to_enqueue_time;
u32 waiting_to_ready_time;
u64 timebase;
u64 fault_addr;
u64 srr0;
u64 srr1;
};
First two fields represent the dispatch reason and preempt reason. The post
processing of PERF_RECORD_AUXTRACE records will translate to meaningful data
for user to consume.
Visualize the dispatch trace log entries with perf report
=========================================================
.. code-block:: sh
# ./perf record -a -e sched:*,vpa_dtl/dtl_all/ -c 1000000000 sleep 1
[ perf record: Woken up 1 times to write data ]
[ perf record: Captured and wrote 0.300 MB perf.data ]
# ./perf report
# Samples: 321 of event 'vpa-dtl'
# Event count (approx.): 321
#
# Children Self Command Shared Object Symbol
# ........ ........ ....... ................. ..............................
#
100.00% 100.00% swapper [kernel.kallsyms] [k] plpar_hcall_norets_notrace
Visualize the dispatch trace log entries with perf script
=========================================================
.. code-block:: sh
# ./perf script
migration/9 67 [009] 105373.359903: sched:sched_waking: comm=perf pid=13418 prio=120 target_cpu=009
migration/9 67 [009] 105373.359904: sched:sched_migrate_task: comm=perf pid=13418 prio=120 orig_cpu=9 dest_cpu=10
migration/9 67 [009] 105373.359907: sched:sched_stat_runtime: comm=migration/9 pid=67 runtime=4050 [ns]
migration/9 67 [009] 105373.359908: sched:sched_switch: prev_comm=migration/9 prev_pid=67 prev_prio=0 prev_state=S ==> next_comm=swapper/9 next_pid=0 next_prio=120
:256 256 [016] 105373.359913: vpa-dtl: timebase: 21403600706628832 dispatch_reason:decrementer interrupt, preempt_reason:H_CEDE, enqueue_to_dispatch_time:4854, ready_to_enqueue_time:139, waiting_to_ready_time:511842115 c0000000000fcd28 plpar_hcall_norets_notrace+0x18 ([kernel.kallsyms])
:256 256 [017] 105373.360012: vpa-dtl: timebase: 21403600706679454 dispatch_reason:priv doorbell, preempt_reason:H_CEDE, enqueue_to_dispatch_time:236, ready_to_enqueue_time:0, waiting_to_ready_time:133864583 c0000000000fcd28 plpar_hcall_norets_notrace+0x18 ([kernel.kallsyms])
perf 13418 [010] 105373.360048: sched:sched_stat_runtime: comm=perf pid=13418 runtime=139748 [ns]
perf 13418 [010] 105373.360052: sched:sched_waking: comm=migration/10 pid=72 prio=0 target_cpu=010
3. 한국어 전문 번역
영어 원문의 문단 순서와 의미를 유지한 전체 번역입니다. 코드, 함수명, symbol과 URL은 원문 표기를 유지합니다.
DTL (Dispatch Trace Log)
1-13Athira Rajeev가 2025-04-19 작성한 이 문서는 pseries VPA Dispatch Trace Log를 perf AUX trace로 수집하고 해석하는 방법을 설명합니다.
기본 개요
14-23Pseries Shared Processor Logical Partition(SPLPAR)은 VPA DTL buffer에서 Hypervisor의 dispatch/preempt event log를 가져와 각 event의 시점과 이유를 확인할 수 있습니다. `vpa-dtl` PMU가 VPA DTL counter를 perf에 노출합니다.
Perf AUX infrastructure
24-54VPA DTL PMU counter는 overflow interrupt나 PMI를 만들지 않으므로 `hrtimer`로 DTL data를 polling합니다. User는 nanosecond 단위 `sample_period`로 interval을 지정하며 vpa-dtl PMU thread마다 hrtimer 하나가 있습니다.
DTL에는 dispatch/preempt, enqueue time 등이 있습니다. Driver는 kernel에서 sample을 다시 만들지 않고 DTL buffer를 AUX buffer에 직접 copy하여 overhead를 줄입니다. Tool에서는 `PERF_RECORD_AUXTRACE` record로 제공합니다.
CPU 사이 DTL entry와 다른 event를 correlate하기 위해 CPU마다 `auxtrace_queue`를 만들고 여러 auxtrace buffer를 둡니다. 모든 queue는 timestamp로 정렬된 auxtrace heap에서 관리합니다.
Perf record timestamp와 heap top timestamp를 비교하여 heap entry가 더 이르면 해당 queue를 처리합니다. Buffer 일부만 처리한 경우 position을 보존해 다음번에 이어가고 마지막 처리 entry timestamp로 heap을 update합니다.
이 infrastructure로 DTL entry를 `sched` 같은 다른 event와 함께 시간순으로 제시할 수 있습니다.
Interrupt 없는 DTL buffer를 timer로 읽어 perf AUX record로 전달합니다.
Timestamp heap이 CPU별 queue와 일반 perf record를 시간순으로 merge합니다.
VPA-DTL PMU sysfs
55-63VPA-DTL PMU device의 sysfs entry 예입니다.
# ls /sys/devices/vpa_dtl/
events format perf_event_mux_interval_ms power subsystem type uevent
Perf record로 DTL capture
64-70다음 command는 system-wide sched event와 `vpa_dtl/dtl_all/`을 1초 동안 함께 기록하며 sample period는 1,000,000,000입니다.
# ./perf record -a -e sched:\*,vpa_dtl/dtl_all/ -c 1000000000 sleep 1
Perf AUX record 종류
71-87Raw record는 `perf report -D`로 확인합니다.
# ./perf report -D
| Record | 역할 |
|---|---|
| `PERF_RECORD_AUX` | AUX area에 새 data가 있음을 알림 |
| `PERF_RECORD_AUXTRACE_INFO` | Buffer의 auxtrace data offset과 size 설명 |
| `PERF_RECORD_AUXTRACE` | VPA-DTL PMU의 실제 Dispatch Trace Log auxtrace data |
PERF_RECORD_AUXTRACE dump
88-104Dump에는 AUXTRACE size/offset, boot timebase와 frequency, 각 DTL entry의 dispatch/preempt reason 및 세 단계 latency가 표시됩니다.
0 0 0x39b10 [0x30]: PERF_RECORD_AUXTRACE size: 0x690 offset: 0 ref: 0 idx: 0 tid: -1 cpu: 0
.
. ... VPA DTL PMU data: size 1680 bytes, entries is 35
. 00000000: boot_tb: 21349649546353231, tb_freq: 512000000
. 00000030: dispatch_reason:decrementer interrupt, preempt_reason:H_CEDE, enqueue_to_dispatch_time:7064, ready_to_enqueue_time:187, waiting_to_ready_time:6611773
. 00000060: dispatch_reason:priv doorbell, preempt_reason:H_CEDE, enqueue_to_dispatch_time:146, ready_to_enqueue_time:0, waiting_to_ready_time:15359437
. 00000090: dispatch_reason:decrementer interrupt, preempt_reason:H_CEDE, enqueue_to_dispatch_time:4868, ready_to_enqueue_time:232, waiting_to_ready_time:5100709
. 000000c0: dispatch_reason:priv doorbell, preempt_reason:H_CEDE, enqueue_to_dispatch_time:179, ready_to_enqueue_time:0, waiting_to_ready_time:30714243
. 000000f0: dispatch_reason:priv doorbell, preempt_reason:H_CEDE, enqueue_to_dispatch_time:197, ready_to_enqueue_time:0, waiting_to_ready_time:15350648
. 00000120: dispatch_reason:priv doorbell, preempt_reason:H_CEDE, enqueue_to_dispatch_time:213, ready_to_enqueue_time:0, waiting_to_ready_time:15353446
. 00000150: dispatch_reason:priv doorbell, preempt_reason:H_CEDE, enqueue_to_dispatch_time:212, ready_to_enqueue_time:0, waiting_to_ready_time:15355126
. 00000180: dispatch_reason:decrementer interrupt, preempt_reason:H_CEDE, enqueue_to_dispatch_time:6368, ready_to_enqueue_time:164, waiting_to_ready_time:5104665
struct dtl_entry
105-124Dump의 각 entry는 다음 원문 structure에 대응합니다.
struct dtl_entry {
u8 dispatch_reason;
u8 preempt_reason;
u16 processor_id;
u32 enqueue_to_dispatch_time;
u32 ready_to_enqueue_time;
u32 waiting_to_ready_time;
u64 timebase;
u64 fault_addr;
u64 srr0;
u64 srr1;
};
| Field | Type | 의미 |
|---|---|---|
| `dispatch_reason` | `u8` | Dispatch 이유 |
| `preempt_reason` | `u8` | Preempt 이유 |
| `processor_id` | `u16` | Processor identifier |
| `enqueue_to_dispatch_time` | `u32` | Enqueue에서 dispatch까지 시간 |
| `ready_to_enqueue_time` | `u32` | Ready에서 enqueue까지 시간 |
| `waiting_to_ready_time` | `u32` | Waiting에서 ready까지 시간 |
| `timebase` | `u64` | DTL timestamp |
| `fault_addr` | `u64` | Fault address |
| `srr0`, `srr1` | `u64` 각각 | Saved instruction/MSR state |
첫 두 field는 dispatch reason과 preempt reason입니다. `PERF_RECORD_AUXTRACE` post-processing이 raw value를 사용자가 읽을 수 있는 의미로 변환합니다.
Perf report와 script 시각화
125-156`perf report`는 vpa-dtl sample을 symbol별로 집계하고, `perf script`는 sched event와 vpa-dtl event를 timestamp 순서로 함께 출력합니다.
# ./perf record -a -e sched:*,vpa_dtl/dtl_all/ -c 1000000000 sleep 1
[ perf record: Woken up 1 times to write data ]
[ perf record: Captured and wrote 0.300 MB perf.data ]
# ./perf report
# Samples: 321 of event 'vpa-dtl'
# Event count (approx.): 321
#
# Children Self Command Shared Object Symbol
# ........ ........ ....... ................. ..............................
#
100.00% 100.00% swapper [kernel.kallsyms] [k] plpar_hcall_norets_notrace
# ./perf script
migration/9 67 [009] 105373.359903: sched:sched_waking: comm=perf pid=13418 prio=120 target_cpu=009
migration/9 67 [009] 105373.359904: sched:sched_migrate_task: comm=perf pid=13418 prio=120 orig_cpu=9 dest_cpu=10
migration/9 67 [009] 105373.359907: sched:sched_stat_runtime: comm=migration/9 pid=67 runtime=4050 [ns]
migration/9 67 [009] 105373.359908: sched:sched_switch: prev_comm=migration/9 prev_pid=67 prev_prio=0 prev_state=S ==> next_comm=swapper/9 next_pid=0 next_prio=120
:256 256 [016] 105373.359913: vpa-dtl: timebase: 21403600706628832 dispatch_reason:decrementer interrupt, preempt_reason:H_CEDE, enqueue_to_dispatch_time:4854, ready_to_enqueue_time:139, waiting_to_ready_time:511842115 c0000000000fcd28 plpar_hcall_norets_notrace+0x18 ([kernel.kallsyms])
:256 256 [017] 105373.360012: vpa-dtl: timebase: 21403600706679454 dispatch_reason:priv doorbell, preempt_reason:H_CEDE, enqueue_to_dispatch_time:236, ready_to_enqueue_time:0, waiting_to_ready_time:133864583 c0000000000fcd28 plpar_hcall_norets_notrace+0x18 ([kernel.kallsyms])
perf 13418 [010] 105373.360048: sched:sched_stat_runtime: comm=perf pid=13418 runtime=139748 [ns]
perf 13418 [010] 105373.360052: sched:sched_waking: comm=migration/10 pid=72 prio=0 target_cpu=010
같은 perf.data에서 summary와 timestamp timeline을 선택할 수 있습니다.
요약과 해설
vpa-dtl.rst:1-156Interrupt 없는 VPA DTL PMU는 hrtimer로 raw buffer를 AUX area에 복사합니다. Userspace는 CPU별 auxtrace queue를 timestamp heap으로 merge하여 dispatch/preempt latency와 sched event를 같은 timeline에서 분석합니다.