diff options
Diffstat (limited to 'tools/perf/pmu-events/jevents.py')
-rwxr-xr-x | tools/perf/pmu-events/jevents.py | 128 |
1 files changed, 90 insertions, 38 deletions
diff --git a/tools/perf/pmu-events/jevents.py b/tools/perf/pmu-events/jevents.py index 53ab050c8fa4..3e204700b59a 100755 --- a/tools/perf/pmu-events/jevents.py +++ b/tools/perf/pmu-events/jevents.py @@ -203,7 +203,7 @@ class JsonEvent: def llx(x: int) -> str: """Convert an int to a string similar to a printf modifier of %#llx.""" - return '0' if x == 0 else hex(x) + return str(x) if x >= 0 and x < 10 else hex(x) def fixdesc(s: str) -> str: """Fix formatting issue for the desc string.""" @@ -284,6 +284,7 @@ class JsonEvent: 'hisi_sccl,hha': 'hisi_sccl,hha', 'hisi_sccl,l3c': 'hisi_sccl,l3c', 'imx8_ddr': 'imx8_ddr', + 'imx9_ddr': 'imx9_ddr', 'L3PMC': 'amd_l3', 'DFPMC': 'amd_df', 'UMCPMC': 'amd_umc', @@ -291,9 +292,27 @@ class JsonEvent: 'cpu_atom': 'cpu_atom', 'ali_drw': 'ali_drw', 'arm_cmn': 'arm_cmn', + 'tool': 'tool', } return table[unit] if unit in table else f'uncore_{unit.lower()}' + def is_zero(val: str) -> bool: + try: + if val.startswith('0x'): + return int(val, 16) == 0 + else: + return int(val) == 0 + except e: + return False + + def canonicalize_value(val: str) -> str: + try: + if val.startswith('0x'): + return llx(int(val, 16)) + return str(int(val)) + except e: + return val + eventcode = 0 if 'EventCode' in jd: eventcode = int(jd['EventCode'].split(',', 1)[0], 0) @@ -356,10 +375,14 @@ class JsonEvent: ('UMask', 'umask='), ('NodeType', 'type='), ('RdWrMask', 'rdwrmask='), + ('EnAllCores', 'enallcores='), + ('EnAllSlices', 'enallslices='), + ('SliceId', 'sliceid='), + ('ThreadMask', 'threadmask='), ] for key, value in event_fields: - if key in jd and jd[key] != '0': - event += ',' + value + jd[key] + if key in jd and not is_zero(jd[key]): + event += f',{value}{canonicalize_value(jd[key])}' if filter: event += f',{filter}' if msr: @@ -407,8 +430,11 @@ class JsonEvent: def to_c_string(self, metric: bool) -> str: """Representation of the event as a C struct initializer.""" + def fix_comment(s: str) -> str: + return s.replace('*/', r'\*\/') + s = self.build_c_string(metric) - return f'{{ { _bcs.offsets[s] } }}, /* {s} */\n' + return f'{{ { _bcs.offsets[s] } }}, /* {fix_comment(s)} */\n' @lru_cache(maxsize=None) @@ -438,12 +464,16 @@ def preprocess_arch_std_files(archpath: str) -> None: """Read in all architecture standard events.""" global _arch_std_events for item in os.scandir(archpath): - if item.is_file() and item.name.endswith('.json'): + if not item.is_file() or not item.name.endswith('.json'): + continue + try: for event in read_json_events(item.path, topic=''): if event.name: _arch_std_events[event.name.lower()] = event if event.metric_name: _arch_std_events[event.metric_name.lower()] = event + except Exception as e: + raise RuntimeError(f'Failure processing \'{item.name}\' in \'{archpath}\'') from e def add_events_table_entries(item: os.DirEntry, topic: str) -> None: @@ -481,8 +511,11 @@ def print_pending_events() -> None: first = True last_pmu = None + last_name = None pmus = set() for event in sorted(_pending_events, key=event_cmp_key): + if last_pmu and last_pmu == event.pmu: + assert event.name != last_name, f"Duplicate event: {last_pmu}/{last_name}/ in {_pending_events_tblname}" if event.pmu != last_pmu: if not first: _args.output_file.write('};\n') @@ -494,6 +527,7 @@ def print_pending_events() -> None: pmus.add((event.pmu, pmu_name)) _args.output_file.write(event.to_c_string(metric=False)) + last_name = event.name _pending_events = [] _args.output_file.write(f""" @@ -609,14 +643,17 @@ def preprocess_one_file(parents: Sequence[str], item: os.DirEntry) -> None: def process_one_file(parents: Sequence[str], item: os.DirEntry) -> None: """Process a JSON file during the main walk.""" - def is_leaf_dir(path: str) -> bool: + def is_leaf_dir_ignoring_sys(path: str) -> bool: for item in os.scandir(path): - if item.is_dir(): + if item.is_dir() and item.name != 'sys': return False return True - # model directory, reset topic - if item.is_dir() and is_leaf_dir(item.path): + # Model directories are leaves (ignoring possible sys + # directories). The FTW will walk into the directory next. Flush + # pending events and metrics and update the table names for the new + # model directory. + if item.is_dir() and is_leaf_dir_ignoring_sys(item.path): print_pending_events() print_pending_metrics() @@ -693,6 +730,17 @@ const struct pmu_events_map pmu_events_map[] = { \t} }, """) + elif arch == 'common': + _args.output_file.write("""{ +\t.arch = "common", +\t.cpuid = "common", +\t.event_table = { +\t\t.pmus = pmu_events__common, +\t\t.num_pmus = ARRAY_SIZE(pmu_events__common), +\t}, +\t.metric_table = {}, +}, +""") else: with open(f'{_args.starting_dir}/{arch}/mapfile.csv') as csvfile: table = csv.reader(csvfile) @@ -884,7 +932,7 @@ static int pmu_events_table__find_event_pmu(const struct pmu_events_table *table do_call: return fn ? fn(&pe, table, data) : 0; } - return -1000; + return PMU_EVENTS__NOT_FOUND; } int pmu_events_table__for_each_event(const struct pmu_events_table *table, @@ -901,7 +949,7 @@ int pmu_events_table__for_each_event(const struct pmu_events_table *table, continue; ret = pmu_events_table__for_each_event_pmu(table, table_pmu, fn, data); - if (pmu || ret) + if (ret) return ret; } return 0; @@ -922,10 +970,10 @@ int pmu_events_table__find_event(const struct pmu_events_table *table, continue; ret = pmu_events_table__find_event_pmu(table, table_pmu, name, fn, data); - if (ret != -1000) + if (ret != PMU_EVENTS__NOT_FOUND) return ret; } - return -1000; + return PMU_EVENTS__NOT_FOUND; } size_t pmu_events_table__num_events(const struct pmu_events_table *table, @@ -978,11 +1026,11 @@ int pmu_metrics_table__for_each_metric(const struct pmu_metrics_table *table, return 0; } -static const struct pmu_events_map *map_for_pmu(struct perf_pmu *pmu) +static const struct pmu_events_map *map_for_cpu(struct perf_cpu cpu) { static struct { const struct pmu_events_map *map; - struct perf_pmu *pmu; + struct perf_cpu cpu; } last_result; static struct { const struct pmu_events_map *map; @@ -993,10 +1041,10 @@ static const struct pmu_events_map *map_for_pmu(struct perf_pmu *pmu) char *cpuid = NULL; size_t i; - if (has_last_result && last_result.pmu == pmu) + if (has_last_result && last_result.cpu.cpu == cpu.cpu) return last_result.map; - cpuid = perf_pmu__getcpuid(pmu); + cpuid = get_cpuid_allow_env_override(cpu); /* * On some platforms which uses cpus map, cpuid can be NULL for @@ -1027,12 +1075,21 @@ static const struct pmu_events_map *map_for_pmu(struct perf_pmu *pmu) has_last_map_search = true; } out_update_last_result: - last_result.pmu = pmu; + last_result.cpu = cpu; last_result.map = map; has_last_result = true; return map; } +static const struct pmu_events_map *map_for_pmu(struct perf_pmu *pmu) +{ + struct perf_cpu cpu = {-1}; + + if (pmu) + cpu = perf_cpu_map__min(pmu->cpus); + return map_for_cpu(cpu); +} + const struct pmu_events_table *perf_pmu__find_events_table(struct perf_pmu *pmu) { const struct pmu_events_map *map = map_for_pmu(pmu); @@ -1053,24 +1110,12 @@ const struct pmu_events_table *perf_pmu__find_events_table(struct perf_pmu *pmu) return NULL; } -const struct pmu_metrics_table *perf_pmu__find_metrics_table(struct perf_pmu *pmu) +const struct pmu_metrics_table *pmu_metrics_table__find(void) { - const struct pmu_events_map *map = map_for_pmu(pmu); - - if (!map) - return NULL; - - if (!pmu) - return &map->metric_table; + struct perf_cpu cpu = {-1}; + const struct pmu_events_map *map = map_for_cpu(cpu); - for (size_t i = 0; i < map->metric_table.num_pmus; i++) { - const struct pmu_table_entry *table_pmu = &map->metric_table.pmus[i]; - const char *pmu_name = &big_c_string[table_pmu->pmu_name.offset]; - - if (pmu__name_match(pmu, pmu_name)) - return &map->metric_table; - } - return NULL; + return map ? &map->metric_table : NULL; } const struct pmu_events_table *find_core_events_table(const char *arch, const char *cpuid) @@ -1212,9 +1257,12 @@ def main() -> None: if len(parents) == _args.model.split(',')[0].count('/'): # We're testing the correct directory. item_path = '/'.join(parents) + ('/' if len(parents) > 0 else '') + item.name - if 'test' not in item_path and item_path not in _args.model.split(','): + if 'test' not in item_path and 'common' not in item_path and item_path not in _args.model.split(','): continue - action(parents, item) + try: + action(parents, item) + except Exception as e: + raise RuntimeError(f'Action failure for \'{item.name}\' in {parents}') from e if item.is_dir(): ftw(item.path, parents + [item.name], action) @@ -1234,6 +1282,10 @@ such as "arm/cortex-a34".''', 'output_file', type=argparse.FileType('w', encoding='utf-8'), nargs='?', default=sys.stdout) _args = ap.parse_args() + _args.output_file.write(f""" +/* SPDX-License-Identifier: GPL-2.0 */ +/* THIS FILE WAS AUTOGENERATED BY jevents.py arch={_args.arch} model={_args.model} ! */ +""") _args.output_file.write(""" #include <pmu-events/pmu-events.h> #include "util/header.h" @@ -1256,10 +1308,10 @@ struct pmu_table_entry { for item in os.scandir(_args.starting_dir): if not item.is_dir(): continue - if item.name == _args.arch or _args.arch == 'all' or item.name == 'test': + if item.name == _args.arch or _args.arch == 'all' or item.name == 'test' or item.name == 'common': archs.append(item.name) - if len(archs) < 2: + if len(archs) < 2 and _args.arch != 'none': raise IOError(f'Missing architecture directory \'{_args.arch}\'') archs.sort() |