162306a36Sopenharmony_ci# mem-phys-addr.py: Resolve physical address samples
262306a36Sopenharmony_ci# SPDX-License-Identifier: GPL-2.0
362306a36Sopenharmony_ci#
462306a36Sopenharmony_ci# Copyright (c) 2018, Intel Corporation.
562306a36Sopenharmony_ci
662306a36Sopenharmony_cifrom __future__ import division
762306a36Sopenharmony_cifrom __future__ import print_function
862306a36Sopenharmony_ci
962306a36Sopenharmony_ciimport os
1062306a36Sopenharmony_ciimport sys
1162306a36Sopenharmony_ciimport struct
1262306a36Sopenharmony_ciimport re
1362306a36Sopenharmony_ciimport bisect
1462306a36Sopenharmony_ciimport collections
1562306a36Sopenharmony_ci
1662306a36Sopenharmony_cisys.path.append(os.environ['PERF_EXEC_PATH'] + \
1762306a36Sopenharmony_ci	'/scripts/python/Perf-Trace-Util/lib/Perf/Trace')
1862306a36Sopenharmony_ci
1962306a36Sopenharmony_ci#physical address ranges for System RAM
2062306a36Sopenharmony_cisystem_ram = []
2162306a36Sopenharmony_ci#physical address ranges for Persistent Memory
2262306a36Sopenharmony_cipmem = []
2362306a36Sopenharmony_ci#file object for proc iomem
2462306a36Sopenharmony_cif = None
2562306a36Sopenharmony_ci#Count for each type of memory
2662306a36Sopenharmony_ciload_mem_type_cnt = collections.Counter()
2762306a36Sopenharmony_ci#perf event name
2862306a36Sopenharmony_cievent_name = None
2962306a36Sopenharmony_ci
3062306a36Sopenharmony_cidef parse_iomem():
3162306a36Sopenharmony_ci	global f
3262306a36Sopenharmony_ci	f = open('/proc/iomem', 'r')
3362306a36Sopenharmony_ci	for i, j in enumerate(f):
3462306a36Sopenharmony_ci		m = re.split('-|:',j,2)
3562306a36Sopenharmony_ci		if m[2].strip() == 'System RAM':
3662306a36Sopenharmony_ci			system_ram.append(int(m[0], 16))
3762306a36Sopenharmony_ci			system_ram.append(int(m[1], 16))
3862306a36Sopenharmony_ci		if m[2].strip() == 'Persistent Memory':
3962306a36Sopenharmony_ci			pmem.append(int(m[0], 16))
4062306a36Sopenharmony_ci			pmem.append(int(m[1], 16))
4162306a36Sopenharmony_ci
4262306a36Sopenharmony_cidef print_memory_type():
4362306a36Sopenharmony_ci	print("Event: %s" % (event_name))
4462306a36Sopenharmony_ci	print("%-40s  %10s  %10s\n" % ("Memory type", "count", "percentage"), end='')
4562306a36Sopenharmony_ci	print("%-40s  %10s  %10s\n" % ("----------------------------------------",
4662306a36Sopenharmony_ci					"-----------", "-----------"),
4762306a36Sopenharmony_ci					end='');
4862306a36Sopenharmony_ci	total = sum(load_mem_type_cnt.values())
4962306a36Sopenharmony_ci	for mem_type, count in sorted(load_mem_type_cnt.most_common(), \
5062306a36Sopenharmony_ci					key = lambda kv: (kv[1], kv[0]), reverse = True):
5162306a36Sopenharmony_ci		print("%-40s  %10d  %10.1f%%\n" %
5262306a36Sopenharmony_ci			(mem_type, count, 100 * count / total),
5362306a36Sopenharmony_ci			end='')
5462306a36Sopenharmony_ci
5562306a36Sopenharmony_cidef trace_begin():
5662306a36Sopenharmony_ci	parse_iomem()
5762306a36Sopenharmony_ci
5862306a36Sopenharmony_cidef trace_end():
5962306a36Sopenharmony_ci	print_memory_type()
6062306a36Sopenharmony_ci	f.close()
6162306a36Sopenharmony_ci
6262306a36Sopenharmony_cidef is_system_ram(phys_addr):
6362306a36Sopenharmony_ci	#/proc/iomem is sorted
6462306a36Sopenharmony_ci	position = bisect.bisect(system_ram, phys_addr)
6562306a36Sopenharmony_ci	if position % 2 == 0:
6662306a36Sopenharmony_ci		return False
6762306a36Sopenharmony_ci	return True
6862306a36Sopenharmony_ci
6962306a36Sopenharmony_cidef is_persistent_mem(phys_addr):
7062306a36Sopenharmony_ci	position = bisect.bisect(pmem, phys_addr)
7162306a36Sopenharmony_ci	if position % 2 == 0:
7262306a36Sopenharmony_ci		return False
7362306a36Sopenharmony_ci	return True
7462306a36Sopenharmony_ci
7562306a36Sopenharmony_cidef find_memory_type(phys_addr):
7662306a36Sopenharmony_ci	if phys_addr == 0:
7762306a36Sopenharmony_ci		return "N/A"
7862306a36Sopenharmony_ci	if is_system_ram(phys_addr):
7962306a36Sopenharmony_ci		return "System RAM"
8062306a36Sopenharmony_ci
8162306a36Sopenharmony_ci	if is_persistent_mem(phys_addr):
8262306a36Sopenharmony_ci		return "Persistent Memory"
8362306a36Sopenharmony_ci
8462306a36Sopenharmony_ci	#slow path, search all
8562306a36Sopenharmony_ci	f.seek(0, 0)
8662306a36Sopenharmony_ci	for j in f:
8762306a36Sopenharmony_ci		m = re.split('-|:',j,2)
8862306a36Sopenharmony_ci		if int(m[0], 16) <= phys_addr <= int(m[1], 16):
8962306a36Sopenharmony_ci			return m[2]
9062306a36Sopenharmony_ci	return "N/A"
9162306a36Sopenharmony_ci
9262306a36Sopenharmony_cidef process_event(param_dict):
9362306a36Sopenharmony_ci	name       = param_dict["ev_name"]
9462306a36Sopenharmony_ci	sample     = param_dict["sample"]
9562306a36Sopenharmony_ci	phys_addr  = sample["phys_addr"]
9662306a36Sopenharmony_ci
9762306a36Sopenharmony_ci	global event_name
9862306a36Sopenharmony_ci	if event_name == None:
9962306a36Sopenharmony_ci		event_name = name
10062306a36Sopenharmony_ci	load_mem_type_cnt[find_memory_type(phys_addr)] += 1
101