diff --git a/linux-ramdump-parser-v2/debug_image_v2.py b/linux-ramdump-parser-v2/debug_image_v2.py index 8d0e7b12a0dda3dbf16ee153041eaa6882df97c4..509249899a8e3fb9861aac0585eb1a534bfb76e0 100755 --- a/linux-ramdump-parser-v2/debug_image_v2.py +++ b/linux-ramdump-parser-v2/debug_image_v2.py @@ -27,6 +27,7 @@ from print_out import print_out_str, print_out_exception from qdss import QDSSDump from watchdog_v2 import TZRegDump_v2 from cachedumplib import lookup_cache_type +from tlbdumplib import lookup_tlb_type from vsens import VsensData MEMDUMPV2_MAGIC = 0x42445953 @@ -58,8 +59,8 @@ class client(object): client_types = [ ('MSM_DUMP_DATA_SCANDUMP', 'parse_scandump'), ('MSM_DUMP_DATA_CPU_CTX', 'parse_cpu_ctx'), - ('MSM_DUMP_DATA_L1_INST_TLB', 'parse_l1_inst_tlb'), - ('MSM_DUMP_DATA_L1_DATA_TLB', 'parse_l1_data_tlb'), + ('MSM_DUMP_DATA_L1_INST_TLB', 'parse_tlb_common'), + ('MSM_DUMP_DATA_L1_DATA_TLB', 'parse_tlb_common'), ('MSM_DUMP_DATA_L1_INST_CACHE', 'parse_cache_common'), ('MSM_DUMP_DATA_L1_DATA_CACHE', 'parse_cache_common'), ('MSM_DUMP_DATA_L2_CACHE', 'parse_cache_common'), @@ -212,6 +213,23 @@ class DebugImage_v2(): print_out_exception() outfile.close() + def parse_tlb_common(self, version, start, end, client_id, ramdump): + client_name = self.dump_data_id_lookup_table[client_id] + core = client_id & 0xF + filename = '{0}_0x{1:x}'.format(client_name, core) + outfile = ramdump.open_file(filename) + cache_type = lookup_tlb_type(ramdump.hw_id, client_id, version) + try: + cache_type.parse(start, end, ramdump, outfile) + except NotImplementedError: + print_out_str('TLB dumping not supported for %s on this target' + % client_name) + except: + print_out_str('!!! Unhandled exception while running {0}'.format(client_name)) + print_out_exception() + outfile.close() + + def ftrace_field_func(self, common_list, ram_dump): name_offset = ram_dump.field_offset('struct ftrace_event_field', 'name') type_offset = ram_dump.field_offset('struct ftrace_event_field', 'type') diff --git a/linux-ramdump-parser-v2/tlbdumplib.py b/linux-ramdump-parser-v2/tlbdumplib.py new file mode 100644 index 0000000000000000000000000000000000000000..f7dd13dc7c04d07befb1d4fbb78aeb62b1453014 --- /dev/null +++ b/linux-ramdump-parser-v2/tlbdumplib.py @@ -0,0 +1,296 @@ +# Copyright (c) 2017, The Linux Foundation. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following +# disclaimer in the documentation and/or other materials provided +# with the distribution. +# +# * Neither the name of The Linux Foundation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED +# WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS +# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +# BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +# OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +# IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +import struct + +"""dictionary mapping from (hw_id, client_id, version) to class CacheDump""" +lookuptable = {} + + +def lookup_tlb_type(hwid, client_id, version): + """defaults to CacheDump() if no match found""" + return lookuptable.get((hwid, client_id, version), TlbDump()) + + +def formatwidth(string, limit): + if len(string) >= limit: + return string[0:limit] + formatstr = '{{0:{0}}}'.format(limit) + return formatstr.format(string) + +class TableOutputFormat: + """ Not sure if using PrettyTable (python lib) is a good idea, since people + would need to install it""" + + def __init__(self): + self.titlebar = [] + self.datafmt = [] + self.have_printed_title = False + self.separator = ' ' + + def addColumn(self, string, datafmt='{0}', width=0): + width = max(len(string), width) + string = formatwidth(string, width) + self.titlebar.append(string) + self.datafmt.append(datafmt) + + def printline(self, array, outfile): + if (len(array) != len(self.titlebar)): + raise Exception('BadTableDataSize', array, self.titlebar) + + if (not self.have_printed_title): + self.have_printed_title = True + outfile.write(self.separator.join(self.titlebar)) + outfile.write('\n') + + for item, title, fmt in zip(array, self.titlebar, self.datafmt): + item = fmt.format(item) + item = formatwidth(item, len(title)) + outfile.write(item) + outfile.write(self.separator) + + outfile.write('\n') + + +class TlbDump(object): + """ Class to describe a method to parse a particular type of tlbdump. + Users should not make instances of this class.""" + def __init__(self): + """do nothing""" + + def parse(self, start, end, ramdump, outfile): + """Called from debug_image_v2.py. Overriden by child classes""" + raise NotImplementedError + +class TlbDumpType(TlbDump): + def __init__(self): + super(TlbDumpType, self).__init__() + self.tableformat = TableOutputFormat() + self.tableformat.addColumn('Way', '{0:01x}') + self.tableformat.addColumn('Set', '{0:03x}') + self.ramdump = None + self.linefmt = None + + def add_table_data_columns(self): + for i in range(0, self.LineSize): + str = "DATA{0}".format(i) + self.tableformat.addColumn(str, '{0:08x}', 8) + + def read_line(self, start): + if self.linefmt is None: + self.linefmt = '<' + self.linefmt += 'I'* self.LineSize + return self.ramdump.read_string(start, self.linefmt, virtual=False) + + +class TlbDumpType_v1(TlbDumpType): + def __init__(self): + super(TlbDumpType_v1, self).__init__() + + def parse(self, start, end, ramdump, outfile): + self.ramdump = ramdump + self.add_table_data_columns() + + for nset in range(self.NumSets): + for nway in range(self.NumWays): + if start > end: + raise Exception('past the end of array') + + output = [nway, nset] + line = self.read_line(start) + output.extend(line) + self.tableformat.printline(output, outfile) + start = start + self.LineSize * 0x4 + +class TlbDumpType_v2(TlbDumpType): + def __init__(self): + super(TlbDumpType_v2, self).__init__() + self.tableformat.addColumn('RAM') + self.tableformat.addColumn('TYPE') + self.tableformat.addColumn('PA', '{0:016x}', 16) + self.tableformat.addColumn('VA', '{0:016x}', 16) + self.tableformat.addColumn('VALID') + self.tableformat.addColumn('VMID', '{0:02x}', 4) + self.tableformat.addColumn('ASID', '{0:04x}', 4) + self.tableformat.addColumn('S1_MODE', '{0:01x}', 7) + self.tableformat.addColumn('S1_LEVEL', '{0:01x}', 8) + self.tableformat.addColumn('SIZE') + + def parse(self, start, end, ramdump, outfile): + self.ramdump = ramdump + self.add_table_data_columns() + + ram = 0 + for nway in range(self.NumWaysRam0): + offset = 0 + for nset in range(self.NumSetsRam0): + if start > end: + raise Exception('past the end of array') + + output = [nway, nset] + line = self.read_line(start) + self.parse_tag_fn(output, line, nset, nway, ram, offset) + output.extend(line) + self.tableformat.printline(output, outfile) + start = start + self.LineSize * 0x4 + offset = offset + 0x1000 + + ram = 1 + for nway in range(self.NumWaysRam0): + offset = 0 + for nset in range(self.NumSetsRam1): + if start > end: + raise Exception('past the end of array') + + output = [nway, nset] + line = self.read_line(start) + self.parse_tag_fn(output, line, nset, nway, ram, offset) + output.extend(line) + self.tableformat.printline(output, outfile) + start = start + self.LineSize * 0x4 + offset = (offset + 0x1000) + +class L1_TLB_KRYO2XX_GOLD(TlbDumpType_v2): + def __init__(self): + super(L1_TLB_KRYO2XX_GOLD, self).__init__() + self.unsupported_header_offset = 0 + self.LineSize = 4 + self.NumSetsRam0 = 0x100 + self.NumSetsRam1 = 0x3c + self.NumWaysRam0 = 4 + self.NumWaysRam1 = 2 + + def parse_tag_fn(self, output, data, nset, nway, ram, offset): + tlb_type = self.parse_tlb_type(data) + + s1_mode = (data[0] >> 2) & 0x3 + + s1_level = data[0] & 0x3 + + pa = (data[2] >> 4) * 0x1000 + pa = pa + offset + + va_l = (data[1] >> 2) + va_h = (data[2]) & 0x7 + va = (va_h << 45) | (va_l << 16) + va = va + offset + + if ((va >> 40) & 0xff )== 0xff: + va = va + 0xffff000000000000 + + valid = (data[2] >> 3) & 0x1 + + vmid_1 = (data[0] >> 26) & 0x3f + vmid_2 = data[1] & 0x3 + vmid = (vmid_2 << 6) | vmid_1 + + asid = (data[0] >> 10) & 0xffff + + size = self.parse_size(data, ram, tlb_type) + output.append(ram) + output.append(tlb_type) + output.append(pa) + output.append(va) + output.append(valid) + output.append(vmid) + output.append(asid) + output.append(s1_mode) + output.append(s1_level) + output.append(size) + + def parse_tlb_type(self, data): + type_num = (data[3] >> 20) & 0x1 + if type_num == 0x0: + s1_level = data[0] & 0x3 + if s1_level == 0x3: + return "IPA" + else: + return "REG" + else: + return "WALK" + + def parse_size(self, data, ram, tlb_type): + size = (data[0] >> 6) & 0x7 + if tlb_type == "REG": + if ram == 0: + if size == 0x0: + return "4KB" + elif size == 0x1: + return "16KB" + else: + return "64KB" + else: + if size == 0x0: + return "1MB" + elif size == 0x1: + return "2MB" + elif size == 0x2: + return "16MB" + elif size == 0x3: + return "32MB" + elif size == 0x4: + return "512MB" + else: + return "1GB" + else: + if size == 0x1: + return "4KB" + elif size == 0x3: + return "16KB" + elif size == 0x4: + return "64KB" + +class L1_TLB_A53(TlbDumpType_v1): + def __init__(self): + super(L1_TLB_A53, self).__init__() + self.unsupported_header_offset = 0 + self.LineSize = 4 + self.NumSets = 0x100 + self.NumWays = 4 + +# "msm8998" +lookuptable[("8998", 0x20, 0x14)] = L1_TLB_A53() +lookuptable[("8998", 0x21, 0x14)] = L1_TLB_A53() +lookuptable[("8998", 0x22, 0x14)] = L1_TLB_A53() +lookuptable[("8998", 0x23, 0x14)] = L1_TLB_A53() +lookuptable[("8998", 0x24, 0x14)] = L1_TLB_KRYO2XX_GOLD() +lookuptable[("8998", 0x25, 0x14)] = L1_TLB_KRYO2XX_GOLD() +lookuptable[("8998", 0x26, 0x14)] = L1_TLB_KRYO2XX_GOLD() +lookuptable[("8998", 0x27, 0x14)] = L1_TLB_KRYO2XX_GOLD() + + +lookuptable[("8998", 0x40, 0x14)] = L1_TLB_A53() +lookuptable[("8998", 0x41, 0x14)] = L1_TLB_A53() +lookuptable[("8998", 0x42, 0x14)] = L1_TLB_A53() +lookuptable[("8998", 0x43, 0x14)] = L1_TLB_A53() +lookuptable[("8998", 0x44, 0x14)] = L1_TLB_KRYO2XX_GOLD() +lookuptable[("8998", 0x45, 0x14)] = L1_TLB_KRYO2XX_GOLD() +lookuptable[("8998", 0x46, 0x14)] = L1_TLB_KRYO2XX_GOLD() +lookuptable[("8998", 0x47, 0x14)] = L1_TLB_KRYO2XX_GOLD() +