← Documents Documentation/arch/arm64/perf.rst GitHub 원문 ↗

Linux 6.18.37 · Architecture

Perf on AArch64

Arm64 Perf의 exception-level filtering, 사용자 공간 PMU register 접근, counter 폭과 PMUv3 threshold 기능을 설명합니다.

Source pathDocumentation/arch/arm64/perf.rst
Source versionLinux v6.18.37
TranslationDUJINLABS 전문 번역 + 해설

요약·해설과 원문, 전문 번역을 서로 분리했습니다. API 이름, symbol, source path는 원문 표기를 사용합니다.

1. 요약·해설

원문의 핵심 논리와 kernel programming 관점의 보충 설명입니다. 아래의 전문 번역과는 별도로 작성했습니다.

요약과 해설

perf.rst:1-238

Arm64 Perf는 EL0/EL1/EL2와 VHE 여부를 함께 고려해 host, guest, kernel, hypervisor event를 구분합니다. 또한 sequence lock으로 유효성을 보호하면서 자기 monitor task가 PMU counter를 직접 읽게 하고, PMUv3 threshold로 한 cycle의 event 수가 조건을 만족할 때만 counting할 수 있습니다.

사용자 공간 counter 접근
`perf_event_open(config1:1)``mmap()` user pageCounter index 확인`mrs`로 읽기Sequence lock 재검증

Kernel이 공개한 user page와 sequence lock을 통해 직접 register read를 검증합니다.

Exception-level filtering
AttributeHostGuest
`exclude_user`EL0EL0
`exclude_kernel`EL1 + VHE의 EL2EL1
`exclude_hv`Non-VHE EL2; VHE에서는 무시효과 없음
`exclude_host/guest`Guest 경계에서 동적 전환EL2 counting 없음

Attribute가 제외하는 실행 영역을 VHE 여부와 guest 관점으로 정리합니다.

2. 영어 원문 전체

번역 기준이 된 Linux v6.18.37 원문입니다. 줄 번호는 이 버전의 파일 좌표입니다.

