From 1722c90cfa54e8d61d808ca2fc5c4e73129c6ec7 Mon Sep 17 00:00:00 2001
From: Aparna Das <adas@codeaurora.org>
Date: Fri, 28 Mar 2014 18:25:48 -0700
Subject: [PATCH] linux-ramdump-parser-v2: Add support for v2 memory dump

Add support to the ramdump parser to parse debug image v2
format. Current support is for parsing cpu context and QDSS
dumps.

Change-Id: Ic7437e3b999845d607366bcf727f00078f81915a
---
 linux-ramdump-parser-v2/debug_image_v2.py     | 237 +++++++++++++
 .../parsers/debug_image.py                    |  23 +-
 linux-ramdump-parser-v2/qdss.py               |  29 +-
 linux-ramdump-parser-v2/watchdog_v2.py        | 331 ++++++++++++++++++
 4 files changed, 601 insertions(+), 19 deletions(-)
 create mode 100644 linux-ramdump-parser-v2/debug_image_v2.py
 create mode 100644 linux-ramdump-parser-v2/watchdog_v2.py

diff --git a/linux-ramdump-parser-v2/debug_image_v2.py b/linux-ramdump-parser-v2/debug_image_v2.py
new file mode 100644
index 0000000..6851442
--- /dev/null
+++ b/linux-ramdump-parser-v2/debug_image_v2.py
@@ -0,0 +1,237 @@
+# Copyright (c) 2012-2014, 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 struct
+
+from print_out import print_out_str
+from qdss import QDSSDump
+from watchdog_v2 import TZRegDump_v2
+
+MEMDUMPV2_MAGIC = 0x42445953
+
+class client(object):
+    MSM_DUMP_DATA_CPU_CTX = 0x00
+    MSM_DUMP_DATA_L1_INST_CACHE = 0x60
+    MSM_DUMP_DATA_L1_DATA_CACHE = 0x80
+    MSM_DUMP_DATA_ETM_REG = 0xA0
+    MSM_DUMP_DATA_L2_CACHE = 0xC0
+    MSM_DUMP_DATA_L3_CACHE = 0xD0
+    MSM_DUMP_DATA_OCMEM = 0xE0
+    MSM_DUMP_DATA_TMC_ETF = 0xF0
+    MSM_DUMP_DATA_TMC_REG = 0x100
+    MSM_DUMP_DATA_TMC_ETF_REG = 0x101
+    MSM_DUMP_DATA_MAX = 0x110
+
+client_table = {
+    'MSM_DUMP_DATA_CPU_CTX': 'parse_cpu_ctx',
+    'MSM_DUMP_DATA_L1_INST_CACHE': 'parse_l1_inst_cache',
+    'MSM_DUMP_DATA_L1_DATA_CACHE': 'parse_l1_data_cache',
+    'MSM_DUMP_DATA_ETM_REG': 'parse_qdss_common',
+    'MSM_DUMP_DATA_L2_CACHE': 'parse_l2_cache',
+    'MSM_DUMP_DATA_L3_CACHE': 'parse_l3_cache',
+    'MSM_DUMP_DATA_OCMEM': 'parse_ocmem',
+    'MSM_DUMP_DATA_TMC_ETF': 'parse_qdss_common',
+    'MSM_DUMP_DATA_TMC_REG': 'parse_qdss_common',
+}
+
+qdss_tag_to_field_name = {
+    'MSM_DUMP_DATA_TMC_REG': 'tmc_etr_start',
+    'MSM_DUMP_DATA_TMC_ETF': 'etf_start',
+    'MSM_ETM0_REG': 'etm_regs0',
+    'MSM_ETM1_REG': 'etm_regs1',
+    'MSM_ETM2_REG': 'etm_regs2',
+    'MSM_ETM3_REG': 'etm_regs3',
+}
+
+class DebugImage_v2():
+
+    def __init__(self):
+        self.qdss = QDSSDump()
+        self.dump_type_lookup_table = []
+        self.dump_table_id_lookup_table = []
+        self.dump_data_id_lookup_table  = []
+
+    def parse_cpu_ctx(self, start, end, client_id, ram_dump):
+        core = client_id - client.MSM_DUMP_DATA_CPU_CTX
+
+        print_out_str(
+            'Parsing CPU{2} context start {0:x} end {1:x}'.format(start, end, core))
+
+        regs = TZRegDump_v2()
+        if regs.init_regs(start, end, core, ram_dump) is False:
+            print_out_str('!!! Could not get registers from TZ dump')
+            return
+        regs.dump_core_pc(ram_dump)
+        regs.dump_all_regs(ram_dump)
+
+    def parse_qdss_common(self, start, end, client_id, ram_dump):
+        client_name = self.dump_data_id_lookup_table[client_id]
+
+        print_out_str(
+            'Parsing {0} context start {1:x} end {2:x}'.format(client_name, start, end))
+
+        if client_id == client.MSM_DUMP_DATA_TMC_ETF_REG:
+            setattr(self.qdss, 'tmc_etf_start', start)
+        else:
+            setattr(self.qdss, qdss_tag_to_field_name[client_name], start)
+
+    def parse_dump_v2(self, ram_dump):
+        self.dump_type_lookup_table = ram_dump.gdbmi.get_enum_lookup_table(
+            'msm_dump_type', 2)
+        self.dump_table_id_lookup_table = ram_dump.gdbmi.get_enum_lookup_table(
+            'msm_dump_table_ids', 0x110)
+        self.dump_data_id_lookup_table = ram_dump.gdbmi.get_enum_lookup_table(
+            'msm_dump_data_ids', 0x110)
+        cpu_present_bits = ram_dump.read_word('cpu_present_bits')
+        cpus = bin(cpu_present_bits).count('1')
+        # per cpu entries
+        for i in range(1, cpus):
+
+                self.dump_data_id_lookup_table[
+                    client.MSM_DUMP_DATA_CPU_CTX + i] = 'MSM_DUMP_DATA_CPU_CTX'
+                self.dump_data_id_lookup_table[
+                    client.MSM_DUMP_DATA_L1_INST_CACHE + i] = 'MSM_DUMP_DATA_L1_INST_CACHE'
+                self.dump_data_id_lookup_table[
+                    client.MSM_DUMP_DATA_L1_DATA_CACHE + i] = 'MSM_DUMP_DATA_L1_DATA_CACHE'
+                self.dump_data_id_lookup_table[
+                    client.MSM_DUMP_DATA_ETM_REG + i] = 'MSM_DUMP_DATA_ETM_REG'
+        # 0x100 - tmc-etr registers and 0x101 - for tmc-etf registers
+        self.dump_data_id_lookup_table[
+            client.MSM_DUMP_DATA_TMC_REG + 1] = 'MSM_DUMP_DATA_TMC_REG'
+        dump_table_ptr_offset = ram_dump.field_offset(
+            'struct msm_memory_dump', 'table')
+        dump_table_version_offset = ram_dump.field_offset(
+            'struct msm_dump_table', 'version')
+        dump_table_num_entry_offset = ram_dump.field_offset(
+            'struct msm_dump_table', 'num_entries')
+        dump_table_entry_offset = ram_dump.field_offset(
+            'struct msm_dump_table', 'entries')
+        dump_entry_id_offset = ram_dump.field_offset(
+            'struct msm_dump_entry', 'id')
+        dump_entry_name_offset = ram_dump.field_offset(
+            'struct msm_dump_entry', 'name')
+        dump_entry_type_offset = ram_dump.field_offset(
+            'struct msm_dump_entry', 'type')
+        dump_entry_addr_offset = ram_dump.field_offset(
+            'struct msm_dump_entry', 'addr')
+        dump_data_version_offset = ram_dump.field_offset(
+            'struct msm_dump_data', 'version')
+        dump_data_magic_offset =  ram_dump.field_offset(
+            'struct msm_dump_data', 'magic')
+        dump_data_name_offset = ram_dump.field_offset(
+            'struct msm_dump_data', 'name')
+        dump_data_addr_offset = ram_dump.field_offset(
+            'struct msm_dump_data', 'addr')
+        dump_data_len_offset = ram_dump.field_offset(
+            'struct msm_dump_data', 'len')
+        dump_data_reserved_offset = ram_dump.field_offset(
+            'struct msm_dump_data', 'reserved')
+        dump_entry_size = ram_dump.sizeof('struct msm_dump_entry')
+        dump_data_size = ram_dump.sizeof('struct msm_dump_data')
+
+        mem_dump_data = ram_dump.addr_lookup('memdump')
+
+        mem_dump_table = ram_dump.read_word(
+            mem_dump_data + dump_table_ptr_offset)
+
+        mem_table_version = ram_dump.read_u32(
+            mem_dump_table + dump_table_version_offset)
+        if mem_table_version is None:
+            print_out_str('Version is bogus! Can\'t parse debug image')
+            return
+        mem_table_num_entry = ram_dump.read_u32(
+            mem_dump_table + dump_table_num_entry_offset)
+        if mem_table_num_entry is None or mem_table_num_entry > 100:
+            print_out_str('num_entries is bogus! Can\'t parse debug image')
+            return
+
+        print_out_str('\nDebug image version: {0}.{1} Number of table entries {2}'.format(
+            mem_table_version >> 20, mem_table_version & 0xFFFFF, mem_table_num_entry))
+        print_out_str('--------')
+
+        for i in range(0, mem_table_num_entry):
+            this_entry = mem_dump_table + dump_table_entry_offset + \
+                i * dump_entry_size
+            entry_id = ram_dump.read_u32(this_entry + dump_entry_id_offset)
+            entry_type = ram_dump.read_u32(this_entry + dump_entry_type_offset)
+            entry_addr = ram_dump.read_word(this_entry + dump_entry_addr_offset)
+
+            if entry_id < 0 or entry_id > len(self.dump_table_id_lookup_table):
+                print_out_str(
+                    '!!! Invalid dump table entry id found {0:x}'.format(entry_id))
+                continue
+
+            if entry_type > len(self.dump_type_lookup_table):
+                print_out_str(
+                    '!!! Invalid dump table entry type found {0:x}'.format(entry_type))
+                continue
+
+            table_version = ram_dump.read_u32(
+                entry_addr + dump_table_version_offset, False)
+            if table_version is None:
+                print_out_str('Dump table entry version is bogus! Can\'t parse debug image')
+                return
+            table_num_entries = ram_dump.read_u32(
+                entry_addr + dump_table_num_entry_offset, False)
+            if table_num_entries is None or table_num_entries > 100:
+                print_out_str('Dump table entry num_entries is bogus! Can\'t parse debug image')
+                return
+
+            print_out_str(
+                'Debug image version: {0}.{1} Entry id: {2} Entry type: {3} Number of entries: {4}'.format(
+                    table_version >> 20, table_version & 0xFFFFF, self.dump_table_id_lookup_table[entry_id],
+                    self.dump_type_lookup_table[entry_type], table_num_entries))
+
+            for j in range(0, table_num_entries):
+                print_out_str('--------')
+                client_entry = entry_addr + dump_table_entry_offset + j * dump_entry_size
+                client_id = ram_dump.read_u32(client_entry + dump_entry_id_offset, False)
+                client_type =  ram_dump.read_u32(client_entry + dump_entry_type_offset, False)
+                client_addr = ram_dump.read_word(client_entry + dump_entry_addr_offset, False)
+
+                if client_id < 0 or client_id > len(self.dump_data_id_lookup_table):
+                    print_out_str(
+                        '!!! Invalid dump client id found {0:x}'.format(client_id))
+                    continue
+
+                if client_type > len(self.dump_type_lookup_table):
+                    print_out_str(
+                        '!!! Invalid dump client type found {0:x}'.format(client_type))
+                    continue
+
+                dump_data_magic = ram_dump.read_u32(client_addr + dump_data_magic_offset, False)
+                dump_data_version = ram_dump.read_u32(client_addr + dump_data_version_offset, False)
+                dump_data_addr = ram_dump.read_dword(client_addr + dump_data_addr_offset, False)
+                dump_data_len = ram_dump.read_dword(client_addr + dump_data_len_offset, False)
+
+                client_name = self.dump_data_id_lookup_table[client_id]
+                if client_name not in client_table:
+                    print_out_str(
+                         '!!! {0} Does not have an associated function. The parser needs to be updated!'.format(client_name))
+                else:
+                    print_out_str('Parsing debug information for {0}. Version: {1} Magic: {2:x}'.format(
+                       client_name, dump_data_version, dump_data_magic))
+
+                    if dump_data_magic is None:
+                        print_out_str(
+                            "!!! Address {0:x} is bogus! Can't parse!".format(start))
+                        continue
+
+                    if dump_data_magic != MEMDUMPV2_MAGIC:
+                        print_out_str(
+                        "!!! Magic {0:x} doesn't match! No context will be parsed".format(dump_data_magic))
+                        continue
+
+                    func = client_table[client_name]
+                    getattr(DebugImage_v2, func)(self, dump_data_addr, dump_data_addr + dump_data_len,
+                                                 client_id, ram_dump)
+
+            self.qdss.dump_all(ram_dump)
diff --git a/linux-ramdump-parser-v2/parsers/debug_image.py b/linux-ramdump-parser-v2/parsers/debug_image.py
index 3354c7f..d5f750a 100644
--- a/linux-ramdump-parser-v2/parsers/debug_image.py
+++ b/linux-ramdump-parser-v2/parsers/debug_image.py
@@ -16,6 +16,7 @@ from print_out import print_out_str
 from qdss import QDSSDump
 from cachedump import save_l1_dump, parse_cache_dump
 from watchdog import TZRegDump
