1# mem-phys-addr.py: Resolve physical address samples
2# SPDX-License-Identifier: GPL-2.0
3#
4# Copyright (c) 2018, Intel Corporation.
5
6from __future__ import division
7from __future__ import print_function
8
9import os
10import sys
11import struct
12import re
13import bisect
14import collections
15
16sys.path.append(os.environ['PERF_EXEC_PATH'] + \
17	'/scripts/python/Perf-Trace-Util/lib/Perf/Trace')
18
19#physical address ranges for System RAM
20system_ram = []
21#physical address ranges for Persistent Memory
22pmem = []
23#file object for proc iomem
24f = None
25#Count for each type of memory
26load_mem_type_cnt = collections.Counter()
27#perf event name
28event_name = None
29
30def parse_iomem():
31	global f
32	f = open('/proc/iomem', 'r')
33	for i, j in enumerate(f):
34		m = re.split('-|:',j,2)
35		if m[2].strip() == 'System RAM':
36			system_ram.append(int(m[0], 16))
37			system_ram.append(int(m[1], 16))
38		if m[2].strip() == 'Persistent Memory':
39			pmem.append(int(m[0], 16))
40			pmem.append(int(m[1], 16))
41
42def print_memory_type():
43	print("Event: %s" % (event_name))
44	print("%-40s  %10s  %10s\n" % ("Memory type", "count", "percentage"), end='')
45	print("%-40s  %10s  %10s\n" % ("----------------------------------------",
46					"-----------", "-----------"),
47                                        end='');
48	total = sum(load_mem_type_cnt.values())
49	for mem_type, count in sorted(load_mem_type_cnt.most_common(), \
50					key = lambda kv: (kv[1], kv[0]), reverse = True):
51		print("%-40s  %10d  %10.1f%%\n" % (mem_type, count, 100 * count / total),
52                        end='')
53
54def trace_begin():
55	parse_iomem()
56
57def trace_end():
58	print_memory_type()
59	f.close()
60
61def is_system_ram(phys_addr):
62	#/proc/iomem is sorted
63	position = bisect.bisect(system_ram, phys_addr)
64	if position % 2 == 0:
65		return False
66	return True
67
68def is_persistent_mem(phys_addr):
69	position = bisect.bisect(pmem, phys_addr)
70	if position % 2 == 0:
71		return False
72	return True
73
74def find_memory_type(phys_addr):
75	if phys_addr == 0:
76		return "N/A"
77	if is_system_ram(phys_addr):
78		return "System RAM"
79
80	if is_persistent_mem(phys_addr):
81		return "Persistent Memory"
82
83	#slow path, search all
84	f.seek(0, 0)
85	for j in f:
86		m = re.split('-|:',j,2)
87		if int(m[0], 16) <= phys_addr <= int(m[1], 16):
88			return m[2]
89	return "N/A"
90
91def process_event(param_dict):
92	name       = param_dict["ev_name"]
93	sample     = param_dict["sample"]
94	phys_addr  = sample["phys_addr"]
95
96	global event_name
97	if event_name == None:
98		event_name = name
99	load_mem_type_cnt[find_memory_type(phys_addr)] += 1
100