원문 전체 펼치기
1 .. SPDX-License-Identifier: GPL-2.0
2
3 .. _perf_index:
4
5 ====
6 Perf
7 ====
8
9 Perf Event Attributes
10 =====================
11
12 :Author: Andrew Murray <[email protected]>
13 :Date: 2019-03-06
14
15 exclude_user
16 ------------
17
18 This attribute excludes userspace.
19
20 Userspace always runs at EL0 and thus this attribute will exclude EL0.
21
22
23 exclude_kernel
24 --------------
25
26 This attribute excludes the kernel.
27
28 The kernel runs at EL2 with VHE and EL1 without. Guest kernels always run
29 at EL1.
30
31 For the host this attribute will exclude EL1 and additionally EL2 on a VHE
32 system.
33
34 For the guest this attribute will exclude EL1. Please note that EL2 is
35 never counted within a guest.
36
37
38 exclude_hv
39 ----------
40
41 This attribute excludes the hypervisor.
42
43 For a VHE host this attribute is ignored as we consider the host kernel to
44 be the hypervisor.
45
46 For a non-VHE host this attribute will exclude EL2 as we consider the
47 hypervisor to be any code that runs at EL2 which is predominantly used for
48 guest/host transitions.
49
50 For the guest this attribute has no effect. Please note that EL2 is
51 never counted within a guest.
52
53
54 exclude_host / exclude_guest
55 ----------------------------
56
57 These attributes exclude the KVM host and guest, respectively.
58
59 The KVM host may run at EL0 (userspace), EL1 (non-VHE kernel) and EL2 (VHE
60 kernel or non-VHE hypervisor).
61
62 The KVM guest may run at EL0 (userspace) and EL1 (kernel).
63
64 Due to the overlapping exception levels between host and guests we cannot
65 exclusively rely on the PMU's hardware exception filtering - therefore we
66 must enable/disable counting on the entry and exit to the guest. This is
67 performed differently on VHE and non-VHE systems.
68
69 For non-VHE systems we exclude EL2 for exclude_host - upon entering and
70 exiting the guest we disable/enable the event as appropriate based on the
71 exclude_host and exclude_guest attributes.
72
73 For VHE systems we exclude EL1 for exclude_guest and exclude both EL0,EL2
74 for exclude_host. Upon entering and exiting the guest we modify the event
75 to include/exclude EL0 as appropriate based on the exclude_host and
76 exclude_guest attributes.
77
78 The statements above also apply when these attributes are used within a
79 non-VHE guest however please note that EL2 is never counted within a guest.
80
81
82 Accuracy
83 --------
84
85 On non-VHE hosts we enable/disable counters on the entry/exit of host/guest
86 transition at EL2 - however there is a period of time between
87 enabling/disabling the counters and entering/exiting the guest. We are
88 able to eliminate counters counting host events on the boundaries of guest
89 entry/exit when counting guest events by filtering out EL2 for
90 exclude_host. However when using !exclude_hv there is a small blackout
91 window at the guest entry/exit where host events are not captured.
92
93 On VHE systems there are no blackout windows.
94
95 Perf Userspace PMU Hardware Counter Access
96 ==========================================
97
98 Overview
99 --------
100 The perf userspace tool relies on the PMU to monitor events. It offers an
101 abstraction layer over the hardware counters since the underlying
102 implementation is cpu-dependent.
103 Arm64 allows userspace tools to have access to the registers storing the
104 hardware counters' values directly.
105
106 This targets specifically self-monitoring tasks in order to reduce the overhead
107 by directly accessing the registers without having to go through the kernel.
108
109 How-to
110 ------
111 The focus is set on the armv8 PMUv3 which makes sure that the access to the pmu
112 registers is enabled and that the userspace has access to the relevant
113 information in order to use them.
114
115 In order to have access to the hardware counters, the global sysctl
116 kernel/perf_user_access must first be enabled:
117
118 .. code-block:: sh
119
120 echo 1 > /proc/sys/kernel/perf_user_access
121
122 It is necessary to open the event using the perf tool interface with config1:1
123 attr bit set: the sys_perf_event_open syscall returns a fd which can
124 subsequently be used with the mmap syscall in order to retrieve a page of memory
125 containing information about the event. The PMU driver uses this page to expose
126 to the user the hardware counter's index and other necessary data. Using this
127 index enables the user to access the PMU registers using the `mrs` instruction.
128 Access to the PMU registers is only valid while the sequence lock is unchanged.
129 In particular, the PMSELR_EL0 register is zeroed each time the sequence lock is
130 changed.
131
132 The userspace access is supported in libperf using the perf_evsel__mmap()
133 and perf_evsel__read() functions. See `tools/lib/perf/tests/test-evsel.c`_ for
134 an example.
135
136 About heterogeneous systems
137 ---------------------------
138 On heterogeneous systems such as big.LITTLE, userspace PMU counter access can
139 only be enabled when the tasks are pinned to a homogeneous subset of cores and
140 the corresponding PMU instance is opened by specifying the 'type' attribute.
141 The use of generic event types is not supported in this case.
142
143 Have a look at `tools/perf/arch/arm64/tests/user-events.c`_ for an example. It
144 can be run using the perf tool to check that the access to the registers works
145 correctly from userspace:
146
147 .. code-block:: sh
148
149 perf test -v user
150
151 About chained events and counter sizes
152 --------------------------------------
153 The user can request either a 32-bit (config1:0 == 0) or 64-bit (config1:0 == 1)
154 counter along with userspace access. The sys_perf_event_open syscall will fail
155 if a 64-bit counter is requested and the hardware doesn't support 64-bit
156 counters. Chained events are not supported in conjunction with userspace counter
157 access. If a 32-bit counter is requested on hardware with 64-bit counters, then
158 userspace must treat the upper 32-bits read from the counter as UNKNOWN. The
159 'pmc_width' field in the user page will indicate the valid width of the counter
160 and should be used to mask the upper bits as needed.
161
162 .. Links
163 .. _tools/perf/arch/arm64/tests/user-events.c:
164 https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/tools/perf/arch/arm64/tests/user-events.c
165 .. _tools/lib/perf/tests/test-evsel.c:
166 https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/tools/lib/perf/tests/test-evsel.c
167
168 Event Counting Threshold
169 ==========================================
170
171 Overview
172 --------
173
174 FEAT_PMUv3_TH (Armv8.8) permits a PMU counter to increment only on
175 events whose count meets a specified threshold condition. For example if
176 threshold_compare is set to 2 ('Greater than or equal'), and the
177 threshold is set to 2, then the PMU counter will now only increment by
178 when an event would have previously incremented the PMU counter by 2 or
179 more on a single processor cycle.
180
181 To increment by 1 after passing the threshold condition instead of the
182 number of events on that cycle, add the 'threshold_count' option to the
183 commandline.
184
185 How-to
186 ------
187
188 These are the parameters for controlling the feature:
189
190 .. list-table::
191 :header-rows: 1
192
193 * - Parameter
194 - Description
195 * - threshold
196 - Value to threshold the event by. A value of 0 means that
197 thresholding is disabled and the other parameters have no effect.
198 * - threshold_compare
199 - | Comparison function to use, with the following values supported:
200 |
201 | 0: Not-equal
202 | 1: Equals
203 | 2: Greater-than-or-equal
204 | 3: Less-than
205 * - threshold_count
206 - If this is set, count by 1 after passing the threshold condition
207 instead of the value of the event on this cycle.
208
209 The threshold, threshold_compare and threshold_count values can be
210 provided per event, for example:
211
212 .. code-block:: sh
213
214 perf stat -e stall_slot/threshold=2,threshold_compare=2/ \
215 -e dtlb_walk/threshold=10,threshold_compare=3,threshold_count/
216
217 In this example the stall_slot event will count by 2 or more on every
218 cycle where 2 or more stalls happen. And dtlb_walk will count by 1 on
219 every cycle where the number of dtlb walks were less than 10.
220
221 The maximum supported threshold value can be read from the caps of each
222 PMU, for example:
223
224 .. code-block:: sh
225
226 cat /sys/bus/event_source/devices/armv8_pmuv3/caps/threshold_max
227
228 0x000000ff
229
230 If a value higher than this is given, then opening the event will result
231 in an error. The highest possible maximum is 4095, as the config field
232 for threshold is limited to 12 bits, and the Perf tool will refuse to
233 parse higher values.
234
235 If the PMU doesn't support FEAT_PMUv3_TH, then threshold_max will read
236 0, and attempting to set a threshold value will also result in an error.
237 threshold_max will also read as 0 on aarch32 guests, even if the host
238 is running on hardware with the feature.
239