+from debug_image_v2 import DebugImage_v2
 
 QDSS_MAGIC = 0x5D1DB1Bf
 
@@ -126,12 +127,7 @@ class DebugImage(RamParser):
 
         setattr(self.qdss, tag_to_field_name[tag], start + 4096)
 
-    def parse(self):
-        if not self.ramdump.is_config_defined('CONFIG_MSM_MEMORY_DUMP'):
-            print_out_str(
-                '!!! Debug image was not enabled. No debug dump will be provided')
-            return
-
+    def parse_dump(self):
         out_dir = self.ramdump.outdir
         self.name_lookup_table = self.ramdump.gdbmi.get_enum_lookup_table(
             'dump_client_type', 32)
@@ -195,3 +191,18 @@ class DebugImage(RamParser):
             print_out_str('--------')
 
         self.qdss.dump_all(self.ramdump)
+
+    def parse(self):
+        # use the mem_dump_data variable to detect if debug image feature was compiled in,
+        # and memdump data variable for debug image v2 feature, rather than relying on
+        # configuration option.
+        if self.ramdump.addr_lookup('mem_dump_data'):
+            self.parse_dump()
+        elif self.ramdump.addr_lookup('memdump'):
+            regs = DebugImage_v2()
+            regs.parse_dump_v2(self.ramdump)
+        else:
+            print_out_str(
+                '!!! Debug image was not enabled. No debug dump will be provided')
+            return
+
diff --git a/linux-ramdump-parser-v2/qdss.py b/linux-ramdump-parser-v2/qdss.py
index f8b3308..99825ae 100644
--- a/linux-ramdump-parser-v2/qdss.py
+++ b/linux-ramdump-parser-v2/qdss.py
@@ -216,7 +216,7 @@ class QDSSDump():
         for a, b in tmc_registers.iteritems():
             offset, name = b
             tmc_etf_out.write('{0} ({1}): {2:x}\n'.format(
-                a, name, ram_dump.read_word(self.tmc_etf_start + offset, False)))
+                a, name, ram_dump.read_u32(self.tmc_etf_start + offset, False)))
         tmc_etf_out.close()
 
     def print_tmc_etr(self, ram_dump):
