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