| # mem-phys-addr.py: Resolve physical address samples | 
 | # SPDX-License-Identifier: GPL-2.0 | 
 | # | 
 | # Copyright (c) 2018, Intel Corporation. | 
 |  | 
 | from __future__ import division | 
 | from __future__ import print_function | 
 |  | 
 | import os | 
 | import sys | 
 | import struct | 
 | import re | 
 | import bisect | 
 | import collections | 
 |  | 
 | sys.path.append(os.environ['PERF_EXEC_PATH'] + \ | 
 | 	'/scripts/python/Perf-Trace-Util/lib/Perf/Trace') | 
 |  | 
 | #physical address ranges for System RAM | 
 | system_ram = [] | 
 | #physical address ranges for Persistent Memory | 
 | pmem = [] | 
 | #file object for proc iomem | 
 | f = None | 
 | #Count for each type of memory | 
 | load_mem_type_cnt = collections.Counter() | 
 | #perf event name | 
 | event_name = None | 
 |  | 
 | def parse_iomem(): | 
 | 	global f | 
 | 	f = open('/proc/iomem', 'r') | 
 | 	for i, j in enumerate(f): | 
 | 		m = re.split('-|:',j,2) | 
 | 		if m[2].strip() == 'System RAM': | 
 | 			system_ram.append(int(m[0], 16)) | 
 | 			system_ram.append(int(m[1], 16)) | 
 | 		if m[2].strip() == 'Persistent Memory': | 
 | 			pmem.append(int(m[0], 16)) | 
 | 			pmem.append(int(m[1], 16)) | 
 |  | 
 | def print_memory_type(): | 
 | 	print("Event: %s" % (event_name)) | 
 | 	print("%-40s  %10s  %10s\n" % ("Memory type", "count", "percentage"), end='') | 
 | 	print("%-40s  %10s  %10s\n" % ("----------------------------------------", | 
 | 					"-----------", "-----------"), | 
 | 					end=''); | 
 | 	total = sum(load_mem_type_cnt.values()) | 
 | 	for mem_type, count in sorted(load_mem_type_cnt.most_common(), \ | 
 | 					key = lambda kv: (kv[1], kv[0]), reverse = True): | 
 | 		print("%-40s  %10d  %10.1f%%\n" % | 
 | 			(mem_type, count, 100 * count / total), | 
 | 			end='') | 
 |  | 
 | def trace_begin(): | 
 | 	parse_iomem() | 
 |  | 
 | def trace_end(): | 
 | 	print_memory_type() | 
 | 	f.close() | 
 |  | 
 | def is_system_ram(phys_addr): | 
 | 	#/proc/iomem is sorted | 
 | 	position = bisect.bisect(system_ram, phys_addr) | 
 | 	if position % 2 == 0: | 
 | 		return False | 
 | 	return True | 
 |  | 
 | def is_persistent_mem(phys_addr): | 
 | 	position = bisect.bisect(pmem, phys_addr) | 
 | 	if position % 2 == 0: | 
 | 		return False | 
 | 	return True | 
 |  | 
 | def find_memory_type(phys_addr): | 
 | 	if phys_addr == 0: | 
 | 		return "N/A" | 
 | 	if is_system_ram(phys_addr): | 
 | 		return "System RAM" | 
 |  | 
 | 	if is_persistent_mem(phys_addr): | 
 | 		return "Persistent Memory" | 
 |  | 
 | 	#slow path, search all | 
 | 	f.seek(0, 0) | 
 | 	for j in f: | 
 | 		m = re.split('-|:',j,2) | 
 | 		if int(m[0], 16) <= phys_addr <= int(m[1], 16): | 
 | 			return m[2] | 
 | 	return "N/A" | 
 |  | 
 | def process_event(param_dict): | 
 | 	name       = param_dict["ev_name"] | 
 | 	sample     = param_dict["sample"] | 
 | 	phys_addr  = sample["phys_addr"] | 
 |  | 
 | 	global event_name | 
 | 	if event_name == None: | 
 | 		event_name = name | 
 | 	load_mem_type_cnt[find_memory_type(phys_addr)] += 1 |