@@ -230,7 +230,7 @@ class QDSSDump():
         for a, b in tmc_registers.iteritems():
             offset, name = b
             tmc_etf_out.write('{0} ({1}): {2:x}\n'.format(
-                a, name, ram_dump.read_word(self.tmc_etr_start + offset, False)))
+                a, name, ram_dump.read_u32(self.tmc_etr_start + offset, False)))
         tmc_etf_out.close()
 
     def print_etm_registers(self, ram_dump, base, fname):
@@ -238,7 +238,7 @@ class QDSSDump():
         for a, b in etm_registers.iteritems():
             offset, name = b
             etm_out.write('{0} ({1}): {2:x})\n'.format(
-                a, name, ram_dump.read_word(base + offset * 4, False)))
+                a, name, ram_dump.read_u32(base + offset * 4, False)))
         etm_out.close()
 
     def print_all_etm_register(self, ram_dump):
@@ -275,13 +275,16 @@ class QDSSDump():
 
         ctl_offset, ctl_desc = tmc_registers['CTL']
         mode_offset, mode_desc = tmc_registers['MODE']
+        rsz_offset, rsz_desc = tmc_registers['RSZ']
 
-        ctl = ram_dump.read_word(self.tmc_etf_start + ctl_offset, False)
-        mode = ram_dump.read_word(self.tmc_etf_start + mode_offset, False)
+        ctl = ram_dump.read_u32(self.tmc_etf_start + ctl_offset, False)
+        mode = ram_dump.read_u32(self.tmc_etf_start + mode_offset, False)
+        rsz = ram_dump.read_u32(self.tmc_etf_start + rsz_offset, False)
+        # rsz is given in words so convert to bytes
+        rsz = 4 * rsz
 
         if (ctl & 0x1) == 1 and (mode == 0):
