drm/bridge: adv7511: Switch to atomic operations
[drm/drm-misc.git] / tools / testing / selftests / turbostat / added_perf_counters.py
blob9ab4aaf45fb8fbbc48fe3b46bc5f178037d0996c
1 #!/bin/env python3
2 # SPDX-License-Identifier: GPL-2.0
4 import subprocess
5 from shutil import which
6 from os import pread
8 class PerfCounterInfo:
9 def __init__(self, subsys, event):
10 self.subsys = subsys
11 self.event = event
13 def get_perf_event_name(self):
14 return f'{self.subsys}/{self.event}/'
16 def get_turbostat_perf_id(self, counter_scope, counter_type, column_name):
17 return f'perf/{self.subsys}/{self.event},{counter_scope},{counter_type},{column_name}'
19 PERF_COUNTERS_CANDIDATES = [
20 PerfCounterInfo('msr', 'mperf'),
21 PerfCounterInfo('msr', 'aperf'),
22 PerfCounterInfo('msr', 'tsc'),
23 PerfCounterInfo('cstate_core', 'c1-residency'),
24 PerfCounterInfo('cstate_core', 'c6-residency'),
25 PerfCounterInfo('cstate_core', 'c7-residency'),
26 PerfCounterInfo('cstate_pkg', 'c2-residency'),
27 PerfCounterInfo('cstate_pkg', 'c3-residency'),
28 PerfCounterInfo('cstate_pkg', 'c6-residency'),
29 PerfCounterInfo('cstate_pkg', 'c7-residency'),
30 PerfCounterInfo('cstate_pkg', 'c8-residency'),
31 PerfCounterInfo('cstate_pkg', 'c9-residency'),
32 PerfCounterInfo('cstate_pkg', 'c10-residency'),
34 present_perf_counters = []
36 def check_perf_access():
37 perf = which('perf')
38 if perf is None:
39 print('SKIP: Could not find perf binary, thus could not determine perf access.')
40 return False
42 def has_perf_counter_access(counter_name):
43 proc_perf = subprocess.run([perf, 'stat', '-e', counter_name, '--timeout', '10'],
44 capture_output = True)
46 if proc_perf.returncode != 0:
47 print(f'SKIP: Could not read {counter_name} perf counter.')
48 return False
50 if b'<not supported>' in proc_perf.stderr:
51 print(f'SKIP: Could not read {counter_name} perf counter.')
52 return False
54 return True
56 for counter in PERF_COUNTERS_CANDIDATES:
57 if has_perf_counter_access(counter.get_perf_event_name()):
58 present_perf_counters.append(counter)
60 if len(present_perf_counters) == 0:
61 print('SKIP: Could not read any perf counter.')
62 return False
64 if len(present_perf_counters) != len(PERF_COUNTERS_CANDIDATES):
65 print(f'WARN: Could not access all of the counters - some will be left untested')
67 return True
69 if not check_perf_access():
70 exit(0)
72 turbostat_counter_source_opts = ['']
74 turbostat = which('turbostat')
75 if turbostat is None:
76 print('Could not find turbostat binary')
77 exit(1)
79 timeout = which('timeout')
80 if timeout is None:
81 print('Could not find timeout binary')
82 exit(1)
84 proc_turbostat = subprocess.run([turbostat, '--list'], capture_output = True)
85 if proc_turbostat.returncode != 0:
86 print(f'turbostat failed with {proc_turbostat.returncode}')
87 exit(1)
89 EXPECTED_COLUMNS_DEBUG_DEFAULT = [b'usec', b'Time_Of_Day_Seconds', b'APIC', b'X2APIC']
91 expected_columns = [b'CPU']
92 counters_argv = []
93 for counter in present_perf_counters:
94 if counter.subsys == 'cstate_core':
95 counter_scope = 'core'
96 elif counter.subsys == 'cstate_pkg':
97 counter_scope = 'package'
98 else:
99 counter_scope = 'cpu'
101 counter_type = 'delta'
102 column_name = counter.event
104 cparams = counter.get_turbostat_perf_id(
105 counter_scope = counter_scope,
106 counter_type = counter_type,
107 column_name = column_name
109 expected_columns.append(column_name.encode())
110 counters_argv.extend(['--add', cparams])
112 expected_columns_debug = EXPECTED_COLUMNS_DEBUG_DEFAULT + expected_columns
114 def gen_user_friendly_cmdline(argv_):
115 argv = argv_[:]
116 ret = ''
118 while len(argv) != 0:
119 arg = argv.pop(0)
120 arg_next = ''
122 if arg in ('-i', '--show', '--add'):
123 arg_next = argv.pop(0) if len(argv) > 0 else ''
125 ret += f'{arg} {arg_next} \\\n\t'
127 # Remove the last separator and return
128 return ret[:-4]
131 # Run turbostat for some time and send SIGINT
133 timeout_argv = [timeout, '--preserve-status', '-s', 'SIGINT', '-k', '3', '0.2s']
134 turbostat_argv = [turbostat, '-i', '0.50', '--show', 'CPU'] + counters_argv
136 def check_columns_or_fail(expected_columns: list, actual_columns: list):
137 if len(actual_columns) != len(expected_columns):
138 print(f'turbostat column check failed\n{expected_columns=}\n{actual_columns=}')
139 exit(1)
141 failed = False
142 for expected_column in expected_columns:
143 if expected_column not in actual_columns:
144 print(f'turbostat column check failed: missing column {expected_column.decode()}')
145 failed = True
147 if failed:
148 exit(1)
150 cmdline = gen_user_friendly_cmdline(turbostat_argv)
151 print(f'Running turbostat with:\n\t{cmdline}\n... ', end = '', flush = True)
152 proc_turbostat = subprocess.run(timeout_argv + turbostat_argv, capture_output = True)
153 if proc_turbostat.returncode != 0:
154 print(f'turbostat failed with {proc_turbostat.returncode}')
155 exit(1)
157 actual_columns = proc_turbostat.stdout.split(b'\n')[0].split(b'\t')
158 check_columns_or_fail(expected_columns, actual_columns)
159 print('OK')
162 # Same, but with --debug
164 # We explicitly specify '--show CPU' to make sure turbostat
165 # don't show a bunch of default counters instead.
167 turbostat_argv.append('--debug')
169 cmdline = gen_user_friendly_cmdline(turbostat_argv)
170 print(f'Running turbostat (in debug mode) with:\n\t{cmdline}\n... ', end = '', flush = True)
171 proc_turbostat = subprocess.run(timeout_argv + turbostat_argv, capture_output = True)
172 if proc_turbostat.returncode != 0:
173 print(f'turbostat failed with {proc_turbostat.returncode}')
174 exit(1)
176 actual_columns = proc_turbostat.stdout.split(b'\n')[0].split(b'\t')
177 check_columns_or_fail(expected_columns_debug, actual_columns)
178 print('OK')