3. 한국어 전문 번역

영어 원문의 문단 순서와 의미를 유지한 전체 번역입니다. 코드, 함수명, symbol과 URL은 원문 표기를 유지합니다.

Perf event attribute 개요

1-14

Sphinx anchor는 `_perf_index`입니다. 이 절은 Andrew Murray가 2019-03-06에 작성한 Arm64 Perf event attribute 설명입니다.

exclude_user

15-22

`exclude_user`는 사용자 공간을 제외합니다. 사용자 공간은 항상 EL0에서 실행되므로 이 attribute는 EL0 event를 counting하지 않습니다.

exclude_kernel

23-37

`exclude_kernel`은 kernel을 제외합니다. Host kernel은 VHE가 있으면 EL2, 없으면 EL1에서 실행되고 guest kernel은 항상 EL1에서 실행됩니다.

Host에서는 EL1을 제외하며 VHE system에서는 EL2도 함께 제외합니다. Guest에서는 EL1을 제외합니다. Guest 안에서는 EL2를 절대 counting하지 않는다는 점에 유의해야 합니다.

exclude_hv

38-53

`exclude_hv`는 hypervisor를 제외합니다. VHE host에서는 host kernel 자체를 hypervisor로 간주하므로 이 attribute를 무시합니다. Non-VHE host에서는 guest/host 전환에 주로 쓰이는 EL2 실행을 hypervisor로 간주하여 EL2를 제외합니다.

Guest에서는 효과가 없으며, guest 내부에서는 애초에 EL2가 counting되지 않습니다.

exclude_host와 exclude_guest

54-81

`exclude_host`와 `exclude_guest`는 각각 KVM host와 guest를 제외합니다. KVM host는 EL0(userspace), EL1(non-VHE kernel), EL2(VHE kernel 또는 non-VHE hypervisor)에서 실행될 수 있고 KVM guest는 EL0(userspace)과 EL1(kernel)에서 실행됩니다.

Host와 guest의 exception level이 겹치므로 PMU의 hardware exception filtering만으로 완전히 구분할 수 없습니다. 따라서 guest에 들어가고 나올 때 counting을 켜거나 꺼야 하며 VHE 여부에 따라 방식이 다릅니다.

환경`exclude_host` 처리`exclude_guest` 처리와 전환
Non-VHEEL2를 제외Guest 진입과 종료 시 두 attribute에 맞춰 event를 disable/enable
VHEEL0와 EL2를 제외EL1을 제외하고 guest 진입과 종료 시 EL0 포함 여부를 변경

위 규칙은 non-VHE guest 내부에서 이 attribute들을 사용할 때도 적용되지만, guest에서 EL2는 어떤 경우에도 counting되지 않습니다.

측정 정확도

82-94

Non-VHE host는 EL2에서 host/guest 전환에 들어가고 나올 때 counter를 enable/disable합니다. Counter 상태를 바꾸는 시점과 실제 guest 경계를 통과하는 시점 사이에는 짧은 간격이 있습니다.

Guest event를 잴 때 `exclude_host`로 EL2를 filtering하면 guest 경계의 host event가 섞이는 것은 막을 수 있습니다. 그러나 `!exclude_hv`를 사용하면 guest 진입과 종료 때 host event를 잡지 못하는 작은 blackout window가 생깁니다. VHE system에는 blackout window가 없습니다.

사용자 공간 PMU 접근 개요

95-108

Perf 사용자 도구는 PMU로 event를 monitor하며 CPU마다 다른 hardware counter 구현 위에 abstraction layer를 제공합니다. Arm64에서는 사용자 도구가 hardware counter 값을 저장한 register에 직접 접근할 수 있습니다.