-            # Save the 64kb of data
-            for i in range(0, 64 * 1024):
+            for i in range(0, rsz):
                 val = ram_dump.read_byte(self.etf_start + i, False)
                 tmc_etf.write(struct.pack('<B', val))
         else:
@@ -299,24 +302,24 @@ class QDSSDump():
         ctl_offset, ctl_desc = tmc_registers['CTL']
         mode_offset, mode_desc = tmc_registers['MODE']
 
-        ctl = ram_dump.read_word(self.tmc_etr_start + ctl_offset, False)
-        mode = ram_dump.read_word(self.tmc_etr_start + mode_offset, False)
+        ctl = ram_dump.read_u32(self.tmc_etr_start + ctl_offset, False)
+        mode = ram_dump.read_u32(self.tmc_etr_start + mode_offset, False)
 
         if (ctl & 0x1) == 1 and (mode == 0):
             sts_offset, sts_desc = tmc_registers['STS']
-            sts = ram_dump.read_word(self.tmc_etr_start + sts_offset, False)
+            sts = ram_dump.read_u32(self.tmc_etr_start + sts_offset, False)
 
             dbalo_offset, dbalo_desc = tmc_registers['DBALO']
-            dbalo = ram_dump.read_word(
+            dbalo = ram_dump.read_u32(
                 self.tmc_etr_start + dbalo_offset, False)
 
             rsz_offset, rsz_desc = tmc_registers['RSZ']
-            rsz = ram_dump.read_word(self.tmc_etr_start + rsz_offset, False)
+            rsz = ram_dump.read_u32(self.tmc_etr_start + rsz_offset, False)
             # rsz is given in words so convert to bytes
             rsz = 4 * rsz
 
             rwp_offset, rwp_desc = tmc_registers['RWP']
-            rwp = ram_dump.read_word(self.tmc_etr_start + rwp_offset, False)
+            rwp = ram_dump.read_u32(self.tmc_etr_start + rwp_offset, False)
 
             if (sts & 0x1) == 1:
                 for i in range(rwp, dbalo + rsz):
diff --git a/linux-ramdump-parser-v2/watchdog_v2.py b/linux-ramdump-parser-v2/watchdog_v2.py
new file mode 100644
index 0000000..1ef5e7d
--- /dev/null
+++ b/linux-ramdump-parser-v2/watchdog_v2.py
@@ -0,0 +1,331 @@
+# Copyright (c) 2012-2014, 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 struct
+from print_out import print_out_str
+
+# (name from tz dump, corresponding T32 register, whether or not to print_out_str (the function name))
+sysdbg_cpu64_register_names = [
+    ('x0', 'x0', False),
+    ('x1', 'x1', False),
+    ('x2', 'x2', False),
+    ('x3', 'x3', False),
+    ('x4', 'x4', False),
+    ('x5', 'x5', False),
+    ('x6', 'x6', False),
+    ('x7', 'x7', False),
+    ('x8', 'x8', False),
+    ('x9', 'x9', False),
+    ('x10', 'x10', False),
+    ('x11', 'x11', False),
+    ('x12', 'x12', False),
+    ('x13', 'x13', False),
+    ('x14', 'x14', False),
+    ('x15', 'x15', False),
+    ('x16', 'x16', False),
+    ('x17', 'x17', False),
+    ('x18', 'x18', False),
+    ('x19', 'x19', False),
+    ('x20', 'x20', False),
+    ('x21', 'x21', False),
+    ('x22', 'x22', False),
+    ('x23', 'x23', False),
+    ('x24', 'x24', False),
+    ('x25', 'x25', False),
+    ('x26', 'x26', False),
+    ('x27', 'x27', False),
+    ('x28', 'x28', False),
+    ('x29', 'x29', False),
+    ('x30', 'x30', True),
+    ('pc', 'pc', True),
+    ('currentEL', None, False),
+    ('sp_el3', 'sp_el3', False),
+    ('elr_el3', 'elr_el3', True),
+    ('spsr_el3', 'spsr_el3', False),
+    ('sp_el2', 'sp_el2', False),
+    ('elr_el2', 'elr_el2', True),
+    ('spsr_el2', 'spsr_el2', False),
+    ('sp_el1', 'sp_el1', False),
+    ('elr_el1', 'elr_el1', True),
+    ('spsr_el1', 'spsr_el1', False),
+    ('sp_el0', 'sp_el0', False),
+    ('__reserved1', '__reserved1', False),
+    ('__reserved2', '__reserved2', False),
+    ('__reserved3', '__reserved3', False),
+    ('__reserved4', '__reserved4', False),
+]
+
+sysdbg_cpu64_ctxt_regs_type = ''.join([
+    'Q',  # x0
+    'Q',  # x1
+    'Q',  # x2
+    'Q',  # x3
+    'Q',  # x4
+    'Q',  # x5
+    'Q',  # x6
+    'Q',  # x7
+    'Q',  # x8
+    'Q',  # x9
+    'Q',  # x10
+    'Q',  # x11
+    'Q',  # x12
+    'Q',  # x13
+    'Q',  # x14
+    'Q',  # x15
+    'Q',  # x16
+    'Q',  # x17
+    'Q',  # x18
+    'Q',  # x19
+    'Q',  # x20
+    'Q',  # x21
+    'Q',  # x22
+    'Q',  # x23
+    'Q',  # x24
+    'Q',  # x25
+    'Q',  # x26
+    'Q',  # x27
+    'Q',  # x28
+    'Q',  # x29
+    'Q',  # x30
+    'Q',  # pc
+    'Q',  # currentEL
+    'Q',  # sp_el3
+    'Q',  # elr_el3
+    'Q',  # spsr_el3
+    'Q',  # sp_el2
+    'Q',  # elr_el2
+    'Q',  # spsr_el2
+    'Q',  # sp_el1
+    'Q',  # elr_el1
+    'Q',  # spsr_el1
+    'Q',  # sp_el0
+    'Q',  # __reserved1
+    'Q',  # __reserved2
+    'Q',  # __reserved3
+    'Q',  # __reserved4
+])
+
+sysdbg_cpu32_register_names = [
+    ('r0', 'r0', False),
+    ('r1', 'r1', False),
+    ('r2', 'r2', False),
+    ('r3', 'r3', False),
+    ('r4', 'r4', False),
+    ('r5', 'r5', False),
+    ('r6', 'r6', False),
+    ('r7', 'r7', False),
+    ('r8', 'r8', False),
+    ('r9', 'r9', False),
+    ('r10', 'r10', False),
+    ('r11', 'r11', False),
+    ('r12', 'r12', False),
+    ('r13_usr', 'r13_usr', False),
+    ('r14_usr', 'r14_usr', False),
+    ('r13_hyp', 'r13_hyp', False),
+    ('r14_irq', 'r14_irq', True),
+    ('r13_irq', 'r13_irq', False),
+    ('r14_svc', 'r14_svc', True),
+    ('r13_svc', 'r13_svc', False),
+    ('r14_abt', 'r14_abt', True),
+    ('r13_abt', 'r13_abt', False),
+    ('r14_und', 'r14_und', True),
+    ('r13_und', 'r13_und', False),
+    ('r8_fiq', 'r8_fiq', False),
+    ('r9_fiq', 'r9_fiq', False),
+    ('r10_fiq', 'r10_fiq', False),
+    ('r11_fiq', 'r11_fiq', False),
+    ('r12_fiq', 'r12_fiq', False),
+    ('r13_fiq', 'r13_fiq', False),
+    ('r14_fiq', 'r14_fiq', True),
+    ('pc', 'pc', True),
+    ('cpsr', 'cpsr', False),
+    ('r13_mon', 'r13_mon', False),
+    ('r14_mon', 'r14_mon', True),
+    ('r14_hyp', 'r14_hyp', True),
+    ('_reserved', '_reserved', False),
+    ('__reserved1', '__reserved1', False),
+    ('__reserved2', '__reserved2', False),
+    ('__reserved3', '__reserved3', False),
+    ('__reserved4', '__reserved4', False),
+]
+
+sysdbg_cpu32_ctxt_regs_type = ''.join([
+    'Q',  # r0
+    'Q',  # r1
+    'Q',  # r2
+    'Q',  # r3
+    'Q',  # r4
+    'Q',  # r5
+    'Q',  # r6
+    'Q',  # r7
+    'Q',  # r8
+    'Q',  # r9
+    'Q',  # r10
+    'Q',  # r11
+    'Q',  # r12
+    'Q',  # r13_usr
+    'Q',  # r14_usr
+    'Q',  # r13_hyp
+    'Q',  # r14_irq
+    'Q',  # r13_irq
+    'Q',  # r14_svc
+    'Q',  # r13_svc
+    'Q',  # r14_abt
+    'Q',  # r13_abt
+    'Q',  # r14_und
+    'Q',  # r13_und
+    'Q',  # r8_fiq
+    'Q',  # r9_fiq
+    'Q',  # r10_fiq
+    'Q',  # r11_fiq
+    'Q',  # r12_fiq
+    'Q',  # r13_fiq
+    'Q',  # r14_fiq
+    'Q',  # pc
+    'Q',  # cpsr
+    'Q',  # r13_mon
+    'Q',  # r14_mon
+    'Q',  # r14_hyp
+    'Q',  # _reserved
+    'Q',  # __reserved1
+    'Q',  # __reserved2
+    'Q',  # __reserved3
+    'Q',  # __reserved4
+])
+
+cpu_name = (
+    'Invalid',
+    'A53',
+    'A57',
+    'Hydra',
+)
+
+class TZCpuCtx_v2():
+
+    def __init__(self, regs_t, ramdump):
+        i = 0
+        self.regs = {}
+        for r in regs_t:
+            if ramdump.arm64:
+                self.regs[sysdbg_cpu64_register_names[i][0]] = r
+            else:
+                self.regs[sysdbg_cpu32_register_names[i][0]] = r
+            i += 1
+
+    def print_regs(self, outfile, ramdump):
+        if ramdump.arm64:
+            register_names = sysdbg_cpu64_register_names
+        else:
+            register_names = sysdbg_cpu32_register_names
+        for reg_name, t32_name, print_pc in register_names:
+            if print_pc:
+                a = ramdump.unwind_lookup(self.regs[reg_name])
+                if a is not None:
+                    symname, offset = ramdump.unwind_lookup(
+                        self.regs[reg_name])
+                    pc_string = '[{0}+0x{1:x}]'.format(symname, offset)
+                else:
+                    pc_string = None
+            else:
+                pc_string = None
+            if pc_string is not None:
+                print_out_str('   {0:8} = 0x{1:016x} {2}'.format(
+                    reg_name, self.regs[reg_name], pc_string))
+            else:
+                print_out_str('   {0:8} = 0x{1:016x}'.format(
+                    reg_name, self.regs[reg_name]))
+            if t32_name is not None:
+                outfile.write(
+                    'r.s {0} 0x{1:x}\n'.format(t32_name, self.regs[reg_name]))
+
+class TZRegDump_v2():
+
+    def __init__(self):
+        self.core_regs = None
+        self.sec_regs = None
+        self.start_addr = 0
+        self.end_addr = 0
+        self.core = 0
+	self.status = []
+
+    def dump_all_regs(self, ram_dump):
+        coren_regs = ram_dump.open_file('core{0}_regs.cmm'.format(self.core))
+
+        print_out_str('core{0} regs:'.format(self.core))
+        self.core_regs.print_regs(coren_regs, ram_dump)
+        coren_regs.close()
+
+        secure_regs = ram_dump.open_file('secure_world_core{0}_regs.cmm'.format(self.core))
+        print_out_str('\n=============== secure contex ===========')
+        self.sec_regs.print_regs(secure_regs, ram_dump)
+        print_out_str('============ end secure context ===========')
+        secure_regs.close()
+
+    def dump_core_pc(self, ram_dump):
+        print ''
+        pc = self.core_regs.regs['pc']
+        if ram_dump.arm64:
+            lr = self.core_regs.regs['elr_el1']
+            bt = self.core_regs.regs['sp_el1']
+        else:
+            lr = self.core_regs.regs['r14_svc']
+            bt = self.core_regs.regs['r13_svc']
+
+        a = ram_dump.unwind_lookup(pc)
+        if a is not None:
+            symname, offset = a
+        else:
+            symname = 'UNKNOWN'
+            offset = 0
+        print_out_str(
+            'Core {3} PC: {0}+{1:x} <{2:x}>'.format(symname, offset, pc, self.core))
+        a = ram_dump.unwind_lookup(lr)
+        if a is not None:
+            symname, offset = a
+        else:
+            symname = 'UNKNOWN'
+            offset = 0
+        print_out_str(
+            'Core {3} LR: {0}+{1:x} <{2:x}>'.format(symname, offset, lr, self.core))
+        print_out_str('')
+        ram_dump.unwind.unwind_backtrace(bt, 0, pc, lr, '')
+        print_out_str('')
+
+    def init_regs(self, start_addr, end_addr, core, ram_dump):
+        self.start_addr = start_addr
+        self.end_addr = end_addr
+        self.core = core
+
+        # uint32 status[4]; -- status fields
+        # sdi_cpu_ctxt_regs_type cpu_regs; -- ctxt for all cpus
+        # sdi_cpu_ctxt_regs_type __reserved3; -- secure ctxt
+        for i in range(0, 4):
+            self.status.append(ram_dump.read_u32(self.start_addr, False))
+            self.start_addr += 4
+
+        if ram_dump.arm64:
+            sc_regs = ram_dump.read_string(
+                self.start_addr, sysdbg_cpu64_ctxt_regs_type, False)
+            self.start_addr += struct.calcsize(sysdbg_cpu64_ctxt_regs_type)
+            sc_secure = ram_dump.read_string(
+               self.start_addr, sysdbg_cpu64_ctxt_regs_type , False)
+            self.start_addr += struct.calcsize(sysdbg_cpu64_ctxt_regs_type)
+        else:
+            sc_regs = ram_dump.read_string(
+                self.start_addr, sysdbg_cpu32_ctxt_regs_type, False)
+            self.start_addr += struct.calcsize(sysdbg_cpu32_ctxt_regs_type)
+            sc_secure = ram_dump.read_string(
+                self.start_addr, sysdbg_cpu32_ctxt_regs_type , False)
+            self.start_addr += struct.calcsize(sysdbg_cpu32_ctxt_regs_type)
+
+        self.core_regs = TZCpuCtx_v2(sc_regs, ram_dump)
+        self.sec_regs = TZCpuCtx_v2(sc_secure, ram_dump)
+        return True
-- 
GitLab