diff --git a/linux-ramdump-parser-v2/parsers/lpm.py b/linux-ramdump-parser-v2/parsers/lpm.py new file mode 100644 index 0000000000000000000000000000000000000000..150ccc03ab8035f05033203a25d4327ece3c751e --- /dev/null +++ b/linux-ramdump-parser-v2/parsers/lpm.py @@ -0,0 +1,344 @@ +# Copyright (c) 2015, The Linux Foundation. All rights reserved. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 and +# only version 2 as published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +import linux_list +from parser_util import register_parser, RamParser +from operator import itemgetter + +@register_parser('--lpm', 'Parse LPM Driver info') +class lpm(RamParser): + def __init__(self, *args): + super(lpm, self).__init__(*args) + self.head = '' + self.output = [] + self.clusters = [] + self.cpu_possible_bits = None + self.cpu_online_bits = None + self.lpm_debug = [] + + def get_bits(self): + bits_addr = self.ramdump.addr_lookup('cpu_possible_bits') + if bits_addr is None: + self.output.append("NOTE: 'cpu_possible_bits' not found") + return + + self.cpu_possible_bits = self.ramdump.read_int(bits_addr) + cpus = bin(self.cpu_possible_bits).count('1') + self.output.append("{}\n".format('Available CPUs')) + for i in range(0, cpus): + self.output.append("{:10}{}:{}\n".format("", "CPU", i)) + self.output.append("\n") + + bits_addr = self.ramdump.addr_lookup('cpu_online_bits') + if bits_addr is None: + self.output.append("NOTE: 'cpu_online_bits' not found") + return + + self.cpu_online_bits = self.ramdump.read_int(bits_addr) + cpus = bin(self.cpu_online_bits).count('1') + self.output.append("{}\n".format('Online CPUs')) + for i in range(0, cpus): + self.output.append("{:10}{}:{}\n".format("", "CPU", i)) + self.output.append("{}{}{}".format("\n", "-" * 81, "\n")) + + def get_cluster_level_info(self, lpm_cluster): + offset = self.ramdump.field_offset('struct lpm_cluster', 'nlevels') + nlevels = self.ramdump.read_int(lpm_cluster + offset) + self.output.append("{:20}:{}\n".format("number of levels", nlevels)) + + offset = self.ramdump.field_offset('struct lpm_cluster', 'min_child_level') + node = self.ramdump.read_int(lpm_cluster + offset) + self.output.append("{:20}:{}\n".format("min child level", node)) + + offset = self.ramdump.field_offset('struct lpm_cluster', 'default_level') + node = self.ramdump.read_int(lpm_cluster + offset) + self.output.append("{:20}:{}\n".format("default level", node)) + + offset = self.ramdump.field_offset('struct lpm_cluster', 'last_level') + node = self.ramdump.read_int(lpm_cluster + offset) + self.output.append("{:20}:{}\n".format("last_level", node)) + + offset = self.ramdump.field_offset('struct lpm_cluster', 'levels') + levels = lpm_cluster + offset + self.output.append("\n") + + cluster_level_size = self.ramdump.sizeof('struct lpm_cluster_level') + + for i in xrange(nlevels): + # ToDo: Need a better way to arrive at the next level info. + level = levels + (i * cluster_level_size) + + offset = self.ramdump.field_offset('struct lpm_cluster_level', 'mode') + addr = self.ramdump.read_word(level + offset, True) + node = self.ramdump.read_int(addr) + self.output.append("{:20}:{}\n".format("level mode", node)) + + offset = self.ramdump.field_offset('struct lpm_cluster_level', 'level_name') + addr = self.ramdump.read_word(level + offset, True) + name = self.ramdump.read_cstring(addr, 48) + self.output.append("{:20}:{}\n".format("level name", name)) + + offset = self.ramdump.field_offset('struct lpm_cluster_level', 'min_child_level') + addr = level + offset + node = self.ramdump.read_int(addr) + self.output.append("{:20}:{}\n".format("min child level", node)) + + offset = self.ramdump.field_offset('struct lpm_cluster_level', 'num_cpu_votes') + addr = level + offset + node = self.ramdump.read_int(addr) + self.output.append("{:20}:{}({})\n".format("num cpu votes", hex(node).rstrip("L"), bin(node).lstrip("0b"))) + + offset = self.ramdump.field_offset('struct lpm_cluster_level', 'available') + addr = level + offset + + offset = self.ramdump.field_offset('struct lpm_level_avail', 'idle_enabled') + node = self.ramdump.read_bool(addr + offset) + self.output.append("{:20}:{}\n".format("idle_enabled", node)) + + offset = self.ramdump.field_offset('struct lpm_level_avail', 'suspend_enabled') + node = self.ramdump.read_bool(addr + offset) + self.output.append("{:20}:{}\n".format("suspend_enabled", node)) + self.output.append("\n") + + def get_cluster_info(self, lpm_cluster): + offset = self.ramdump.field_offset('struct lpm_cluster', 'cluster_name') + addr = self.ramdump.read_word(lpm_cluster + offset, True) + node = self.ramdump.read_cstring(addr, 48) + self.output.append("{:20}:{}\n".format("Cluster Name", node)) + + offset = self.ramdump.field_offset('struct lpm_cluster', 'child_cpus') + node = self.ramdump.read_int(lpm_cluster + offset) + self.output.append("{:20}:{}({})\n".format("child_cpus", hex(node).rstrip("L"), bin(node).lstrip("0b"))) + + offset = self.ramdump.field_offset('struct lpm_cluster', 'num_childs_in_sync') + node = self.ramdump.read_int(lpm_cluster + offset) + self.output.append("{:20}:{}({})\n".format("num_childs_in_sync", hex(node).rstrip("L"), bin(node).lstrip("0b"))) + self.output.append("\n") + + def lpm_walker(self, lpm_cluster): + if lpm_cluster == self.head: + return + self.clusters.append(lpm_cluster) + + def get_clusters(self): + lpm_root_node = self.ramdump.read_word(self.ramdump.addr_lookup('lpm_root_node'), True) + if lpm_root_node is None: + self.output_file.write("NOTE: 'lpm_root_node' not found\n") + return + + self.clusters.append(lpm_root_node) + + offset = self.ramdump.field_offset('struct lpm_cluster', 'child') + lpm_cluster = self.ramdump.read_word(lpm_root_node + offset, True) + self.head = lpm_root_node + offset + + offset = self.ramdump.field_offset('struct lpm_cluster', 'list') + lpm_walker = linux_list.ListWalker(self.ramdump, lpm_cluster, offset) + lpm_walker.walk(lpm_cluster, self.lpm_walker) + + def get_cpu_level_info(self, cpu_cluster_base, cpu): + self.output.append("{:20}:{}\n".format("CPU", cpu)) + + cpu_cluster = self.ramdump.read_word(cpu_cluster_base, cpu=cpu) + offset = self.ramdump.field_offset('struct lpm_cluster', 'cpu') + cpu_level = self.ramdump.read_word(cpu_cluster + offset, True) + + offset = self.ramdump.field_offset('struct lpm_cpu', 'nlevels') + nlevels = self.ramdump.read_int(cpu_level + offset, True) + self.output.append("{:20}:{}\n".format("number of levels", nlevels)) + + offset = self.ramdump.field_offset('struct lpm_cpu', 'levels') + levels = cpu_level + offset + + self.output.append("\n") + + cpu_level_available = self.ramdump.addr_lookup('cpu_level_available') + if cpu_level_available is None: + self.output.append("NOTE: 'cpu_level_available' not found\n") + return + cpu_level_available = cpu_level_available + self.ramdump.sizeof('long') * cpu + cpu_level_available = self.ramdump.read_word(cpu_level_available, True) + + for i in range(0, nlevels): + level = levels + (i * self.ramdump.sizeof('struct lpm_cpu_level')) + + offset = self.ramdump.field_offset('struct lpm_cpu_level', 'name') + addr = self.ramdump.read_word(level + offset, True) + node = self.ramdump.read_cstring(addr, 48) + self.output.append("{:20}:{}\n".format("level name", node)) + + offset = self.ramdump.field_offset('struct lpm_cpu_level', 'mode') + node = self.ramdump.read_int(level + offset, True) + self.output.append("{:20}:{}\n".format("level mode", node)) + + level_available = cpu_level_available + i * self.ramdump.sizeof('struct lpm_level_avail') + offset = self.ramdump.field_offset('struct lpm_level_avail', 'idle_enabled') + node = self.ramdump.read_bool(level_available + offset) + self.output.append("{:20}:{}\n".format("idle enabled", node)) + + offset = self.ramdump.field_offset('struct lpm_level_avail', 'suspend_enabled') + node = self.ramdump.read_bool(level_available + offset, True) + self.output.append("{:20}:{}\n".format("suspend enabled", node)) + + self.output.append("\n") + + self.output.append("{}{}".format("-" * 81, "\n")) + + def get_lpm(self): + self.get_clusters() + for i in self.clusters: + self.get_cluster_info(i) + self.get_cluster_level_info(i) + self.output.append("{}{}".format("-" * 81, "\n")) + + cpu_cluster_base = self.ramdump.addr_lookup('cpu_cluster') + if cpu_cluster_base is None: + self.output.append("NOTE: 'cpu_cluster' not found\n") + return + + cpus = bin(self.cpu_possible_bits).count('1') + for i in range(0, cpus): + self.get_cpu_level_info(cpu_cluster_base, i) + + def get_time_stats(self, tstats, nlevels): + for i in range(nlevels): + lstats = tstats + i * self.ramdump.sizeof('struct level_stats') + + offset = self.ramdump.field_offset('struct level_stats', 'name') + addr = self.ramdump.read_word(lstats + offset, True) + self.output.append("{:20}:{}\n".format("lpm name", self.ramdump.read_cstring(addr + offset, 48))) + + offset = self.ramdump.field_offset('struct level_stats', 'success_count') + self.output.append("{:20}:{}\n".format("success_count", self.ramdump.read_int(lstats + offset, True))) + + offset = self.ramdump.field_offset('struct level_stats', 'failed_count') + self.output.append("{:20}:{}\n".format("failed_count", self.ramdump.read_int(lstats + offset, True))) + + self.output.append("\n") + + def get_cluster_stats(self, cluster): + offset = self.ramdump.field_offset('struct lpm_cluster', 'stats') + stats = self.ramdump.read_word(cluster + offset, True) + + offset = self.ramdump.field_offset('struct lpm_stats', 'name') + self.output.append("{} {}\n\n".format(self.ramdump.read_cstring(stats + offset, 48), "lpm stats")) + + offset = self.ramdump.field_offset('struct lpm_stats', 'num_levels') + nlevels = self.ramdump.read_int(stats + offset, True) + + offset = self.ramdump.field_offset('struct lpm_stats', 'time_stats') + tstats = self.ramdump.read_word(stats + offset, True) + + self.get_time_stats(tstats, nlevels) + self.output.append("{}{}".format("-" * 81, "\n")) + + def get_cpu_stats(self, cpu_stats_base, cpu): + stats = cpu_stats_base + self.ramdump.per_cpu_offset(cpu) + + offset = self.ramdump.field_offset('struct lpm_stats', 'name') + self.output.append("{} {}\n\n".format(self.ramdump.read_cstring(stats + offset, 48), "lpm stats")) + + offset = self.ramdump.field_offset('struct lpm_stats', 'num_levels') + nlevels = self.ramdump.read_int(stats + offset, True) + + offset = self.ramdump.field_offset('struct lpm_stats', 'time_stats') + tstats = self.ramdump.read_word(stats + offset, True) + + self.get_time_stats(tstats, nlevels) + self.output.append("{}{}".format("-" * 81, "\n")) + + def get_stats(self): + for i in self.clusters: + self.get_cluster_stats(i) + + cpu_stats_base = self.ramdump.addr_lookup('cpu_stats') + if cpu_stats_base is None: + self.output.append("NOTE: 'cpu_stats' not found\n") + return + + cpus = bin(self.cpu_possible_bits).count('1') + for i in range(0, cpus): + self.get_cpu_stats(cpu_stats_base, i) + + def get_debug_phys(self): + lpm_debug_phys = self.ramdump.addr_lookup('lpm_debug_phys') + if lpm_debug_phys is None: + self.output.append("NOTE: 'lpm_debug data' not found\n") + return + lpm_debug_phys = self.ramdump.read_word(lpm_debug_phys, True) + + for i in range(0, 256): + debug = [] + + addr = lpm_debug_phys + i * self.ramdump.sizeof('struct lpm_debug') + + offset = self.ramdump.field_offset('struct lpm_debug', 'time') + time = self.ramdump.read_word(addr + offset, False) + debug.append(time) + + offset = self.ramdump.field_offset('struct lpm_debug', 'evt') + evt = self.ramdump.read_int(addr + offset, False) + debug.append(evt) + + offset = self.ramdump.field_offset('struct lpm_debug', 'cpu') + cpu = self.ramdump.read_int(addr + offset, False) + debug.append(cpu) + + offset = self.ramdump.field_offset('struct lpm_debug', 'arg1') + arg1 = self.ramdump.read_int(addr + offset, False) + debug.append(arg1) + + offset = self.ramdump.field_offset('struct lpm_debug', 'arg2') + arg2 = self.ramdump.read_int(addr + offset, False) + debug.append(arg2) + + offset = self.ramdump.field_offset('struct lpm_debug', 'arg3') + arg3 = self.ramdump.read_int(addr + offset, False) + debug.append(arg3) + + offset = self.ramdump.field_offset('struct lpm_debug', 'arg4') + arg4 = self.ramdump.read_int(addr + offset, False) + debug.append(arg4) + + self.lpm_debug.append(debug) + + def print_debug_phys(self): + debug = [] + lpm_debug = [] + + self.output.append("\n") + self.output.append("{:16}".format("TimeStamp")) + self.output.append("{:8} {:8} {:8} ".format("Event", "CPU", "arg1")) + self.output.append("{:16}{:16}{:16}\n".format("arg2", "arg3", "arg4")) + self.output.append("{}{}".format("-" * 81, "\n")) + + lpm_debug = sorted(self.lpm_debug, key=itemgetter(0)) + + for i in range(len(lpm_debug)): + debug = lpm_debug[i] + for j in range(len(debug)): + if j == 0 or j > 3: + self.output.append("{:16}".format(hex(debug[j]).rstrip("L"))) + else: + self.output.append("{}{:8}".format(debug[j], "")) + + self.output.append("\n") + + def parse(self): + self.output_file = self.ramdump.open_file('lpm.txt') + self.get_bits() + self.get_lpm() + self.get_stats() + self.get_debug_phys() + self.print_debug_phys() + for i in self.output: + self.output_file.write(i) + self.output_file.close() diff --git a/linux-ramdump-parser-v2/parsers/spm.py b/linux-ramdump-parser-v2/parsers/spm.py new file mode 100644 index 0000000000000000000000000000000000000000..076a435f3adc8ac433a4bb8b0baa9ec486b2c0e3 --- /dev/null +++ b/linux-ramdump-parser-v2/parsers/spm.py @@ -0,0 +1,112 @@ +# Copyright (c) 2015, The Linux Foundation. All rights reserved. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 and +# only version 2 as published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +import linux_list +from parser_util import register_parser, RamParser + +@register_parser('--spm', 'Parse SPM Driver info') +class spm(RamParser): + def __init__(self, *args): + super(spm, self).__init__(*args) + self.head = '' + self.output = [] + self.spm_reg_2_1 = ('MSM_SPM_REG_SAW2_SECURE', 'MSM_SPM_REG_SAW2_ID', + 'MSM_SPM_REG_SAW2_CFG', 'MSM_SPM_REG_SAW2_SPM_STS', + 'MSM_SPM_REG_SAW2_AVS_STS', 'MSM_SPM_REG_SAW2_PMIC_STS', + 'MSM_SPM_REG_SAW2_RST', 'MSM_SPM_REG_SAW2_VCTL', + 'MSM_SPM_REG_SAW2_AVS_CTL', 'MSM_SPM_REG_SAW2_AVS_LIMIT', + 'MSM_SPM_REG_SAW2_AVS_DLY', 'MSM_SPM_REG_SAW2_AVS_HYSTERESIS', + 'MSM_SPM_REG_SAW2_SPM_CTL', 'MSM_SPM_REG_SAW2_SPM_DLY', + 'MSM_SPM_REG_SAW2_PMIC_DATA_0', 'MSM_SPM_REG_SAW2_PMIC_DATA_1', + 'MSM_SPM_REG_SAW2_PMIC_DATA_2', 'MSM_SPM_REG_SAW2_PMIC_DATA_3', + 'MSM_SPM_REG_SAW2_PMIC_DATA_4', 'MSM_SPM_REG_SAW2_PMIC_DATA_5', + 'MSM_SPM_REG_SAW2_PMIC_DATA_6', 'MSM_SPM_REG_SAW2_PMIC_DATA_7', + 'MSM_SPM_REG_SAW2_SEQ_ENTRY', 'MSM_SPM_REG_SAW2_VERSION') + + self.spm_reg_3_0 = ('MSM_SPM_REG_SAW2_SECURE', 'MSM_SPM_REG_SAW2_ID', + 'MSM_SPM_REG_SAW2_CFG', 'MSM_SPM_REG_SAW2_SPM_STS', + 'MSM_SPM_REG_SAW2_AVS_STS', 'MSM_SPM_REG_SAW2_PMIC_STS', + 'MSM_SPM_REG_SAW2_RST', 'MSM_SPM_REG_SAW2_VCTL', + 'MSM_SPM_REG_SAW2_AVS_CTL', 'MSM_SPM_REG_SAW2_AVS_LIMIT', + 'MSM_SPM_REG_SAW2_AVS_DLY', 'MSM_SPM_REG_SAW2_AVS_HYSTERESIS', + 'MSM_SPM_REG_SAW2_SPM_CTL', 'MSM_SPM_REG_SAW2_SPM_DLY', + 'MSM_SPM_REG_SAW2_STS2', 'MSM_SPM_REG_SAW2_PMIC_DATA_0', + 'MSM_SPM_REG_SAW2_PMIC_DATA_1', 'MSM_SPM_REG_SAW2_PMIC_DATA_2', + 'MSM_SPM_REG_SAW2_PMIC_DATA_3', 'MSM_SPM_REG_SAW2_PMIC_DATA_4', + 'MSM_SPM_REG_SAW2_PMIC_DATA_5', 'MSM_SPM_REG_SAW2_PMIC_DATA_6', + 'MSM_SPM_REG_SAW2_PMIC_DATA_7', 'MSM_SPM_REG_SAW2_SEQ_ENTRY', + 'MSM_SPM_REG_SAW2_VERSION') + + def spm_walker(self, spm): + if spm == self.head: + return + + offset = self.ramdump.field_offset('struct msm_spm_device', 'initialized') + if self.ramdump.read_bool(spm + offset) is False: + return + + offset = self.ramdump.field_offset('struct msm_spm_device', 'name') + name = self.ramdump.read_cstring(self.ramdump.read_word(spm + offset, True), 48) + self.output.append("{:35}:{}\n".format("SPM Device Name", name)) + + offset = self.ramdump.field_offset('struct msm_spm_device', 'reg_data') + reg_data = spm + offset + + offset = self.ramdump.field_offset('struct msm_spm_driver_data', 'major') + addr = reg_data + offset + major = self.ramdump.read_int(addr) + self.output.append("{:35}:{}".format("version", major)) + + offset = self.ramdump.field_offset('struct msm_spm_driver_data', 'minor') + addr = reg_data + offset + minor = self.ramdump.read_int(addr) + self.output.append(".{}\n".format(minor)) + + self.output.append("\n{}\n".format("Shadow Registers")) + + offset = self.ramdump.field_offset('struct msm_spm_driver_data', 'reg_shadow') + + if major is 2 and minor is 1: + rList = self.spm_reg_2_1 + else: + rList = self.spm_reg_3_0 + + for i in range(len(rList)): + addr = reg_data + offset + i * self.ramdump.sizeof('uint32_t') + val = self.ramdump.read_int(addr) + self.output.append("{:35}:{}\n".format(rList[i], hex(val).rstrip("L"))) + + self.output.append("{}{}".format("-" * 81, "\n\n")) + + def get_spm(self): + lpm_root_node = self.ramdump.read_word(self.ramdump.addr_lookup('lpm_root_node'), True) + if lpm_root_node is None: + self.output_file.write("NOTE: 'lpm_root_node' not found\n") + return + + offset = self.ramdump.field_offset('struct lpm_cluster', 'lpm_dev') + lpm_dev = self.ramdump.read_word(lpm_root_node + offset, True) + + offset = self.ramdump.field_offset('struct low_power_ops', 'spm') + spm = self.ramdump.read_word(lpm_dev + offset, True) + + self.head = lpm_dev + offset + + offset = self.ramdump.field_offset('struct msm_spm_device', 'list') + spm_walker = linux_list.ListWalker(self.ramdump, spm, offset) + spm_walker.walk(spm, self.spm_walker) + + def parse(self): + self.output_file = self.ramdump.open_file('spm.txt') + self.get_spm() + for i in self.output: + self.output_file.write(i) + self.output_file.close()