이 기능은 자기 자신을 monitor하는 task가 kernel을 거치지 않고 register를 읽어 overhead를 줄이는 용도에 맞춰져 있습니다.

사용자 공간 PMU 접근 방법

109-135

Armv8 PMUv3를 대상으로 PMU register 접근을 허용하고 사용자 공간에 필요한 정보를 제공합니다. 먼저 global sysctl `kernel/perf_user_access`를 켭니다.

echo 1 > /proc/sys/kernel/perf_user_access

Perf interface에서 `config1:1` attr bit를 설정해 event를 열어야 합니다. `sys_perf_event_open`은 file descriptor를 반환하고, 이 fd를 `mmap()`에 넘기면 event 정보 page를 얻습니다. PMU driver는 이 page에 hardware counter index와 필요한 data를 공개합니다. 사용자는 index를 이용해 `mrs` 명령으로 PMU register를 읽습니다.

PMU register 접근은 sequence lock이 바뀌지 않은 동안에만 유효합니다. 특히 sequence lock이 바뀔 때마다 `PMSELR_EL0` register가 0으로 초기화됩니다.

Libperf는 `perf_evsel__mmap()`과 `perf_evsel__read()`으로 이 접근을 지원합니다. 예제는 `tools/lib/perf/tests/test-evsel.c`에 있습니다.

이기종 system

136-150

big.LITTLE 같은 heterogeneous system에서는 task를 homogeneous core subset에 고정하고 해당 PMU instance의 `type` attribute를 지정해 열었을 때만 사용자 공간 PMU counter 접근을 켤 수 있습니다. 이 경우 generic event type은 지원하지 않습니다.

예제는 `tools/perf/arch/arm64/tests/user-events.c`에 있으며 다음 Perf test로 사용자 공간 register 접근을 확인할 수 있습니다.

perf test -v user

Chained event와 counter 폭

151-167

사용자는 사용자 공간 접근과 함께 32비트(`config1:0 == 0`) 또는 64비트(`config1:0 == 1`) counter를 요청할 수 있습니다. Hardware가 64비트 counter를 지원하지 않는데 64비트를 요청하면 `sys_perf_event_open`이 실패합니다.

사용자 공간 counter 접근과 chained event는 함께 사용할 수 없습니다. 64비트 counter hardware에서 32비트를 요청하면 사용자는 읽은 값의 상위 32비트를 `UNKNOWN`으로 취급해야 합니다. User page의 `pmc_width`가 유효 폭을 알려 주므로 필요하면 이 값으로 상위 bit를 mask해야 합니다.

Event counting threshold 개요

168-184

`FEAT_PMUv3_TH`(Armv8.8)는 한 processor cycle에서 발생한 event 수가 지정한 threshold 조건을 만족할 때만 PMU counter를 증가시킵니다. 예를 들어 `threshold_compare=2`(greater than or equal), `threshold=2`이면 한 cycle에 원래 2 이상 증가할 event에서만 counter가 증가합니다.

조건을 통과했을 때 해당 cycle의 event 수만큼 올리지 않고 1만 올리려면 command line에 `threshold_count` option을 추가합니다.

Threshold 설정 방법

185-238

기능을 제어하는 parameter는 다음과 같습니다.

Parameter설명
`threshold`Event에 적용할 threshold 값. 0이면 thresholding이 꺼지고 다른 parameter도 효과가 없습니다.
`threshold_compare`조건을 판정할 comparison function 값
`threshold_count`설정하면 조건 통과 후 그 cycle의 event 값 대신 1을 counting
`threshold_compare`비교
`0`Not-equal
`1`Equals
`2`Greater-than-or-equal
`3`Less-than

`threshold`, `threshold_compare`, `threshold_count`는 event마다 지정할 수 있습니다.

perf stat -e stall_slot/threshold=2,threshold_compare=2/ \
          -e dtlb_walk/threshold=10,threshold_compare=3,threshold_count/

이 예에서 `stall_slot`은 한 cycle에 stall이 2개 이상일 때 2 이상을 counting합니다. `dtlb_walk`는 한 cycle의 DTLB walk 수가 10보다 작을 때 1을 counting합니다.

PMU별 최대 threshold는 `caps/threshold_max`에서 읽습니다.

cat /sys/bus/event_source/devices/armv8_pmuv3/caps/threshold_max

0x000000ff

최대값보다 큰 값을 주면 event open이 실패합니다. Threshold config field가 12비트이므로 가능한 절대 최대는 4095이며 Perf 도구도 그보다 큰 값을 parse하지 않습니다.

PMU가 `FEAT_PMUv3_TH`를 지원하지 않으면 `threshold_max`는 0이고 threshold 설정도 실패합니다. Host hardware가 기능을 지원해도 `aarch32` guest에서는 `threshold_max`가 0입니다.