diff --git a/linux-ramdump-parser-v2/README b/linux-ramdump-parser-v2/README
index 84993be6db794deadcb6770e0fd9595329fa77a7..efeea31b704496bf2a433ad2decd78694b32158a 100644
--- a/linux-ramdump-parser-v2/README
+++ b/linux-ramdump-parser-v2/README
@@ -92,6 +92,13 @@ gdb64_path - absolute path to the 64-bit gdb tool for the ramdumps
 nm64_path - absolute path to the 64-bit nm tool for the ramdumps
 qtf_path - absolute path to qtf tool executable
 scandump_parser_path - absolute path to scandump parser for the ramdumps
+crashtool - absolute path to the 'crash' tool that is able to provide
+	    gdb like debugging and also host an extension that extracts
+	    ftrace
+trace_ext - shared library extension that allows the 'crash' tool to read
+	    raw ftrace data from a ramdump and dump it into a binary format
+tracecmdtool - absolute path to the trace-cmd tool that converts the binary
+	       trace format created by trace_ext to human readable ftrace
 
 Note that local_settings.py is just a python file so the file may take advantage
 of python features.
diff --git a/linux-ramdump-parser-v2/aarch64iommulib.py b/linux-ramdump-parser-v2/aarch64iommulib.py
old mode 100755
new mode 100644
index de13e0bec26b29337b38a408ae584d7d9e091228..f14a9b4ec17a8c5c0a2180eb6589f3868b37c818
--- a/linux-ramdump-parser-v2/aarch64iommulib.py
+++ b/linux-ramdump-parser-v2/aarch64iommulib.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2016, The Linux Foundation. All rights reserved.
+# Copyright (c) 2016-2017, 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
@@ -28,26 +28,42 @@ LL_PAGE_MASK = 0xFFFFFFFFF000
 
 LL_AP_BITS = (0x3 << 6)
 LL_CH = (0x1 << 52)
+LL_XN = (0x1 << 54)
+LL_ATTR_INDX = (0x7 << 2)
+LL_SH_BITS = (0x3 << 8)
+
+ATTR_IDX_NONCACHED = 0x0
+ATTR_IDX_CACHE = 0x1
+ATTR_IDX_DEV = 0x2
+
+SH_NON_SHARE = (0x0 << 8)
+SH_RESERVED = (0x1 << 8)
+SH_OUTER_SHARE = (0x2 << 8)
+SH_INNER_SHARE = (0x3 << 8)
 
 LL_AP_RO = (0x3 << 6)
 LL_AP_RW = (0x1 << 6)
 LL_AP_PR_RW = (0x0 << 6)
 LL_AP_PR_RO = (0x2 << 6)
 
-
 class FlatMapping(object):
 
-    def __init__(self, virt, phys=-1, type='[]', size=SZ_4K, mapped=False):
+    def __init__(self, virt, phys=-1, type='[]', size=SZ_4K, attr_indx_str='[]',
+                shareability_str='[]', execute_never_str='[]', mapped=False):
         self.virt = virt
         self.phys = phys
         self.type = type
         self.map_size = size
+        self.attr_indx_str = attr_indx_str
+        self.shareability_str = shareability_str
+        self.execute_never_str = execute_never_str
         self.mapped = mapped
 
 
 class CollapsedMapping(object):
     def __init__(self, virt_start, virt_end, phys_start=-1, phys_end=-1,
-                 map_type='[]', map_size=SZ_4K, mapped=False):
+                map_type='[]', map_size=SZ_4K, attr_indx_str='[]',
+                shareability_str='[]', execute_never_str='[]', mapped=False):
 
         self.virt_start = virt_start
         self.virt_end = virt_end - 1
@@ -55,13 +71,18 @@ class CollapsedMapping(object):
         self.phys_end = phys_end - 1
         self.map_type = map_type
         self.map_size = map_size
+        self.attr_indx_str = attr_indx_str
+        self.shareability_str = shareability_str
+        self.execute_never_str = execute_never_str
         self.mapped = mapped
 
 
 def add_collapsed_mapping(mappings, virt_start, virt_end, phys_start, phys_end,
-                          map_type, map_size, mapped):
+                          map_type, map_size, attr_indx_str, shareability_str,
+                          execute_never_str, mapped):
     map = CollapsedMapping(virt_start, virt_end, phys_start, phys_end,
-                           map_type, map_size, mapped)
+                           map_type, map_size, attr_indx_str, shareability_str,
+                           execute_never_str, mapped)
 
     if virt_start not in mappings:
         mappings[virt_start] = map
@@ -101,7 +122,9 @@ def create_collapsed_mapping(flat_mapping):
                     collapsed_mapping, start_map.virt,
                     map.virt, start_map.phys,
                     start_map.phys + start_map.map_size,
-                    start_map.type, start_map.map_size, start_map.mapped)
+                    start_map.type, start_map.map_size, map.attr_indx_str,
+                    map.shareability_str, map.execute_never_str,
+                    start_map.mapped)
                 start_map = map
 
             elif last_mapping:
@@ -109,14 +132,17 @@ def create_collapsed_mapping(flat_mapping):
                     collapsed_mapping, start_map.virt,
                     0xFFFFFFFFFFFF + 1, start_map.phys,
                     start_map.phys + start_map.map_size,
-                    start_map.type, start_map.map_size, start_map.mapped)
+                    start_map.type, start_map.map_size, map.attr_indx_str,
+                    map.shareability_str, map.execute_never_str,
+                    start_map.mapped)
 
             prev_map = map
     return collapsed_mapping
 
 
-def add_flat_mapping(mappings, fl_idx, sl_idx, tl_idx, ll_idx,
-                     phy_addr, map_type, page_size, mapped):
+def add_flat_mapping(mappings, fl_idx, sl_idx, tl_idx, ll_idx, phy_addr,
+                    map_type, page_size, attr_indx, shareability,
+                    xn_bit, mapped):
     virt = (fl_idx << 39) | (sl_idx << 30) | (tl_idx << 21) | (ll_idx << 12)
     map_type_str = '[R/W]'
 
@@ -127,7 +153,37 @@ def add_flat_mapping(mappings, fl_idx, sl_idx, tl_idx, ll_idx,
     elif map_type == LL_AP_PR_RO:
         map_type_str = '[P RO]'
 
-    map = FlatMapping(virt, phy_addr, map_type_str, page_size, mapped)
+    if shareability != -1:
+        if shareability == SH_NON_SHARE:
+            shareability_str = 'Non-Shareable'
+        if shareability == SH_RESERVED:
+            shareability_str = 'Reserved'
+        if shareability == SH_OUTER_SHARE:
+            shareability_str = 'Outer-Shareable'
+        if shareability == SH_INNER_SHARE:
+            shareability_str = 'Inner-Shareable'
+    else:
+        shareability_str = 'N/A'
+
+    if attr_indx != -1:
+        if attr_indx == ATTR_IDX_NONCACHED:
+            attr_indx_str = 'Non-Cached'
+        if attr_indx == ATTR_IDX_CACHE:
+            attr_indx_str = 'Cached'
+        if attr_indx == ATTR_IDX_DEV:
+            attr_indx_str = 'Device'
+    else:
+        attr_indx_str = 'N/A'
+
+    if xn_bit == 1:
+        execute_never_str = 'True'
+    elif xn_bit == 0:
+        execute_never_str = 'False'
+    elif xn_bit == -1:
+        execute_never_str = 'N/A'
+
+    map = FlatMapping(virt, phy_addr, map_type_str, page_size, attr_indx_str,
+                      shareability_str, execute_never_str, mapped)
 
     if virt not in mappings:
         mappings[virt] = map
@@ -153,7 +209,6 @@ def get_super_section_mapping_info(ramdump, pg_table, index):
 
     return (current_phy_addr, current_page_size, current_map_type, status)
 
-
 def get_section_mapping_info(ramdump, pg_table, index):
     phy_addr = ramdump.read_u64(pg_table, False)
     current_phy_addr = -1
@@ -161,10 +216,22 @@ def get_section_mapping_info(ramdump, pg_table, index):
     current_map_type = 0
     status = True
     section_skip_count = 0
+    attr_indx = 0
+    sh_bits = -1
+    xn_bit = 0
+
 
     if phy_addr is not None:
         current_map_type = phy_addr & LL_AP_BITS
 
+        attr_indx = ( (phy_addr & LL_ATTR_INDX) >> 2 )
+        if attr_indx == ATTR_IDX_NONCACHED or attr_indx == ATTR_IDX_CACHE:
+            sh_bits = phy_addr & LL_SH_BITS   # Shareability info available
+                                              # only for Normal Memory
+
+        if phy_addr & LL_XN:
+            xn_bit = 1
+
         if phy_addr & LL_CH:
             current_phy_addr = phy_addr & 0xFFFFFE000000
             current_page_size = SZ_32M
@@ -175,7 +242,7 @@ def get_section_mapping_info(ramdump, pg_table, index):
             current_page_size = SZ_2M
 
     return (current_phy_addr, current_page_size, current_map_type,
-            status, section_skip_count)
+            status, section_skip_count, attr_indx, sh_bits, xn_bit)
 
 
 def get_mapping_info(ramdump, pg_table, index):
@@ -186,12 +253,23 @@ def get_mapping_info(ramdump, pg_table, index):
     current_map_type = 0
     status = True
     skip_count = 0
+    attr_indx = 0
+    sh_bits = -1
+    xn_bit = 0
 
     if phy_addr is not None:
         current_map_type = phy_addr & LL_AP_BITS
 
         if phy_addr & LL_TYPE_PAGE:
             current_phy_addr = phy_addr & 0xFFFFFFFFF000
+            attr_indx = ( (phy_addr & LL_ATTR_INDX) >> 2 )
+            if attr_indx == ATTR_IDX_NONCACHED or attr_indx == ATTR_IDX_CACHE:
+                sh_bits = phy_addr & LL_SH_BITS   # Shareability info available
+                                                  # only for Normal Memory
+
+            if phy_addr & LL_XN:
+                xn_bit = 1
+
             if phy_addr & LL_CH:
                 current_phy_addr = phy_addr & 0xFFFFFFFF0000
                 current_page_size = SZ_64K
@@ -203,7 +281,7 @@ def get_mapping_info(ramdump, pg_table, index):
             current_phy_addr = phy_addr
             status = False
     return (current_phy_addr, current_page_size, current_map_type,
-            status, skip_count)
+            status, skip_count, attr_indx, sh_bits, xn_bit)
 
 
 def fl_entry(ramdump, fl_pte, skip_fl):
@@ -233,7 +311,7 @@ def parse_2nd_level_table(ramdump, sl_pg_table_entry, fl_index,
             tmp_mapping = add_flat_mapping(
                           tmp_mapping, fl_index, sl_index,
                           tl_index, 0, -1,
-                          -1, SZ_2M, False)
+                          -1, SZ_2M, -1, -1, -1, False)
             tl_pte += 8
             continue
 
@@ -248,41 +326,37 @@ def parse_2nd_level_table(ramdump, sl_pg_table_entry, fl_index,
                     continue
 
                 (phy_addr, page_size, map_type, status,
-                    skip_count) = get_mapping_info(
-                                                ramdump, ll_pte,
-                                                ll_index)
+                    skip_count, attr_indx, shareability,
+                    xn_bit) = get_mapping_info(ramdump, ll_pte, ll_index)
 
                 if status and phy_addr != -1:
                     tmp_mapping = add_flat_mapping(
                         tmp_mapping, fl_index, sl_index,
-                        tl_index, ll_index, phy_addr,
-                        map_type, page_size, True)
+                        tl_index, ll_index, phy_addr, map_type,
+                        page_size, attr_indx, shareability, xn_bit, True)
                 else:
                     tmp_mapping = add_flat_mapping(
                         tmp_mapping, fl_index, sl_index,
                         tl_index, ll_index, -1,
-                        -1, page_size, False)
+                        -1, page_size, attr_indx, shareability, xn_bit, False)
 
         elif tl_entry_type == FLSL_TYPE_BLOCK:
             if section_skip_count:
                 section_skip_count -= 1
                 continue
 
-            (phy_addr, page_size,
-                map_type, status,
-                section_skip_count) = get_section_mapping_info(
-                                          ramdump, tl_pte, tl_index)
-
+            (phy_addr, page_size, map_type, status,
+                section_skip_count, attr_indx, shareability,
+                xn_bit) = get_section_mapping_info(ramdump, tl_pte, tl_index)
             if status and phy_addr != -1:
                 tmp_mapping = add_flat_mapping(
                     tmp_mapping, fl_index, sl_index,
                     tl_index, 0, phy_addr,
-                    map_type, page_size, True)
+                    map_type, page_size, attr_indx, shareability, xn_bit, True)
 
         tl_pte += 8
     return tmp_mapping
 
-
 def create_flat_mappings(ramdump, pg_table, level):
     tmp_mapping = {}
     fl_pte = pg_table
@@ -307,7 +381,7 @@ def create_flat_mappings(ramdump, pg_table, level):
         if fl_pg_table_entry == 0:
             tmp_mapping = add_flat_mapping(
                                         tmp_mapping, fl_index, 0, 0, 0,
-                                        -1, -1, SZ_256G, False)
+                                        -1, -1, SZ_256G, -1, -1, -1, False)
             fl_pte += 8
             continue
 
@@ -318,7 +392,7 @@ def create_flat_mappings(ramdump, pg_table, level):
             if sl_pg_table_entry == 0 or sl_pg_table_entry is None:
                 tmp_mapping = add_flat_mapping(tmp_mapping,
                                                fl_index, sl_index, 0, 0,
-                                               -1, -1, SZ_1G, False)
+                                               -1, -1, SZ_1G, -1, -1, -1, False)
                 sl_pte += 8
                 continue
 
@@ -332,9 +406,10 @@ def create_flat_mappings(ramdump, pg_table, level):
                     = get_super_section_mapping_info(ramdump, sl_pte, sl_index)
 
                 if status and phy_addr != -1:
+                    #TODO: Fix memory attributes for 2nd-level entry
                     tmp_mapping = add_flat_mapping(
                         tmp_mapping, fl_index, sl_index, 0, 0,
-                        phy_addr, map_type, page_size, True)
+                        phy_addr, map_type, page_size, -1, -1, -1, True)
 
             sl_pte += 8
         fl_pte += 8
@@ -355,12 +430,13 @@ def parse_aarch64_tables(ramdump, d, domain_num):
         iommu_context = iommu_context or 'None attached'
 
         outfile.write(
-            'IOMMU Context: %s. Domain: %s'
+            'IOMMU Contextttt: %s. Domain: %s'
             '[L2 cache redirect for page tables is %s]\n' % (
                 iommu_context, d.client_name, redirect))
         outfile.write(
             '[VA Start -- VA End  ] [Size      ] [PA Start   -- PA End  ] '
-            '[Attributes][Page Table Entry Size]\n')
+            '[Attributes][Page Table Entry Size] [Memory Type] '
+            '[Shareability] [Non-Executable] \n')
         if d.pg_table == 0:
             outfile.write(
                 'No Page Table Found. (Probably a secure domain)\n')
@@ -373,11 +449,14 @@ def parse_aarch64_tables(ramdump, d, domain_num):
 
                 if mapping.mapped:
                     outfile.write(
-                        '0x%x--0x%x [0x%x] A:0x%x--0x%x [0x%x] %s[%s] \n' %
+                        '0x%x--0x%x [0x%x] A:0x%x--0x%x [0x%x] %s[%s] [%s] '
+                        '[%s] [%s]\n' %
                         (mapping.virt_start, mapping.virt_end,
                          mapping.map_size, mapping.phys_start,
                          mapping.phys_end, mapping.map_size, mapping.map_type,
-                         order_size_strings[get_order(mapping.map_size)]))
+                         order_size_strings[get_order(mapping.map_size)],
+                         mapping.attr_indx_str, mapping.shareability_str,
+                         mapping.execute_never_str))
                 else:
                     outfile.write(
                         '0x%x--0x%x [0x%x] [UNMAPPED]\n' %
diff --git a/linux-ramdump-parser-v2/boards.py b/linux-ramdump-parser-v2/boards.py
index 79c385f49f1e66e6a61788c434c3d8a56f4f3bad..3909b106623b8774ad99ede4b8d907230b00d093 100755
--- a/linux-ramdump-parser-v2/boards.py
+++ b/linux-ramdump-parser-v2/boards.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2014-2016, The Linux Foundation. All rights reserved.
+# Copyright (c) 2014-2017, 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
@@ -415,6 +415,20 @@ class BoardCobalt(Board):
         self.wdog_addr = 0x146BF658
         self.imem_file_name = 'OCIMEM.BIN'
 
+class BoardSDM845(Board):
+    def __init__(self, socid):
+        super(BoardSDM845, self).__init__()
+        self.socid = socid
+        self.board_num = "sdm845"
+        self.cpu = 'CORTEXA53'
+        self.ram_start = 0x80000000
+        self.smem_addr = 0x6000000
+        self.phys_offset = 0x80000000
+        self.imem_start = 0x14680000
+        self.kaslr_addr = 0x146bf6d0
+        self.wdog_addr = 0x146BF658
+        self.imem_file_name = 'OCIMEM.BIN'
+
 class Board8998(Board):
     def __init__(self, socid):
         super(Board8998, self).__init__()
@@ -439,6 +453,7 @@ class Board660(Board):
         self.smem_addr = 0x6000000
         self.phys_offset = 0x80000000
         self.imem_start = 0x14680000
+        self.kaslr_addr = 0x146bf6d0
         self.wdog_addr = 0x146BF658
         self.imem_file_name = 'OCIMEM.BIN'
 
@@ -452,6 +467,7 @@ class Board630(Board):
         self.smem_addr = 0x6000000
         self.phys_offset = 0x80000000
         self.imem_start = 0x14680000
+        self.kaslr_addr = 0x146bf6d0
         self.wdog_addr = 0x146BF658
         self.imem_file_name = 'OCIMEM.BIN'
 
@@ -665,6 +681,8 @@ boards.append(Board660(socid=326))
 boards.append(Board630(socid=318))
 boards.append(Board630(socid=327))
 
+boards.append(BoardSDM845(socid=321))
+
 def get_supported_boards():
     """ Called by other part of the code to get a list of boards """
     return boards
diff --git a/linux-ramdump-parser-v2/cachedumplib.py b/linux-ramdump-parser-v2/cachedumplib.py
old mode 100755
new mode 100644
index d6568940a26e451978584a2a60658f8b70be809f..18b43e8c483134c27fa9e8c6fcd46c66555d2705
--- a/linux-ramdump-parser-v2/cachedumplib.py
+++ b/linux-ramdump-parser-v2/cachedumplib.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2015-2016, The Linux Foundation. All rights reserved.
+# Copyright (c) 2015-2017, 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
@@ -431,6 +431,181 @@ class L1_ICache_KRYO2XX_GOLD(CacheDumpType_v1):
         output.append(n)
         output.append(addr)
 
+class L1_DCache_KRYO3XX_SILVER(CacheDumpType_v1):
+    """Refer to documentation:ad003_atrm"""
+    def __init__(self):
+        super(L1_DCache_KRYO3XX_SILVER, self).__init__()
+        self.tableformat.addColumn('MESI')
+        self.tableformat.addColumn('Tag Address [39:12]')
+        self.tableformat.addColumn('NS')
+        self.tableformat.addColumn('Outer Allocation Hint')
+        self.unsupported_header_offset = 0
+        self.TagSize = 2
+        self.LineSize = 16
+        self.NumSets = 0x80
+        self.NumWays = 4
+
+    def MESI_to_string(MESI_d):
+        if MESI_d == 0:
+            return 'I'
+        elif MESI_d == 1:
+            return 'S'
+        elif MESI_d == 2:
+            return 'E'
+        else:
+            return 'M'
+
+    def parse_tag_fn(self, output, data, nset, nway):
+        if self.TagSize != 2:
+            raise Exception('cache tag size mismatch')
+
+        MESI_d = (data[1] >> 30) & 0x3
+        addr = (data[1] >> 1) & 0xfffffff
+        ns = (data[1] >> 29) & 0x1
+        alloc_hint = data[0] & 0x1
+
+        mesi = self.MESI_to_string(MESI_d)
+        output.append(mesi)
+        output.append(addr)
+        output.append(ns)
+        output.append(alloc_hint)
+
+class L1_ICache_KRYO3XX_SILVER(CacheDumpType_v1):
+    """Refer to documentation:ad003_atrm"""
+    def __init__(self):
+        super(L1_ICache_KRYO3XX_SILVER, self).__init__()
+        self.tableformat.addColumn('Valid and set mode')
+        self.tableformat.addColumn('NS')
+        self.tableformat.addColumn('Tag address')
+        self.unsupported_header_offset = 0
+        self.TagSize = 2
+        self.LineSize = 16
+        self.NumSets = 0x80
+        self.NumWays = 4
+
+    def valid_to_string(valid_d):
+        if valid_d == 0:
+            return 'A32'
+        elif valid_d == 1:
+            return 'T32'
+        elif valid_d == 2:
+            return 'A64'
+        else:
+            return 'Invalid'
+
+    def parse_tag_fn(self, output, data, nset, nway):
+        if self.TagSize != 2:
+            raise Exception('cache tag size mismatch')
+
+        valid_d = (data[0] >> 29) & 0x3
+        ns = (data[0] >> 28) & 0x1
+        addr = data[0] & 0xfffffff
+
+        set_mode = self.valid_to_string(valid_d)
+        output.append(set_mode)
+        output.append(ns)
+        output.append(addr)
+
+class L1_DCache_KRYO3XX_GOLD(CacheDumpType_v1):
+    """Refer to documentation:ad003_atrm"""
+    def __init__(self):
+        super(L1_DCache_KRYO3XX_GOLD, self).__init__()
+        self.tableformat.addColumn('PA [43:12]')
+        self.tableformat.addColumn('MESI')
+        self.unsupported_header_offset = 0
+        self.TagSize = 3
+        self.LineSize = 16
+        self.NumSets = 0x40
+        self.NumWays = 16
+
+    def MESI_to_string(MESI_d):
+        if MESI_d == 0:
+            return 'I'
+        elif MESI_d == 1:
+            return 'S'
+        elif MESI_d == 2:
+            return 'E'
+        else:
+            return 'M'
+
+    def parse_tag_fn(self, output, data, nset, nway):
+        if self.TagSize != 3:
+            raise Exception('cache tag size mismatch')
+
+        addr_lower = (data[0] >> 10) & 0x3fffff
+        addr_higher = data[1] & 0x3ff
+        mesi_d = (data[0] >> 2) & 0x3
+
+        addr = (addr_higher << 22) | addr_lower
+        mesi = MESI_to_string(mesi_d)
+        output.append(addr)
+        output.append(mesi)
+
+
+class L1_ICache_KRYO3XX_GOLD(CacheDumpType_v1):
+    """Refer to documentation:ad003_atrm"""
+    def __init__(self):
+        super(L1_ICache_KRYO3XX_GOLD, self).__init__()
+        self.tableformat.addColumn('Valid and set mode')
+        self.tableformat.addColumn('NS')
+        self.tableformat.addColumn('Tag address')
+        self.unsupported_header_offset = 0
+        self.TagSize = 2
+        self.LineSize = 16
+        self.NumSets = 0x100
+        self.NumWays = 4
+
+    def parse_tag_fn(self, output, data, nset, nway):
+        if self.TagSize != 2:
+            raise Exception('cache tag size mismatch')
+
+        valid = (data[0] >> 29) & 0x1
+        ns = (data[0] >> 28) & 0x1
+        addr = data[0] & 0xfffffff
+
+        output.append(valid)
+        output.append(ns)
+        output.append(addr)
+
+class LLC_SYSTEM_CACHE_KRYO3XX(CacheDumpType_v1):
+    """Refer to documentation:LLC_HDD"""
+    def __init__(self):
+        super(LLC_SYSTEM_CACHE_KRYO3XX, self).__init__()
+        self.tableformat.addColumn('G0 Valid')
+        self.tableformat.addColumn('G0 Dirty')
+        self.tableformat.addColumn('G1 Valid')
+        self.tableformat.addColumn('G1 Dirty')
+        self.tableformat.addColumn('SCID')
+        self.tableformat.addColumn('ECC')
+        self.tableformat.addColumn('Tag address')
+        self.unsupported_header_offset = 0
+        self.TagSize = 2
+        self.LineSize = 16
+        self.NumSets = 0x400
+        self.NumWays = 12
+
+    def parse_tag_fn(self, output, data, nset, nway):
+        if self.TagSize != 2:
+            raise Exception('cache tag size mismatch')
+
+        G0_valid = data[0] & 0x1
+        G1_valid = (data[0] >> 2) & 0x1
+        G0_dirty = (data[0] >> 3) & 0x1
+        G1_dirty = (data[0] >> 4) & 0x1
+        SCID = (data[0] >> 7) & 0x1f
+        ECC_bits = (data[0] >> 14) & 0x7f
+
+        DONE_bit = (data[1] >> 28) & 0x1
+        addr = data[1] & 0x3fffffff
+
+        output.append(G0_valid)
+        output.append(G0_dirty)
+        output.append(G1_valid)
+        output.append(G1_dirty)
+        output.append(SCID)
+        output.append(ECC_bits)
+        output.append(addr)
+
 L1_DCache_KRYO2XX_SILVER = L1_DCache_A53
 L1_ICache_KYRO2XX_SILVER = L1_ICache_A53
 
@@ -454,6 +629,32 @@ lookuptable[("8998", 0x65, 0x14)] = L1_ICache_KRYO2XX_GOLD()
 lookuptable[("8998", 0x66, 0x14)] = L1_ICache_KRYO2XX_GOLD()
 lookuptable[("8998", 0x67, 0x14)] = L1_ICache_KRYO2XX_GOLD()
 
+# "sdm845"
+lookuptable[("sdm845", 0x80, 0x14)] = L1_DCache_KRYO3XX_SILVER()
+lookuptable[("sdm845", 0x81, 0x14)] = L1_DCache_KRYO3XX_SILVER()
+lookuptable[("sdm845", 0x82, 0x14)] = L1_DCache_KRYO3XX_SILVER()
+lookuptable[("sdm845", 0x83, 0x14)] = L1_DCache_KRYO3XX_SILVER()
+lookuptable[("sdm845", 0x84, 0x14)] = L1_DCache_KRYO3XX_GOLD()
+lookuptable[("sdm845", 0x85, 0x14)] = L1_DCache_KRYO3XX_GOLD()
+lookuptable[("sdm845", 0x86, 0x14)] = L1_DCache_KRYO3XX_GOLD()
+lookuptable[("sdm845", 0x87, 0x14)] = L1_DCache_KRYO3XX_GOLD()
+
+
+lookuptable[("sdm845", 0x60, 0x14)] = L1_ICache_KRYO3XX_SILVER()
+lookuptable[("sdm845", 0x61, 0x14)] = L1_ICache_KRYO3XX_SILVER()
+lookuptable[("sdm845", 0x62, 0x14)] = L1_ICache_KRYO3XX_SILVER()
+lookuptable[("sdm845", 0x63, 0x14)] = L1_ICache_KRYO3XX_SILVER()
+lookuptable[("sdm845", 0x64, 0x14)] = L1_ICache_KRYO3XX_GOLD()
+lookuptable[("sdm845", 0x65, 0x14)] = L1_ICache_KRYO3XX_GOLD()
+lookuptable[("sdm845", 0x66, 0x14)] = L1_ICache_KRYO3XX_GOLD()
+lookuptable[("sdm845", 0x67, 0x14)] = L1_ICache_KRYO3XX_GOLD()
+
+
+lookuptable[("sdm845", 0x121, 0x14)] = LLC_SYSTEM_CACHE_KRYO3XX()
+lookuptable[("sdm845", 0x122, 0x14)] = LLC_SYSTEM_CACHE_KRYO3XX()
+lookuptable[("sdm845", 0x123, 0x14)] = LLC_SYSTEM_CACHE_KRYO3XX()
+lookuptable[("sdm845", 0x124, 0x14)] = LLC_SYSTEM_CACHE_KRYO3XX()
+
 # "sdm660"
 lookuptable[("660", 0x80, 0x14)] = L1_DCache_KRYO2XX_SILVER()
 lookuptable[("660", 0x81, 0x14)] = L1_DCache_KRYO2XX_SILVER()
@@ -545,12 +746,20 @@ lookuptable[("8917", 0x84, 0x14)] = L1_DCache_A53()
 lookuptable[("8917", 0x85, 0x14)] = L1_DCache_A53()
 lookuptable[("8917", 0x86, 0x14)] = L1_DCache_A53()
 lookuptable[("8917", 0x87, 0x14)] = L1_DCache_A53()
+lookuptable[("8917", 0x64, 0x14)] = L1_ICache_A53()
+lookuptable[("8917", 0x65, 0x14)] = L1_ICache_A53()
+lookuptable[("8917", 0x66, 0x14)] = L1_ICache_A53()
+lookuptable[("8917", 0x67, 0x14)] = L1_ICache_A53()
 
 # 8920
 lookuptable[("8920", 0x84, 0x14)] = L1_DCache_A53()
 lookuptable[("8920", 0x85, 0x14)] = L1_DCache_A53()
 lookuptable[("8920", 0x86, 0x14)] = L1_DCache_A53()
 lookuptable[("8920", 0x87, 0x14)] = L1_DCache_A53()
+lookuptable[("8920", 0x64, 0x14)] = L1_ICache_A53()
+lookuptable[("8920", 0x65, 0x14)] = L1_ICache_A53()
+lookuptable[("8920", 0x66, 0x14)] = L1_ICache_A53()
+lookuptable[("8920", 0x67, 0x14)] = L1_ICache_A53()
 
 # 8937
 lookuptable[("8937", 0x80, 0x14)] = L1_DCache_A53()
@@ -561,6 +770,14 @@ lookuptable[("8937", 0x84, 0x14)] = L1_DCache_A53()
 lookuptable[("8937", 0x85, 0x14)] = L1_DCache_A53()
 lookuptable[("8937", 0x86, 0x14)] = L1_DCache_A53()
 lookuptable[("8937", 0x87, 0x14)] = L1_DCache_A53()
+lookuptable[("8937", 0x60, 0x14)] = L1_ICache_A53()
+lookuptable[("8937", 0x61, 0x14)] = L1_ICache_A53()
+lookuptable[("8937", 0x62, 0x14)] = L1_ICache_A53()
+lookuptable[("8937", 0x63, 0x14)] = L1_ICache_A53()
+lookuptable[("8937", 0x64, 0x14)] = L1_ICache_A53()
+lookuptable[("8937", 0x65, 0x14)] = L1_ICache_A53()
+lookuptable[("8937", 0x66, 0x14)] = L1_ICache_A53()
+lookuptable[("8937", 0x67, 0x14)] = L1_ICache_A53()
 
 # 8940
 lookuptable[("8940", 0x80, 0x14)] = L1_DCache_A53()
@@ -571,6 +788,14 @@ lookuptable[("8940", 0x84, 0x14)] = L1_DCache_A53()
 lookuptable[("8940", 0x85, 0x14)] = L1_DCache_A53()
 lookuptable[("8940", 0x86, 0x14)] = L1_DCache_A53()
 lookuptable[("8940", 0x87, 0x14)] = L1_DCache_A53()
+lookuptable[("8940", 0x60, 0x14)] = L1_ICache_A53()
+lookuptable[("8940", 0x61, 0x14)] = L1_ICache_A53()
+lookuptable[("8940", 0x62, 0x14)] = L1_ICache_A53()
+lookuptable[("8940", 0x63, 0x14)] = L1_ICache_A53()
+lookuptable[("8940", 0x64, 0x14)] = L1_ICache_A53()
+lookuptable[("8940", 0x65, 0x14)] = L1_ICache_A53()
+lookuptable[("8940", 0x66, 0x14)] = L1_ICache_A53()
+lookuptable[("8940", 0x67, 0x14)] = L1_ICache_A53()
 
 # 8953
 lookuptable[("8953", 0x80, 0x14)] = L1_DCache_A53()
diff --git a/linux-ramdump-parser-v2/debug_image_v2.py b/linux-ramdump-parser-v2/debug_image_v2.py
index 8d0e7b12a0dda3dbf16ee153041eaa6882df97c4..81e54907f5663a985d5fa654577c37075504450b 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
@@ -51,6 +52,7 @@ class client(object):
     MSM_DUMP_DATA_LOG_BUF = 0x110
     MSM_DUMP_DATA_LOG_BUF_FIRST_IDX = 0x111
     MSM_DUMP_DATA_L2_TLB = 0x120
+    MSM_DUMP_DATA_LLC_CACHE = 0x121
     MSM_DUMP_DATA_SCANDUMP = 0xEB
     MSM_DUMP_DATA_MAX = MAX_NUM_ENTRIES
 
@@ -58,8 +60,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'),
@@ -73,6 +75,7 @@ client_types = [
     ('MSM_DUMP_DATA_TMC_ETF', 'parse_qdss_common'),
     ('MSM_DUMP_DATA_TMC_REG', 'parse_qdss_common'),
     ('MSM_DUMP_DATA_L2_TLB', 'parse_l2_tlb'),
+    ('MSM_DUMP_DATA_LLC_CACHE', 'parse_system_cache_common'),
 ]
 
 qdss_tag_to_field_name = {
@@ -95,7 +98,6 @@ class DebugImage_v2():
         else:
             self.event_call = 'struct ftrace_event_call'
             self.event_class = 'struct ftrace_event_class'
-        self.has_scan_dump = False
 
     def parse_scandump(self, version, start, end, client_id, ram_dump):
         scandump_file_prefix = "scandump"
@@ -104,8 +106,6 @@ class DebugImage_v2():
         except AttributeError:
             print_out_str('Could not find scandump_parser_path . Please define scandump_parser_path in local_settings')
             return
-        if client_id == client.MSM_DUMP_DATA_SCANDUMP:
-            self.has_scan_dump = True
         output = os.path.join(ram_dump.outdir, scandump_file_prefix)
         input = os.path.join(ram_dump.outdir, "vv_msg_4_header.bin")
         print_out_str(
@@ -126,7 +126,7 @@ class DebugImage_v2():
         print_out_str(
             'Parsing CPU{2} context start {0:x} end {1:x}'.format(start, end, core))
 
-        regs = TZRegDump_v2(self.has_scan_dump)
+        regs = TZRegDump_v2()
         if regs.init_regs(version, start, end, core, ram_dump) is False:
             print_out_str('!!! Could not get registers from TZ dump')
             return
@@ -212,6 +212,40 @@ class DebugImage_v2():
             print_out_exception()
         outfile.close()
 
+    def parse_system_cache_common(self, version, start, end, client_id, ramdump):
+        client_name = self.dump_data_id_lookup_table[client_id]
+        bank_number = client_id - client.MSM_DUMP_DATA_LLC_CACHE
+
+        filename = '{0}_0x{1:x}'.format(client_name, bank_number)
+        outfile = ramdump.open_file(filename)
+        cache_type = lookup_cache_type(ramdump.hw_id, client_id, version)
+        try:
+            cache_type.parse(start, end, ramdump, outfile)
+        except NotImplementedError:
+            print_out_str('System cache dumping not supported'
+                          % client_name)
+        except:
+            print_out_str('!!! Unhandled exception while running {0}'.format(client_name))
+            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')
@@ -470,6 +504,10 @@ class DebugImage_v2():
                     client.MSM_DUMP_DATA_L2_CACHE + i] = 'MSM_DUMP_DATA_L2_CACHE'
                 self.dump_data_id_lookup_table[
                     client.MSM_DUMP_DATA_ETM_REG + i] = 'MSM_DUMP_DATA_ETM_REG'
+
+        for i in range(0, 4):
+                self.dump_data_id_lookup_table[
+                    client.MSM_DUMP_DATA_LLC_CACHE + i] = 'MSM_DUMP_DATA_LLC_CACHE'
         # 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'
diff --git a/linux-ramdump-parser-v2/mm.py b/linux-ramdump-parser-v2/mm.py
index 02fa7aa918566760d150651f7fc3148cf4f5b07d..efca724830789ce95123989d4146d72c2f375acb 100644
--- a/linux-ramdump-parser-v2/mm.py
+++ b/linux-ramdump-parser-v2/mm.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2013-2016, The Linux Foundation. All rights reserved.
+# Copyright (c) 2013-2017, 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
@@ -19,6 +19,21 @@ def page_buddy(ramdump, page):
     return val == 0xffffff80
 
 
+def page_count(ramdump, page):
+    """Commit: 0139aa7b7fa12ceef095d99dc36606a5b10ab83a
+    mm: rename _count, field of the struct page, to _refcount"""
+    if (ramdump.version < (4, 6, 0)):
+        count = ramdump.read_structure_field(page, 'struct page',
+                                             '_count.counter')
+    else:
+        count = ramdump.read_structure_field(page, 'struct page',
+                                             '_refcount.counter')
+    return count
+
+
+def page_ref_count(ramdump, page):
+    return page_count(ramdump, page)
+
 def get_debug_flags(ramdump, page):
     debug_flag_offset = ramdump.field_offset('struct page', 'debug_flags')
     flagval = ramdump.read_word(page + debug_flag_offset)
@@ -135,6 +150,7 @@ def get_vmemmap(ramdump):
     # See: include/asm-generic/pgtable-nopud.h,
     # arch/arm64/include/asm/pgtable-hwdef.h,
     # arch/arm64/include/asm/pgtable.h
+    # kernel/arch/arm64/include/asm/memory.h
     if (ramdump.kernel_version < (3, 18, 0)):
         nlevels = int(ramdump.get_config_val("CONFIG_ARM64_PGTABLE_LEVELS"))
     else:
@@ -151,16 +167,27 @@ def get_vmemmap(ramdump):
     spsize = ramdump.sizeof('struct page')
     vmemmap_size = bitops.align((1 << (va_bits - page_shift)) * spsize,
                                 pud_size)
+
+    memstart_addr = ramdump.read_s64('memstart_addr')
+    page_section_mask = ~((1 << 18) - 1)
+    memstart_offset = (memstart_addr >> page_shift) & page_section_mask
+    memstart_offset *= spsize
+
     if (ramdump.kernel_version < (3, 18, 31)):
-        vmalloc_end = ramdump.page_offset - pud_size - vmemmap_size
         # vmalloc_end = 0xFFFFFFBC00000000
-    else:
+        vmemmap = ramdump.page_offset - pud_size - vmemmap_size
+    elif (ramdump.kernel_version < (4, 9, 0)):
         # for version >= 3.18.31,
         # vmemmap is shifted to base addr (0x80000000) pfn.
-        pfn_offset = (ramdump.phys_offset >> page_shift)
-        offset = pfn_offset * spsize
-        vmalloc_end = ramdump.page_offset - pud_size - vmemmap_size - offset
-    return vmalloc_end
+        vmemmap = (ramdump.page_offset - pud_size - vmemmap_size -
+                   memstart_offset)
+    else:
+        # for version >= 4.9.0,
+        # vmemmap_size = ( 1 << (39 - 12 - 1 + 6))
+        struct_page_max_shift = 6
+        vmemmap_size = ( 1 << (va_bits - page_shift - 1 + struct_page_max_shift))
+        vmemmap = ramdump.page_offset - vmemmap_size - memstart_offset
+    return vmemmap
 
 
 def page_to_pfn_vmemmap(ramdump, page):
@@ -277,3 +304,30 @@ def page_address(ramdump, page):
         pam = ramdump.read_word(pam + lh_offset)
         if pam == start:
             return None
+
+
+def for_each_pfn(ramdump):
+    """ creates a generator for looping through valid pfn
+    Example:
+    for i in for_each_pfn(ramdump):
+        page = pfn_to_page(i)
+    """
+    page_size = (1 << 12)
+    cnt = ramdump.read_structure_field('memblock', 'struct memblock',
+                                       'memory.cnt')
+    region = ramdump.read_structure_field('memblock', 'struct memblock',
+                                          'memory.regions')
+    memblock_region_size = ramdump.sizeof('struct memblock_region')
+    for i in range(cnt):
+        start = ramdump.read_structure_field(region, 'struct memblock_region',
+                                             'base')
+        end = start + ramdump.read_structure_field(
+                            region, 'struct memblock_region', 'size')
+
+        pfn = start / page_size
+        end /= page_size
+        while pfn < end:
+            yield pfn
+            pfn += 1
+
+        region += memblock_region_size
diff --git a/linux-ramdump-parser-v2/mmu.py b/linux-ramdump-parser-v2/mmu.py
index 4444cd2dd4eaf067f90120688b0d3c7a5bd014ad..0d395a6006a6d6b662d94c8998d2feca2bda1ee4 100644
--- a/linux-ramdump-parser-v2/mmu.py
+++ b/linux-ramdump-parser-v2/mmu.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2013-2016, The Linux Foundation. All rights reserved.
+# Copyright (c) 2013-2017, 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
@@ -51,16 +51,21 @@ class MMU(object):
         if addr is None:
             return None
 
+        page_addr = (addr >> 12) << 12
+        page_offset = addr & 0xFFF
+
         if not skip_tlb:
-            if addr in self._tlb:
-                return self._tlb[addr]
+            if page_addr in self._tlb:
+                return self._tlb[page_addr] + page_offset
 
-        phys_addr = self.page_table_walk(addr)
+        phys_addr = self.page_table_walk(page_addr)
+        if phys_addr is None:
+            return None
 
         if save_in_tlb:
-            self._tlb[addr] = phys_addr
+            self._tlb[page_addr] = phys_addr
 
-        return phys_addr
+        return phys_addr + page_offset
 
     def load_page_tables(self):
         raise NotImplementedError
diff --git a/linux-ramdump-parser-v2/parsers/clockdump.py b/linux-ramdump-parser-v2/parsers/clockdump.py
old mode 100755
new mode 100644
index 09b4657d3c1efe6ecd92acf4be0d2afb75688b49..fd7eedccb4e152f6a97ef6c7d439b6a29e14dead
--- a/linux-ramdump-parser-v2/parsers/clockdump.py
+++ b/linux-ramdump-parser-v2/parsers/clockdump.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2015, The Linux Foundation. All rights reserved.
+# Copyright (c) 2015,2017 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
@@ -13,8 +13,9 @@ import linux_list
 from print_out import print_out_str
 from parser_util import register_parser, RamParser
 
+
 @register_parser('--clock-dump', 'Dump all the clocks in the system')
-class ClockDumps(RamParser) :
+class ClockDumps(RamParser):
 
     def __init__(self, *args):
         super(ClockDumps, self).__init__(*args)
@@ -118,14 +119,7 @@ class ClockDumps(RamParser) :
         clk_providers_walker = linux_list.ListWalker(self.ramdump, head, node_offset)
         clk_providers_walker.walk(head, self.clk_providers_walker)
 
-    def clk_providers_walker(self, node):
-        if node == self.head:
-            return
-
-        data_address = node + self.ramdump.field_offset('struct of_clk_provider', 'data')
-        node_address = node + self.ramdump.field_offset('struct of_clk_provider', 'node')
-        data = self.ramdump.read_word(data_address, True)
-        node = self.ramdump.read_word(node_address, True)
+    def print_clk_of_msm_provider_data(self, data):
         table_address = data + self.ramdump.field_offset('struct of_msm_provider_data', 'table')
         size_address = data + self.ramdump.field_offset('struct of_msm_provider_data', 'size')
         table = self.ramdump.read_word(table_address, True)
@@ -163,6 +157,73 @@ class ClockDumps(RamParser) :
             counter = counter + 1
             table = table + self.ramdump.sizeof('struct clk_lookup')
 
+    def print_clk_onecell_data(self, data):
+        offset_clk_onecell_data_clks = (
+                self.ramdump.field_offset('struct clk_onecell_data', 'clks'))
+        offset_clk_onecell_data_clknum = (
+                            self.ramdump.field_offset(
+                                'struct clk_onecell_data', 'clk_num'))
+        clks = self.ramdump.read_word(data + offset_clk_onecell_data_clks)
+        size = self.ramdump.read_int(data + offset_clk_onecell_data_clknum)
+        sizeof_clk_pointer = self.ramdump.sizeof('struct clk *')
+        offset_vdd_cur_level = self.ramdump.field_offset(
+                                    'struct clk_vdd_class', 'cur_level')
+        counter = 0
+
+        while counter < size:
+            clk = self.ramdump.read_word(clks + (sizeof_clk_pointer * counter))
+            if clk == 0 or clk is None:
+                counter = counter + 1
+                continue
+            clk_core = self.ramdump.read_structure_field(
+                                                    clk, 'struct clk', 'core')
+            if clk_core == 0 or clk_core is None:
+                counter = counter + 1
+                continue
+            clk_name_addr = self.ramdump.read_structure_field(
+                                        clk_core, 'struct clk_core', 'name')
+            clk_name = self.ramdump.read_cstring(clk_name_addr, 48)
+            clk_prepare_count = self.ramdump.read_structure_field(
+                                clk_core, 'struct clk_core', 'prepare_count')
+            clk_enable_count = self.ramdump.read_structure_field(
+                                clk_core, 'struct clk_core', 'enable_count')
+            clk_rate = self.ramdump.read_structure_field(
+                                    clk_core, 'struct clk_core', 'rate')
+            clk_vdd_class_addr = (
+                    self.ramdump.read_structure_field(
+                        clk_core, 'struct clk_core', 'vdd_class'))
+            vdd_class = self.ramdump.read_word(clk_vdd_class_addr)
+            cur_level = 0
+            if vdd_class != 0 and vdd_class is not None:
+                cur_level_address = (vdd_class + offset_vdd_cur_level)
+                cur_level = self.ramdump.read_word(cur_level_address, True)
+            formatStr  = "{0:40} {1:<2}/ {2:<17} {3:<25} {4:<10} v.v (struct clk_core *)0x{5:<20x}\n"
+            output = formatStr.format(
+                                    clk_name,
+                                    clk_enable_count,
+                                    clk_prepare_count,
+                                    clk_rate, cur_level,
+                                    clk_core)
+            if clk_enable_count > 0:
+                self.enabled_clocks.append(output)
+            elif clk_prepare_count > 0:
+                self.prepared_clocks.append(output)
+            else:
+                self.disabled_clocks.append(output)
+            counter = counter + 1
+
+    def clk_providers_walker(self, node):
+        if node == self.head:
+            return
+        data_address = node + self.ramdump.field_offset(
+                                    'struct of_clk_provider', 'data')
+        data = self.ramdump.read_word(data_address, True)
+
+        if (self.ramdump.kernel_version < (4, 4, 38)):
+            self.print_clk_of_msm_provider_data(data)
+        else:
+            self.print_clk_onecell_data(data)
+
     def parse(self):
         self.output_file = self.ramdump.open_file('ClockDumps.txt')
 
diff --git a/linux-ramdump-parser-v2/parsers/ftrace.py b/linux-ramdump-parser-v2/parsers/ftrace.py
new file mode 100644
index 0000000000000000000000000000000000000000..90ea0765a5902adc3b725f580302220c16a12b15
--- /dev/null
+++ b/linux-ramdump-parser-v2/parsers/ftrace.py
@@ -0,0 +1,144 @@
+# 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 parser_util
+import local_settings
+import os
+import subprocess
+
+from parser_util import register_parser, RamParser
+from print_out import print_out_str
+from tempfile import NamedTemporaryFile
+
+@register_parser(
+    '--dump-ftrace',
+    'Use \'crash\' to extract ftrace and trace-cmd to parse it.',
+    optional=True)
+class FtraceParser(RamParser):
+
+    def __init__(self, *args):
+        super(FtraceParser, self).__init__(*args)
+
+    def parse(self):
+        if parser_util.get_system_type() != 'Linux':
+            print_out_str("Run the ramdump parser on Linux to get ftrace")
+            return False
+
+        try:
+            crashtool = local_settings.crashtool
+            trace_ext = local_settings.trace_ext
+            tracecmdtool = local_settings.tracecmdtool
+        except AttributeError:
+            print_out_str("One of crashtool, the trace extension or" +
+                          " trace-cmd is missing from local-settings.py")
+            return False
+
+        if not os.path.exists(crashtool):
+            print_out_str("Couldn't find the crash tool")
+            return False
+        if not os.path.exists(trace_ext):
+            print_out_str("Couldn't find the crash tool trace extension")
+            return False
+        if not os.path.exists(tracecmdtool):
+            print_out_str("Couldn't find the trace-cmd tool")
+            return False
+
+        print_out_str(crashtool)
+        dumps=""
+        for (f, start, end, filename) in self.ramdump.ebi_files:
+                if "DDR" in filename or "dram" in filename:
+                    dumps += '{0}@0x{1:x},'.format(filename, start)
+        pagesize = "-p 4096"
+
+        commandsfile = NamedTemporaryFile(mode='w', delete=False,
+                              dir=self.ramdump.outdir)
+        commandsfile.write("extend " + trace_ext + "\n")
+        commandsfile.write("trace dump -t " + self.ramdump.outdir +
+                       "/rawtracedata\n")
+        commandsfile.write("quit\n")
+        commandsfile.close()
+
+        commands = "-i " + commandsfile.name
+
+        crashargs = [crashtool]
+
+        if self.ramdump.kaslr_offset is not None:
+            kaslroffset = "--kaslr={0}".format(hex(self.ramdump.kaslr_offset))
+            crashargs.append(kaslroffset)
+
+        if self.ramdump.kimage_voffset is not None:
+            kimagevoff="kimage_voffset={0}".format(hex(self.ramdump.kimage_voffset).replace('L',''))
+            crashargs.append("--machdep")
+            crashargs.append(kimagevoff)
+
+        crashargs.extend([dumps, self.ramdump.vmlinux,
+                     pagesize, commands])
+
+        print_out_str('args to crash: {0}'.format(crashargs))
+
+        sp = subprocess.Popen(crashargs,
+                              stdout=subprocess.PIPE,
+                              stderr=subprocess.PIPE)
+        out, err = sp.communicate()
+
+        if out:
+             print_out_str("crash standard output recorded.")
+             std = self.ramdump.open_file('stdout_crashtool.txt')
+             std.write(out);
+             std.close();
+        if err:
+             print_out_str("crash standard error recorded.")
+             std = self.ramdump.open_file('stderr_crashtool.txt')
+             std.write(err);
+             std.close();
+
+        os.remove(commandsfile.name)
+
+        if not os.path.exists(self.ramdump.outdir + "/rawtracedata"):
+             print_out_str("crash failed to extract raw ftrace data")
+             return False
+
+        tracecmd_arg = self.ramdump.outdir + "/rawtracedata"
+        sp = subprocess.Popen([tracecmdtool, "report", "-l", tracecmd_arg],
+                              stdout=subprocess.PIPE,
+                              stderr=subprocess.PIPE)
+        out, err = sp.communicate();
+
+        if out:
+             ftrace_out = self.ramdump.open_file('ftrace.txt')
+             ftrace_out.write(out);
+             ftrace_out.close();
+             print_out_str("Ftrace successfully extracted.");
+        if err:
+             print_out_str("trace-cmd standard error recorded.")
+             std = self.ramdump.open_file('stderr_tracecmd.txt')
+             std.write(err);
+             std.close();
+
+        return True
diff --git a/linux-ramdump-parser-v2/parsers/memstat.py b/linux-ramdump-parser-v2/parsers/memstat.py
index aabe62bf3982d70fffee167255d65871f155e55f..322a0508856e56505fd4809af4ac325d1ed13b63 100644
--- a/linux-ramdump-parser-v2/parsers/memstat.py
+++ b/linux-ramdump-parser-v2/parsers/memstat.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2016 The Linux Foundation. All rights reserved.
+# Copyright (c) 2016-2017 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
@@ -50,7 +50,7 @@ class MemStats(RamParser):
         list_walker.walk(vmlist, self.list_func)
         self.vmalloc_size = self.bytes_to_mb(self.vmalloc_size)
 
-    def calculate_others(self):
+    def calculate_vm_stat(self):
         # Other memory :  NR_ANON_PAGES + NR_FILE_PAGES + NR_PAGETABLE \
         # + NR_KERNEL_STACK - NR_SWAPCACHE
         vmstat_anon_pages = self.ramdump.read_word(
@@ -68,6 +68,22 @@ class MemStats(RamParser):
         other_mem = self.pages_to_mb(other_mem)
         return other_mem
 
+    def calculate_vm_node_zone_stat(self):
+        # Other memory :  NR_ANON_MAPPED + NR_FILE_PAGES + NR_PAGETABLE \
+        # + NR_KERNEL_STACK_KB
+        vmstat_anon_pages = self.ramdump.read_word(
+                            'vm_node_stat[NR_ANON_MAPPED]')
+        vmstat_file_pages = self.ramdump.read_word(
+                            'vm_node_stat[NR_FILE_PAGES]')
+        vmstat_pagetbl = self.ramdump.read_word(
+                            'vm_zone_stat[NR_PAGETABLE]')
+        vmstat_kernelstack = self.ramdump.read_word(
+                            'vm_zone_stat[NR_KERNEL_STACK_KB]')
+        other_mem = (vmstat_anon_pages + vmstat_file_pages + vmstat_pagetbl +
+                     (vmstat_kernelstack/4))
+        other_mem = self.pages_to_mb(other_mem)
+        return other_mem
+
     def calculate_ionmem(self):
         number_of_ion_heaps = self.ramdump.read_int('num_heaps')
         heap_addr = self.ramdump.read_word('heaps')
@@ -98,16 +114,33 @@ class MemStats(RamParser):
         total_mem = self.ramdump.read_word('totalram_pages')
         total_mem = self.pages_to_mb(total_mem)
 
-        # Free Memory
-        total_free = self.ramdump.read_word('vm_stat[NR_FREE_PAGES]')
-        total_free = self.pages_to_mb(total_free)
+        if (self.ramdump.kernel_version < (4, 9, 0)):
+           # Free Memory
+           total_free = self.ramdump.read_word('vm_stat[NR_FREE_PAGES]')
+           total_free = self.pages_to_mb(total_free)
 
-        # slab Memory
-        slab_rec = \
-            self.ramdump.read_word('vm_stat[NR_SLAB_RECLAIMABLE]')
-        slab_unrec = \
-            self.ramdump.read_word('vm_stat[NR_SLAB_UNRECLAIMABLE]')
-        total_slab = self.pages_to_mb(slab_rec + slab_unrec)
+           # slab Memory
+           slab_rec = \
+               self.ramdump.read_word('vm_stat[NR_SLAB_RECLAIMABLE]')
+           slab_unrec = \
+               self.ramdump.read_word('vm_stat[NR_SLAB_UNRECLAIMABLE]')
+           total_slab = self.pages_to_mb(slab_rec + slab_unrec)
+
+           #others
+           other_mem = self.calculate_vm_stat()
+        else:
+           # Free Memory
+           total_free = self.ramdump.read_word('vm_zone_stat[NR_FREE_PAGES]')
+           total_free = self.pages_to_mb(total_free)
+
+           # slab Memory
+           slab_rec = \
+               self.ramdump.read_word('vm_zone_stat[NR_SLAB_RECLAIMABLE]')
+           slab_unrec = \
+               self.ramdump.read_word('vm_zone_stat[NR_SLAB_UNRECLAIMABLE]')
+           total_slab = self.pages_to_mb(slab_rec + slab_unrec)
+           #others
+           other_mem = self.calculate_vm_node_zone_stat()
 
         # ion memory
         ion_mem = self.calculate_ionmem()
@@ -136,9 +169,6 @@ class MemStats(RamParser):
         # vmalloc area
         self.calculate_vmalloc()
 
-        # Others
-        other_mem = self.calculate_others()
-
         # Output prints
         out_mem_stat.write('{0:30}: {1:8} MB'.format(
                                 "Total RAM", total_mem))
diff --git a/linux-ramdump-parser-v2/parsers/mmcdoctor.py b/linux-ramdump-parser-v2/parsers/mmcdoctor.py
new file mode 100644
index 0000000000000000000000000000000000000000..0d6a820809d7576477fdd9e15d8ce74bdc645c00
--- /dev/null
+++ b/linux-ramdump-parser-v2/parsers/mmcdoctor.py
@@ -0,0 +1,368 @@
+# Copyright (c) 2017, 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 os
+from parser_util import register_parser, RamParser
+from parsers.irqstate import IrqParse
+from dmesglib import DmesgLib
+from print_out import print_out_str
+
+MMC0_IRQ = 0
+MMC1_IRQ = 0
+SDHCI_IRQ_NAME = "sdhci"
+SDHCI_IRQ_CD_NAME = "sdhci cd"
+
+F_MMCDEBUG = "mmcreport.txt"
+F_MMCTEMP = "mmctemp.txt"
+
+PATTERN_ST = "========== REGISTER DUMP (mmc0)=========="
+PATTERN_END = "sdhci: ===================="
+
+MMC_DATA_HEAD = "#################### MMC(mmc%d) INFO START #######################\n"
+MMC_DATA_FOOT = "#################### MMC(mmc%d) INFO END #########################\n\n"
+
+MMC_TRACE_HEADER = "\n################ MMC(mmc%d) RING BUFFER ################\n"
+MMC_TRACE_BUF_EVENTS = 64
+MMC_TRACE_EVENT_SIZE = 256
+
+card_data = {
+    0x2: "SANDISK",
+    0x11: "TOSHIBA",
+    0x13: "MICRON",
+    0x15: "SAMSUNG",
+    0x70: "KINGSTON",
+    0x90: "HYNIX",
+}
+
+card_err_data = {
+    "Card Timeout"      : ["err: -110", "error: -110"],
+    "Soft Timeout"      : ["Timeout waiting for hardware interrupt", "request with tag"],
+    "CRC ERROR"         : ["err: -84", "error: -84"],
+    "Resp_error"        : ["status: 0x00000006", "status: 0x00000004"],
+    "Spurious_cmd_intr" : ["Got command interrupt", "even though no command"],
+    "Spurious_data_intr": ["Got data interrupt", "even though no data"],
+    "Spurious_intr"     : ["Unexpected interrupt", "Unexpected interrupt"],
+}
+
+
+#
+# This class defines parsing function
+# to parse for mmclog
+#
+class ParseMmcLog():
+
+    def __init__(self, ramdump):
+        self.ramdump = ramdump
+        self.error = 0
+        self.error_line = ""
+
+    def dumptemplog(self):
+        fd_temp = self.ramdump.open_file(F_MMCTEMP, "w+")
+        d = DmesgLib(self.ramdump, fd_temp)
+        d.extract_dmesg()
+        fd_temp.close()
+
+    def check_for_error(self, line):
+        if (self.error):
+            return
+        for key, item in card_err_data.iteritems():
+            if (item[0] in line or item[1] in line):
+                self.error = key
+                self.error_line = line
+                break
+
+    def dumpmemreport(self):
+        self.dumptemplog()
+        self.error = 0
+        self.error_line = ""
+        fdr = self.ramdump.open_file(F_MMCTEMP, "r")
+        fdw = self.ramdump.open_file(F_MMCDEBUG, "a")
+        line = fdr.readline()
+        while (line):
+            if ("mmc" in line):
+                fdw.write(line)
+                self.check_for_error(line)
+            if (PATTERN_ST in line):
+                line = fdr.readline()
+                while (line and (PATTERN_END not in line)):
+                    fdw.write("ERROR" + line)
+                    line = fdr.readline()
+                if (line and PATTERN_END in line):
+                    fdw.write("ERROR" + line)
+            line = fdr.readline()
+        fdw.close()
+        fdr.close()
+        self.ramdump.remove_file(F_MMCTEMP)
+
+
+#
+# Function definition to find all relevant structure
+#
+
+def get_sdhci_irqs(ram_dump):
+    irqs = IrqParse(RamParser)
+    count = 0
+    global MMC0_IRQ
+    global MMC1_IRQ
+    irq_action_offset = ram_dump.field_offset('struct irq_desc', 'action')
+    action_name_offset = ram_dump.field_offset('struct irqaction', 'name')
+    irq_desc_tree = ram_dump.address_of('irq_desc_tree')
+    nr_irqs = ram_dump.read_int(ram_dump.address_of('nr_irqs'))
+
+    if nr_irqs > 50000:
+        return
+    for i in range(0, nr_irqs):
+        irq_desc = irqs.radix_tree_lookup_element(
+            ram_dump, irq_desc_tree, i)
+        if irq_desc is None:
+            continue
+        action = ram_dump.read_word(irq_desc + irq_action_offset)
+        if action != 0 and count < 2:
+            name_addr = ram_dump.read_word(action + action_name_offset)
+            name = ram_dump.read_cstring(name_addr, 48)
+            if (not name):
+                continue
+            if (SDHCI_IRQ_NAME in name and not SDHCI_IRQ_CD_NAME in name):
+                if (count == 0):
+                    MMC0_IRQ = i
+                elif (count == 1):
+                    MMC1_IRQ = i
+                count += 1
+    return count
+
+def find_sdhci_host(ramdump, irq):
+    irq_desc_tree = ramdump.address_of('irq_desc_tree')
+    irq_action_offset = ramdump.field_offset('struct irq_desc', 'action')
+    dev_id = ramdump.field_offset('struct irqaction', 'dev_id')
+    irqs = IrqParse(RamParser)
+    sdhci_irq_desc = irqs.radix_tree_lookup_element(ramdump, irq_desc_tree, irq)
+    sdhci_irq_action = ramdump.read_word(sdhci_irq_desc + irq_action_offset)
+    sdhci_host = ramdump.read_word(sdhci_irq_action + dev_id)
+    return sdhci_host
+
+
+def find_mmc_host(ramdump, sdhci_host):
+    mmc_offset = ramdump.field_offset('struct sdhci_host', 'mmc')
+    mmc_host = ramdump.read_word(sdhci_host + mmc_offset)
+    return mmc_host
+
+
+def find_mmc_card(ramdump, mmc_host):
+    card_offset = ramdump.field_offset('struct mmc_host', 'card')
+    mmc_card = ramdump.read_word(mmc_host + card_offset)
+    return mmc_card
+
+
+def find_sdhci_msm_host(ramdump, sdhci_host):
+    sdhci_pltfm_host = (sdhci_host + ramdump.sizeof('struct sdhci_host'))
+    msm_offset = ramdump.field_offset('struct sdhci_pltfm_host', 'priv')
+    sdhci_msm_host = ramdump.read_word(sdhci_pltfm_host + msm_offset)
+    return sdhci_msm_host
+
+
+class MmcCardInfo():
+
+    def __init__(self, ramdump, mmc_card):
+        self.ramdump = ramdump
+        self.card = mmc_card
+        self.type = self.find_mmc_cid()
+        self.ext_csd_fwrev = self.find_ext_csd()
+        self.cmdq_init = self.find_cmdq_init()
+
+    def find_ext_csd(self):
+        if (not self.card):
+            return 0
+        ext_csd_off = self.card + \
+            self.ramdump.field_offset('struct mmc_card', 'ext_csd')
+        self.mmc_ext_csd = ext_csd_off
+        fw_version_offset = self.ramdump.field_offset('struct mmc_ext_csd', 'fw_version')
+        if (fw_version_offset is None):
+            return -2
+        ext_csd_fwrev = ext_csd_off + fw_version_offset
+        return self.ramdump.read_byte(ext_csd_fwrev)
+
+    def find_mmc_cid(self):
+        if (not self.card):
+            return 0
+        cid = self.card + self.ramdump.field_offset('struct mmc_card', 'cid')
+        self.mmc_cid = cid
+        manfid = self.ramdump.read_u32(cid)
+        if manfid in card_data.keys():
+            return card_data[manfid]
+        else:
+            return manfid
+
+    def find_cmdq_init(self):
+        if (not self.card):
+            return 0
+        cmdq_init = self.card + self.ramdump.field_offset('struct mmc_card', 'cmdq_init')
+        return self.ramdump.read_bool(cmdq_init)
+
+
+class MmcHostInfo():
+
+    def __init__(self, ramdump, mmc_host):
+        self.ramdump = ramdump
+        self.host = mmc_host
+        self.clk_gated = self.ramdump.read_bool(self.host +
+                    self.ramdump.field_offset('struct mmc_host', 'clk_gated'))
+        self.clk_requests = self.ramdump.read_int(self.host +
+                    self.ramdump.field_offset('struct mmc_host', 'clk_requests'))
+        self.clk_old = self.ramdump.read_int(self.host +
+                    self.ramdump.field_offset('struct mmc_host', 'clk_old'))
+
+        offset = self.ramdump.field_offset('struct mmc_host', 'err_occurred')
+        if (offset):
+            self.err_occurred = self.ramdump.read_bool(self.host + offset)
+        else:
+            self.err_occurred = -1
+        self.ios = self.find_ios()
+        self.ios_clock = self.ramdump.read_int(self.ios +
+                    self.ramdump.field_offset('struct mmc_ios', 'clock'))
+        self.ios_old_rate = self.ramdump.read_int(self.ios +
+                    self.ramdump.field_offset('struct mmc_ios', 'old_rate'))
+        self.ios_vdd = self.ramdump.read_u16(self.ios +
+                    self.ramdump.field_offset('struct mmc_ios', 'vdd'))
+        self.ios_bus_width = self.ramdump.read_byte(self.ios +
+                    self.ramdump.field_offset('struct mmc_ios', 'bus_width'))
+        self.ios_timing = self.ramdump.read_byte(self.ios +
+                    self.ramdump.field_offset('struct mmc_ios', 'timing'))
+        self.ios_signal_voltage = self.ramdump.read_byte(self.ios +
+                    self.ramdump.field_offset('struct mmc_ios', 'signal_voltage'))
+        self.ios_drv_type= self.ramdump.read_byte(self.ios +
+                    self.ramdump.field_offset('struct mmc_ios', 'drv_type'))
+
+    def find_ios(self):
+        return (self.host + self.ramdump.field_offset('struct mmc_host', 'ios'))
+
+
+#
+# Base class which save all mmc data structure info
+# This uses other classes for card and host related
+# info
+#
+class MmcDataStructure():
+    global MMC0_IRQ
+    global MMC1_IRQ
+
+    def __init__(self, ramdump, index):
+        self.mmclist_irq = {0 : MMC0_IRQ, 1 : MMC1_IRQ}
+        self.index = index
+        self.irq = self.mmclist_irq[index]
+        if (self.irq == 0):
+            return
+        self.ramdump = ramdump
+        self.sdhci_host = find_sdhci_host(self.ramdump, self.irq)
+        self.mmc_host = find_mmc_host(self.ramdump, self.sdhci_host)
+        self.mmc_card = find_mmc_card(self.ramdump, self.mmc_host)
+        self.sdhci_msm_host = find_sdhci_msm_host(self.ramdump, self.sdhci_host)
+        self.cardinfo = MmcCardInfo(self.ramdump, self.mmc_card)
+        self.hostinfo = MmcHostInfo(self.ramdump, self.mmc_host)
+        self.parse = ParseMmcLog(self.ramdump)
+        return
+
+    def dump_trace_buf(self, fd):
+        if (not self.mmc_host or (fd <= 0) or (self.ramdump.kernel_version < (4, 4))):
+            return
+        mmc_host = self.mmc_host
+        ramdump = self.ramdump
+
+        fd.write(MMC_TRACE_HEADER % self.index)
+        buf_offset = ramdump.field_offset('struct mmc_host', 'trace_buf')
+        if (not buf_offset):
+            return 0
+
+        data_offset = ramdump.field_offset('struct mmc_trace_buffer', 'data')
+        if (not data_offset):
+            return 0
+
+        trace_buf = mmc_host + buf_offset
+        wr_idx = ramdump.read_int(trace_buf)
+        if (wr_idx >= 0xFFFFFFFF):
+            fd.write("mmc%d trace buffer empty\n" %(self.index))
+            return 0
+
+        dataptr = ramdump.read_word(trace_buf + data_offset)
+        if (not dataptr):
+            return
+
+        datastr = []
+        for i in xrange(MMC_TRACE_BUF_EVENTS):
+            trace_str = ramdump.read_cstring(dataptr, MMC_TRACE_EVENT_SIZE)
+            dataptr += MMC_TRACE_EVENT_SIZE
+            datastr.append(trace_str)
+        num = MMC_TRACE_BUF_EVENTS - 1
+        idx = wr_idx & num
+        cur_idx = (idx + 1) & num
+        for i in xrange(MMC_TRACE_BUF_EVENTS):
+            fd.write("event[%d] = %s" %(cur_idx, datastr[cur_idx]))
+            cur_idx = (cur_idx + 1 ) & num
+
+    def dump_data(self, mode):
+        fd = self.ramdump.open_file(F_MMCDEBUG, mode)
+        fd.write(MMC_DATA_HEAD % self.index)
+        fd.write("mmc_card = 0x%x\n" % self.mmc_card)
+        fd.write("mmc_host = 0x%x\n" % self.mmc_host)
+        fd.write("sdhci_host = 0x%x\n" % self.sdhci_host)
+        fd.write("sdhci_msm_host = 0x%x\n\n" % self.sdhci_msm_host)
+        fd.write("mmc_host->err_occurred = %d\n" % self.hostinfo.err_occurred)
+        fd.write("Grep MMC_ERROR TYPE at End of File\n\n")
+        fd.write("CARD MANFID = %s\n" %self.cardinfo.type)
+        fd.write("CARD Fw_rev = 0x%x\n" %self.cardinfo.ext_csd_fwrev)
+        fd.write("CARD CMDQ INIT = %d\n\n" %self.cardinfo.cmdq_init)
+        fd.write("Host clk_requests = %d\n" %self.hostinfo.clk_requests)
+        fd.write("Host clk_gated = %d\n" %self.hostinfo.clk_gated)
+        fd.write("Host clk_old = %dHz\n" %self.hostinfo.clk_old)
+        fd.write("Host ios_clock = %dHz\n" %self.hostinfo.ios_clock)
+        fd.write("Host ios_old_rate = %uHz\n" %self.hostinfo.ios_old_rate)
+        fd.write("Host ios_vdd = %d\n" %self.hostinfo.ios_vdd)
+        fd.write("Host ios_bus_width = %d\n" %self.hostinfo.ios_bus_width)
+        fd.write("Host ios_timing = %d\n" %self.hostinfo.ios_timing)
+        fd.write("Host ios_signal_voltage = %d\n" %self.hostinfo.ios_signal_voltage)
+        fd.write("Host ios_drv_type = %d\n" %self.hostinfo.ios_drv_type)
+        self.dump_trace_buf(fd)
+        fd.write(MMC_DATA_FOOT % self.index)
+        fd.close()
+        return
+
+
+def dump_mmc_info(ramdump, count):
+    mmc0 = MmcDataStructure(ramdump, 0)
+    mmc0.dump_data("w+")
+
+    if (count > 1):
+        mmc1 = MmcDataStructure(ramdump, 1)
+        mmc1.dump_data("a")
+
+    mmc0.parse.dumpmemreport()
+    fd = ramdump.open_file(F_MMCDEBUG, "a")
+    fd.write("\n\n\n#########MMC_ERROR#########\n")
+    if (mmc0.parse.error):
+        fd.write("ERROR TYPE = %s\n" %mmc0.parse.error)
+    else:
+       fd.write("ERROR TYPE = Unknown Error\n")
+    fd.write("ERROR SIGN = %s\n\n" % mmc0.parse.error_line)
+    fd.close()
+
+
+@register_parser('--mmcdoctor', 'Generate MMC diagnose report')
+class MmcDebug(RamParser):
+    def parse(self):
+        count_irq = 0
+        if self.ramdump.is_config_defined('CONFIG_SPARSE_IRQ'):
+            count_irq = get_sdhci_irqs(self.ramdump)
+            if (count_irq == 0):
+                return
+            dump_mmc_info(self.ramdump, count_irq)
+        else:
+            print_out_str("\n Could not generate MMC diagnose report\n")
+            return
diff --git a/linux-ramdump-parser-v2/parsers/pagealloccorruption.py b/linux-ramdump-parser-v2/parsers/pagealloccorruption.py
old mode 100755
new mode 100644
index 302d46da03c12fabe67c143c609d42781c1a4220..d4174dde027829467f28af2ef5827768720aa3f7
--- a/linux-ramdump-parser-v2/parsers/pagealloccorruption.py
+++ b/linux-ramdump-parser-v2/parsers/pagealloccorruption.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2012,2014-2015 The Linux Foundation. All rights reserved.
+# Copyright (c) 2012,2014-2017 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
@@ -27,6 +27,14 @@ class PageallocCorruption(RamParser):
         cnt = self.ramdump.read_word(memblock_addr + memblock_memory_offset + memblock_memory_cnt_offset)
         region_offset = self.ramdump.field_offset('struct memblock_type', 'regions')
         regions_baseaddr = self.ramdump.read_word(memblock_addr + memblock_memory_offset + region_offset)
+        page_ext_offset = self.ramdump.field_offset(
+                                    'struct mem_section', 'page_ext')
+        page_flags_offset = self.ramdump.field_offset(
+                'struct page_ext', 'flags')
+        mem_section_size = self.ramdump.sizeof("struct mem_section")
+        mem_section = self.ramdump.read_word('mem_section')
+        page_ext_size = self.ramdump.sizeof("struct page_ext")
+
         for r in range(0,cnt) :
             region_addr = regions_baseaddr + r * self.ramdump.sizeof('struct memblock_region')
             start_addr_offset =  self.ramdump.field_offset('struct memblock_region', 'base')
@@ -41,11 +49,23 @@ class PageallocCorruption(RamParser):
             for pfn in range(min_pfn, max_pfn):
                 page = pfn_to_page(self.ramdump, pfn)
                 page_pa = (pfn << 12)
-                # debug_flags value should be 1 for pages having poisoned value 0xaa
-                free = get_debug_flags(self.ramdump, page)
+                if (self.ramdump.kernel_version > (3, 18, 0)):
+                    free = 0
+                    offset = page_pa >> 30
+                    mem_section_0_offset = (
+                        mem_section + (offset * mem_section_size))
+                    page_ext = self.ramdump.read_word(
+                        mem_section_0_offset + page_ext_offset)
+                    temp_page_ext = page_ext + (pfn * page_ext_size)
+                    page_ext_flags = self.ramdump.read_word(
+                        temp_page_ext + page_flags_offset)
+                    # enum PAGE_EXT_DEBUG_POISON ( == 0th bit is set ) for page poisioning
+                    free = page_ext_flags & 1
+                else:
+                    # debug_flags value should be 1 for pages having poisoned value 0xaa
+                    free = get_debug_flags(self.ramdump, page)
 
                 if free == 1:
-                   page_pa = (pfn << 12)
                    flag = 0;
                    for i in range(0,1024):
                        readval = self.ramdump.read_u32(page_pa+i*4, False)
diff --git a/linux-ramdump-parser-v2/parsers/pagetracking.py b/linux-ramdump-parser-v2/parsers/pagetracking.py
index c7d4d87d8ecc87ae3d1f4be6055d3387aa16e9d2..c627ac87f9ea7473780c5e2748134d3af8e5e8b1 100644
--- a/linux-ramdump-parser-v2/parsers/pagetracking.py
+++ b/linux-ramdump-parser-v2/parsers/pagetracking.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2012,2014-2015 The Linux Foundation. All rights reserved.
+# Copyright (c) 2012,2014-2015,2017 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
@@ -11,54 +11,90 @@
 
 from print_out import print_out_str
 from parser_util import register_parser, RamParser
-from mm import pfn_to_page, page_buddy
+from mm import pfn_to_page, page_buddy, page_count, for_each_pfn
+
 
 @register_parser('--print-pagetracking', 'print page tracking information (if available)')
 class PageTracking(RamParser):
 
     def parse(self):
         if not self.ramdump.is_config_defined('CONFIG_PAGE_OWNER'):
+            print_out_str('CONFIG_PAGE_OWNER not defined')
             return
 
-        min_pfn_addr = self.ramdump.address_of('min_low_pfn')
-        max_pfn_addr = self.ramdump.address_of('max_pfn')
-        min_pfn = self.ramdump.read_word(
-            min_pfn_addr) + (self.ramdump.phys_offset >> 12)
-        max_pfn = self.ramdump.read_word(
-            max_pfn_addr) + (self.ramdump.phys_offset >> 12)
-
-        order_offset = self.ramdump.field_offset('struct page', 'order')
-        flags_offset = self.ramdump.field_offset('struct page', 'flags')
-        trace_offset = self.ramdump.field_offset('struct page', 'trace')
-        nr_entries_offset = self.ramdump.field_offset(
-            'struct stack_trace', 'nr_entries')
-        trace_entries_offset = self.ramdump.field_offset(
-            'struct page', 'trace_entries')
+        if (self.ramdump.kernel_version >= (3, 19, 0)):
+            mem_section = self.ramdump.read_word('mem_section')
+
+        trace_offset = 0
+        nr_entries_offset = 0
+        trace_entries_offset = 0
+        offset = 0
+        struct_holding_trace_entries = 0
+        trace_entry_size = self.ramdump.sizeof("unsigned long")
+
+        if (self.ramdump.kernel_version <= (3, 19, 0)):
+            trace_offset = self.ramdump.field_offset('struct page', 'trace')
+            nr_entries_offset = self.ramdump.field_offset(
+                'struct stack_trace', 'nr_entries')
+            trace_entries_offset = self.ramdump.field_offset(
+                'struct page', 'trace_entries')
+        else:
+            page_ext_offset = self.ramdump.field_offset(
+                                    'struct mem_section', 'page_ext')
+            trace_offset = self.ramdump.field_offset(
+                                    'struct page_ext', 'trace')
+            trace_entries_offset = self.ramdump.field_offset(
+                                'struct page_ext', 'trace_entries')
+            nr_entries_offset = self.ramdump.field_offset(
+                                'struct page_ext', 'nr_entries')
+            mem_section_size = self.ramdump.sizeof("struct mem_section")
+            page_ext_size = self.ramdump.sizeof("struct page_ext")
 
         out_tracking = self.ramdump.open_file('page_tracking.txt')
         out_frequency = self.ramdump.open_file('page_frequency.txt')
         sorted_pages = {}
-        trace_entry_size = self.ramdump.sizeof("unsigned long")
 
-        for pfn in range(min_pfn, max_pfn):
+        for pfn in for_each_pfn(self.ramdump):
             page = pfn_to_page(self.ramdump, pfn)
+            order = 0
 
-            # validate this page is free
-            if page_buddy(self.ramdump, page):
+            """must be allocated, and the first pfn of an order > 0 page"""
+            if (page_buddy(self.ramdump, page) or
+                    page_count(self.ramdump, page) == 0):
                 continue
-
-            nr_trace_entries = self.ramdump.read_int(
-                page + trace_offset + nr_entries_offset)
+            if (self.ramdump.kernel_version <= (3, 19, 0)):
+                nr_trace_entries = self.ramdump.read_int(
+                    page + trace_offset + nr_entries_offset)
+                struct_holding_trace_entries = page
+                order = self.ramdump.read_structure_field(
+                            page, 'struct page', 'order')
+            else:
+                phys = pfn << 12
+                if phys is None or phys is 0:
+                    continue
+                offset = phys >> 30
+
+                mem_section_0_offset = (
+                                mem_section + (offset * mem_section_size))
+                page_ext = self.ramdump.read_word(
+                            mem_section_0_offset + page_ext_offset)
+                temp_page_ext = page_ext + (pfn * page_ext_size)
+                nr_trace_entries = self.ramdump.read_int(
+                                    temp_page_ext + nr_entries_offset)
+                struct_holding_trace_entries = temp_page_ext
+                order = self.ramdump.read_structure_field(
+                            temp_page_ext, 'struct page_ext', 'order')
 
             if nr_trace_entries <= 0 or nr_trace_entries > 16:
                 continue
 
-            out_tracking.write('PFN 0x{0:x} page 0x{1:x}\n'.format(pfn, page))
+            out_tracking.write('PFN 0x{:x}-0x{:x} page 0x{:x}\n'.format(
+                pfn, pfn + (1 << order) - 1, page))
 
             alloc_str = ''
             for i in range(0, nr_trace_entries):
                 addr = self.ramdump.read_word(
-                    page + trace_entries_offset + i * trace_entry_size)
+                    struct_holding_trace_entries + trace_entries_offset + i * trace_entry_size)
 
                 if addr == 0:
                     break
@@ -66,8 +102,8 @@ class PageTracking(RamParser):
                 if look is None:
                     break
                 symname, offset = look
-                unwind_dat = '      [<{0:x}>] {1}+0x{2:x}\n'.format(addr,
-                                                                    symname, offset)
+                unwind_dat = '      [<{0:x}>] {1}+0x{2:x}\n'.format(
+                                        addr, symname, offset)
                 out_tracking.write(unwind_dat)
                 alloc_str = alloc_str + unwind_dat
 
diff --git a/linux-ramdump-parser-v2/parsers/slabinfo.py b/linux-ramdump-parser-v2/parsers/slabinfo.py
index e65fb1504c95cc409ba78f931414868eff9a9fa1..ff9dcaca2563c4d9af904a1e744d8d28c8da2309 100644
--- a/linux-ramdump-parser-v2/parsers/slabinfo.py
+++ b/linux-ramdump-parser-v2/parsers/slabinfo.py
@@ -26,7 +26,26 @@ SLUB_RED_ACTIVE = 0xcc
 POISON_INUSE = 0x5a
 POISON_FREE = 0x6b
 POISON_END = 0xa5
-g_printfreeobjStack = False
+
+FREQUENCY = 0
+CALLSTACK_INDEX = 1
+CALL_STACK = 2
+TRACK_TYPE = 3
+
+# g_Optimization - if false will print :
+# 1. Free objects callstacks
+# 2. Object address range of allocated and FREE objects
+g_Optimization = True
+
+# When optimization is true, below two parameters will be used
+# 1. MAX_NO_OF_CALLSTACK_TO_PRINT : Maximum number of callstacks to print
+# in a slab.
+# 2. CALLSTACK_FREQ_IN_SLAB: Print callstack only if occurance of
+# each unique callstack in a slab is more than particular
+# value(CALLSTACK_FREQ_IN_SLAB)
+
+MAX_NO_OF_CALLSTACK_TO_PRINT = 5
+CALLSTACK_FREQ_IN_SLAB = 10
 
 
 class kmem_cache(object):
@@ -89,6 +108,8 @@ class struct_member_offset(object):
                             'struct page', 'freelist')
         self.sizeof_struct_track = ramdump.sizeof(
                                             'struct track')
+        self.cpu_cache_page_offset = ramdump.field_offset(
+                            'struct kmem_cache_cpu', 'page')
         self.sizeof_void_pointer = ramdump.sizeof(
                                              "void *")
         self.sizeof_unsignedlong = ramdump.sizeof(
@@ -131,7 +152,7 @@ class Slabinfo(RamParser):
             p = obj + slab.inuse
         return p + track_type * track_size
 
-    def extract_callstack(self, ramdump, a, stack, out_file):
+    def extract_callstack(self, ramdump, stack, out_file):
         for a in stack:
             look = ramdump.unwind_lookup(a)
             if look is None:
@@ -159,28 +180,17 @@ class Slabinfo(RamParser):
         if stackstr_len == 0:
             return
         try:
-            self.g_allstacks[stackstr][0] += 1
-            if self.g_allstacks[stackstr][0] > 1:
+            self.g_allstacks[stackstr][FREQUENCY] += 1
+            if self.g_allstacks[stackstr][FREQUENCY] > 1:
                 return
-            self.extract_callstack(self.ramdump, a, stack, out_file)
         except KeyError:
-            if g_printfreeobjStack is False:
+            if g_Optimization is True:
                 if track_type != 0:
-                    # if free object and g_printfreeobjStack is False,
+                    # if free object and g_Optimization is True,
                     # ignore it for printing its call stack
                     return
-            if track_type == 1:
-                out_file.write(
-                        "FREE Call stack index:{0}".format(
-                                                            self.g_index))
-            else:
-                out_file.write(
-                        "ALLOCATED Call stack index:{0}".format(
-                                                                self.g_index))
-            self.extract_callstack(self.ramdump, a, stack, out_file)
-            self.g_allstacks[stackstr] = [1, self.g_index]
+            self.g_allstacks[stackstr] = [1, self.g_index, stack, track_type]
             self.g_index += 1
-            out_file.write('\n')
 
     def print_slab(
                 self, ramdump, slab, page,
@@ -206,13 +216,41 @@ class Slabinfo(RamParser):
                         page, out_file, out_slabs_addrs)
             p = p + slab.size
 
-    def printsummary(self, slabs_output_summary):
+    def printsummary(self, slabs_output_summary, slab_out):
+        nCounter = 0
+        write_output = False
+        str = " Call stack index:{0} frequency: {1}\n"
         sorted_val = sorted(
                             self.g_allstacks.items(),
                             key=operator.itemgetter(1), reverse=True)
-        for key, value in sorted_val:
+
+        if g_Optimization is False:
+            write_output = True
+
+        for key, val in sorted_val:
+            if g_Optimization is True:
+                if nCounter >= MAX_NO_OF_CALLSTACK_TO_PRINT:
+                    break
+                if(
+                    (nCounter < MAX_NO_OF_CALLSTACK_TO_PRINT)
+                        and (val[FREQUENCY] > CALLSTACK_FREQ_IN_SLAB)):
+                        write_output = True
+                else:
+                        write_output = False
+            nCounter = nCounter + 1
+            if write_output is True:
+                if val[TRACK_TYPE] == 1:  # free object
+                    slab_out.write(
+                        "\nFREE" + str.format(
+                                val[CALLSTACK_INDEX], val[FREQUENCY]))
+                else:  # allocated object
+                    slab_out.write(
+                        "\nALLOCATED" + str.format(
+                                val[CALLSTACK_INDEX], val[FREQUENCY]))
+                self.extract_callstack(self.ramdump, val[CALL_STACK], slab_out)
             slabs_output_summary.write(
-                " stack index:{0} frequency:{1}\n".format(value[1], value[0]))
+                " stack index:{0} frequency:{1}\n".format(
+                        val[CALLSTACK_INDEX], val[FREQUENCY]))
 
     def print_slab_page_info(
                 self, ramdump, slab_obj, slab_node, start,
@@ -239,29 +277,31 @@ class Slabinfo(RamParser):
             page = self.ramdump.read_word(page + g_offsetof.page_lru)
 
     def print_per_cpu_slab_info(
-            self, ramdump, slab, slab_node, start, out_file, map_fn):
+            self, ramdump, slab, slab_node, start, out_file, map_fn,
+            out_slabs_addrs):
         page = self.ramdump.read_word(start)
         if page == 0:
             return
         if page is None:
             return
-        page_addr = page_address(self.ramdump, page)
         self.print_slab(
-            self.ramdump, page_addr, slab, page, out_file, map_fn)
+            self.ramdump, slab, page, out_file, map_fn, out_slabs_addrs)
 
     def print_all_objects(
-            self, ramdump, p, free, slab, page, out_file, out_slabs_addrs):
-
-        if free:
-            out_slabs_addrs.write(
-                '\n   Object {0:x}-{1:x} FREE'.format(
+        self, ramdump, p, free, slab, page,
+            out_file, out_slabs_addrs):
+
+        if g_Optimization is False:
+            if free:
+                out_slabs_addrs.write(
+                    '\n   Object {0:x}-{1:x} FREE'.format(
+                                        p, p + slab.size))
+            else:
+                out_slabs_addrs.write(
+                    '\n   Object {0:x}-{1:x} ALLOCATED'.format(
                                     p, p + slab.size))
-        else:
-            out_slabs_addrs.write(
-                '\n   Object {0:x}-{1:x} ALLOCATED'.format(
-                                p, p + slab.size))
         if self.ramdump.is_config_defined('CONFIG_SLUB_DEBUG_ON'):
-            if g_printfreeobjStack is True:
+            if g_Optimization is False:
                 self.print_track(ramdump, slab, p, 0, out_file)
                 self.print_track(ramdump, slab, p, 1, out_file)
             else:
@@ -285,6 +325,7 @@ class Slabinfo(RamParser):
         slab_name_found = False
         original_slab = self.ramdump.address_of('slab_caches')
         cpus = self.ramdump.get_num_cpus()
+
         offsetof = struct_member_offset(self.ramdump)
         self.initializeOffset()
         slab_list_offset = g_offsetof.kmemcache_list
@@ -296,6 +337,16 @@ class Slabinfo(RamParser):
         slab = self.ramdump.read_word(original_slab)
         slabs_output_summary = self.ramdump.open_file('slabs_output.txt')
         out_slabs_addrs = self.ramdump.open_file('out_slabs_addrs.txt')
+        if g_Optimization is True:
+            msg = (
+                    "To optimize slab traverse time,"
+                    "print of object address are skipped."
+                    " Supply option perf_off in command"
+                    "prompt to print object address as well."
+                    )
+
+            out_slabs_addrs.write(msg)
+
         while slab != original_slab:
             slab = slab - slab_list_offset
             slab_obj = kmem_cache(self.ramdump, slab)
@@ -322,6 +373,9 @@ class Slabinfo(RamParser):
             print_out_str(
                 '\nExtracting slab details of : {0}'.format(
                                                                     slab_name))
+            if g_Optimization is False:
+                out_slabs_addrs.write(
+                    '\nslab address of : {0}'.format(slab_name))
             cpu_slab_addr = self.ramdump.read_word(
                                         slab + cpu_slab_offset)
             nr_total_objects = self.ramdump.read_structure_field(
@@ -352,8 +406,7 @@ class Slabinfo(RamParser):
                     self.ramdump, slab_obj,
                     slab_node, cpu_slabn_addr + offsetof.cpu_cache_page_offset,
                     slab_out, map_fn)
-
-            self.printsummary(slabs_output_summary)
+            self.printsummary(slabs_output_summary, slab_out)
             self.g_allstacks.clear()
             if slab_name_found is True:
                 break
@@ -362,13 +415,13 @@ class Slabinfo(RamParser):
         slabs_output_summary.close()
 
     def parse(self):
-        global g_printfreeobjStack
+        global g_Optimization
         slabname = None
         for arg in sys.argv:
             if 'slabname=' in arg:
                 k, slabname = arg.split('=')
-            if 'freeobj' in arg:
-                g_printfreeobjStack = True
+            if 'perf_off' in arg:
+                g_Optimization = False
         slab_out = self.ramdump.open_file('slabs.txt')
         self.validate_slab_cache(slab_out, slabname, self.print_all_objects)
         slab_out.close()
diff --git a/linux-ramdump-parser-v2/parsers/timerlist.py b/linux-ramdump-parser-v2/parsers/timerlist.py
old mode 100755
new mode 100644
index 80510a01f43caa7044c5b4751280b22bd9e109d9..a6ddaecb1496e9885f62d79fdc9fa32a1d160f87
--- a/linux-ramdump-parser-v2/parsers/timerlist.py
+++ b/linux-ramdump-parser-v2/parsers/timerlist.py
@@ -21,13 +21,24 @@ class TimerList(RamParser) :
         super(TimerList, self).__init__(*args)
         self.vectors = {'tv1': 256, 'tv2': 64, 'tv3': 64, 'tv4': 64, 'tv5': 64}
         self.output = []
+        major, minor, patch = self.ramdump.kernel_version
         self.timer_42 = False
-
+        self.timer_jiffies = 'timer_jiffies'
+        self.tvec_base = 'struct tvec_base'
+        self.tvec_bases = 'tvec_bases'
+        self.next_timer = 'next_timer'
+
+        if (major, minor) >= (4, 9):
+            self.vectors = {'vectors': 512}
+            self.timer_jiffies = 'clk'
+            self.tvec_base = 'struct timer_base'
+            self.tvec_bases = 'timer_bases'
+            self.next_timer = 'next_expiry'
         # Timerlist structure changed in kernel 4.2
         # Requires separate processing
-        if self.ramdump.kernel_version[0] >= 4:
-            if self.ramdump.kernel_version[1] >= 2:
-                self.timer_42 = True
+        if (major, minor) >= (4, 2):
+            self.timer_42 = True
+
 
     def timer_list_walker(self, node, type, index, base):
         if node == self.head:
@@ -65,7 +76,7 @@ class TimerList(RamParser) :
         self.output.append(output)
 
     def iterate_vec(self, type, base):
-        vec_addr = base + self.ramdump.field_offset('struct tvec_base', type)
+        vec_addr = base + self.ramdump.field_offset(self.tvec_base, type)
         for i in range(0, self.vectors[type]):
             index = self.ramdump.array_index(vec_addr, 'struct list_head', i)
             self.head = index
@@ -74,7 +85,7 @@ class TimerList(RamParser) :
             timer_list_walker.walk(index, self.timer_list_walker, type, i, base)
 
     def iterate_vec_v2(self, type, base):
-        vec_addr = base + self.ramdump.field_offset('struct tvec_base', type)
+        vec_addr = base + self.ramdump.field_offset(self.tvec_base, type)
         for i in range(0, self.vectors[type]):
             index = self.ramdump.array_index(vec_addr, 'struct hlist_head', i)
             self.head = index
@@ -101,14 +112,14 @@ class TimerList(RamParser) :
 
         tvec_base_deferral_addr = self.ramdump.address_of('tvec_base_deferrable')
         if tvec_base_deferral_addr:
-            timer_jiffies_addr = tvec_base_deferral_addr + self.ramdump.field_offset('struct tvec_base', 'timer_jiffies')
-            next_timer_addr = tvec_base_deferral_addr + self.ramdump.field_offset('struct tvec_base', 'next_timer')
+            timer_jiffies_addr = tvec_base_deferral_addr + self.ramdump.field_offset(self.tvec_base, self.timer_jiffies)
+            next_timer_addr = tvec_base_deferral_addr + self.ramdump.field_offset(self.tvec_base, self.next_timer)
 
             timer_jiffies = self.ramdump.read_word(timer_jiffies_addr)
             next_timer = self.ramdump.read_word(next_timer_addr)
-            active_timers_offset = self.ramdump.field_offset('struct tvec_base', 'active_timers')
+            active_timers_offset = self.ramdump.field_offset(self.tvec_base, 'active_timers')
             if active_timers_offset is not None:
-                    active_timers_addr = tvec_base_deferral_addr + self.ramdump.field_offset('struct tvec_base', 'active_timers')
+                    active_timers_addr = tvec_base_deferral_addr + self.ramdump.field_offset(self.tvec_base, 'active_timers')
                     active_timers = self.ramdump.read_word(active_timers_addr)
             else:
                     active_timers = "NA"
@@ -127,8 +138,7 @@ class TimerList(RamParser) :
                      self.iterate_vec(vec, tvec_base_deferral_addr)
                 self.print_vec(vec)
 
-        tvec_bases_addr = self.ramdump.address_of('tvec_bases')
-
+        tvec_bases_addr = self.ramdump.address_of(self.tvec_bases)
         for cpu in range(0, self.ramdump.get_num_cpus()):
             title = "CPU {0}".format(cpu)
 
@@ -140,14 +150,14 @@ class TimerList(RamParser) :
 
             title += "(tvec_base: {0:x} ".format(base)
 
-            timer_jiffies_addr = base + self.ramdump.field_offset('struct tvec_base', 'timer_jiffies')
-            next_timer_addr = base + self.ramdump.field_offset('struct tvec_base', 'next_timer')
+            timer_jiffies_addr = base + self.ramdump.field_offset(self.tvec_base, self.timer_jiffies)
+            next_timer_addr = base + self.ramdump.field_offset(self.tvec_base, self.next_timer)
 
             timer_jiffies = self.ramdump.read_word(timer_jiffies_addr)
             next_timer = self.ramdump.read_word(next_timer_addr)
-            active_timers_offset = self.ramdump.field_offset('struct tvec_base', 'active_timers')
+            active_timers_offset = self.ramdump.field_offset(self.tvec_base, 'active_timers')
             if active_timers_offset is not None:
-                active_timers_addr = base + self.ramdump.field_offset('struct tvec_base', 'active_timers')
+                active_timers_addr = base + self.ramdump.field_offset(self.tvec_base, 'active_timers')
                 active_timers = self.ramdump.read_word(active_timers_addr)
             else:
                 active_timers = "NA"
diff --git a/linux-ramdump-parser-v2/ramdump.py b/linux-ramdump-parser-v2/ramdump.py
index 289b850cde1e491610f1cf7cf64e97879c37c92d..e0a379cd4d5c11884d38dfd6e1c1885af2fab48c 100755
--- a/linux-ramdump-parser-v2/ramdump.py
+++ b/linux-ramdump-parser-v2/ramdump.py
@@ -590,6 +590,7 @@ class RamDump():
         if self.kimage_voffset is not None:
             self.kimage_voffset = self.kimage_vaddr - self.phys_offset
             self.modules_end = self.kimage_vaddr
+            print_out_str("The kimage_voffset extracted is: {:x}".format(self.kimage_voffset))
 
         # The address of swapper_pg_dir can be used to determine
         # whether or not we're running with LPAE enabled since an
@@ -695,6 +696,16 @@ class RamDump():
             sys.exit(1)
         return f
 
+    def remove_file(self, file_name):
+	file_path = os.path.join(self.outdir, file_name)
+	try:
+	    if (os.path.exists(file_path)):
+		os.remove(file_path)
+	except:
+	    print_out_str('Could not remove file {0}'.format(file_path))
+	    print_out_str('Do you have write/read permissions on the path?')
+	    sys.exit(1)
+
     def get_config(self):
         kconfig_addr = self.address_of('kernel_config_data')
         if kconfig_addr is None:
@@ -1264,6 +1275,11 @@ class RamDump():
         s = self.read_string(addr_or_name, '<?', virtual, cpu)
         return s[0] if s is not None else None
 
+    def read_s64(self, addr_or_name, virtual=True, cpu=None):
+        """returns a value guaranteed to be 64 bits"""
+        s = self.read_string(addr_or_name, '<q', virtual, cpu)
+        return s[0] if s is not None else None
+
     def read_u64(self, addr_or_name, virtual=True, cpu=None):
         """returns a value guaranteed to be 64 bits"""
         s = self.read_string(addr_or_name, '<Q', virtual, cpu)
@@ -1302,6 +1318,9 @@ class RamDump():
         """reads a 4 or 8 byte field from a structure"""
         size = self.sizeof("(({0} *)0)->{1}".format(struct_name, field))
         virt = self.resolve_virt(addr_or_name)
+        if virt is None or size is None:
+            return None
+
         if size == 4:
             return self.read_u32(virt + self.field_offset(struct_name,
                                                                   field))
diff --git a/linux-ramdump-parser-v2/tlbdumplib.py b/linux-ramdump-parser-v2/tlbdumplib.py
new file mode 100644
index 0000000000000000000000000000000000000000..03e9f77793224c1e9bb5b85e80d0c84c715618b3
--- /dev/null
+++ b/linux-ramdump-parser-v2/tlbdumplib.py
@@ -0,0 +1,398 @@
+# 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
+
+class L1_TLB_KRYO3XX_GOLD(TlbDumpType_v2):
+    def __init__(self):
+        super(L1_TLB_KRYO3XX_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_l = data[2] >> 14
+        pa_h =  (data[3])& 0x1fff
+        pa = (pa_h << 18 | pa_l) * 0x1000
+        pa = pa + offset
+
+        va_l = (data[1] >> 10)
+        va_h = (data[2]) & 0x3ff
+        va = ((va_h << 22) | (va_l)) * 0x1000
+        va = va + offset
+
+        if ((va >> 40) & 0xff )== 0xff:
+            va = va + 0xffff000000000000
+
+        valid = (data[2] >> 11) & 0x1
+
+        vmid_1 = (data[0] >> 26) & 0x3f
+        vmid_2 = data[1] & 0x3ff
+        vmid = (vmid_2 << 6) | vmid_1
+
+        asid = (data[0] >> 10) & 0xffff
+
+        size = self.parse_size(data, ram, tlb_type)
+        output.append(ram)
+        output.append("N/A")
+        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 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"
+
+class L1_TLB_KRYO3XX_SILVER(TlbDumpType_v1):
+    def __init__(self):
+        super(L1_TLB_KRYO3XX_SILVER, self).__init__()
+        self.unsupported_header_offset = 0
+        self.LineSize = 4
+        self.NumSets = 0x100
+        self.NumWays = 4
+
+# "sdm845"
+lookuptable[("sdm845", 0x20, 0x14)] = L1_TLB_KRYO3XX_SILVER()
+lookuptable[("sdm845", 0x21, 0x14)] = L1_TLB_KRYO3XX_SILVER()
+lookuptable[("sdm845", 0x22, 0x14)] = L1_TLB_KRYO3XX_SILVER()
+lookuptable[("sdm845", 0x23, 0x14)] = L1_TLB_KRYO3XX_SILVER()
+lookuptable[("sdm845", 0x24, 0x14)] = L1_TLB_KRYO3XX_GOLD()
+lookuptable[("sdm845", 0x25, 0x14)] = L1_TLB_KRYO3XX_GOLD()
+lookuptable[("sdm845", 0x26, 0x14)] = L1_TLB_KRYO3XX_GOLD()
+lookuptable[("sdm845", 0x27, 0x14)] = L1_TLB_KRYO3XX_GOLD()
+
+# "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()
+
diff --git a/linux-ramdump-parser-v2/watchdog_v2.py b/linux-ramdump-parser-v2/watchdog_v2.py
index c9e856e8513de3c531534ae985cd0a2777c9d9cd..f74a42a6aed63d23958879dbd714497eeebd525f 100755
--- a/linux-ramdump-parser-v2/watchdog_v2.py
+++ b/linux-ramdump-parser-v2/watchdog_v2.py
@@ -12,7 +12,6 @@
 import struct
 import re
 
-from scandump_reader import Scandump_v2
 from print_out import print_out_str
 from bitops import is_set
 from parser_util import register_parser, RamParser
@@ -696,7 +695,7 @@ class TZCpuCtx_v2():
 
 class TZRegDump_v2():
 
-    def __init__(self, has_scan_dump):
+    def __init__(self):
         self.core_regs = None
         self.sec_regs = None
         self.neon_regs = {}
@@ -706,7 +705,6 @@ class TZRegDump_v2():
         self.core = 0
         self.status = []
         self.neon_fields = []
-        self.has_scan_dump = has_scan_dump
 
     def dump_all_regs(self, ram_dump):
         coren_regs = ram_dump.open_file('core{0}_regs.cmm'.format(self.core))
@@ -819,21 +817,9 @@ class TZRegDump_v2():
             self.start_addr += struct.calcsize(
                 sysdbg_cpu32_ctxt_regs_type[self.version])
 
-        if self.has_scan_dump:
-           if core > 3:
-              self.scan_data = Scandump_v2(self.core, ram_dump, self.version)
-              self.scan_regs = self.scan_data.prepare_dict()
-        else:
-           print_out_str("No Scan dump data to be processed...")
-
         self.core_regs = TZCpuCtx_v2(self.version, sc_regs,
                                      self.neon_regs, ram_dump)
 
-        if core > 3:
-            if self.has_scan_dump:
-               self.scan_regs['pc'] = self.core_regs.regs['pc']
-               self.core_regs.regs = self.scan_regs
-
         self.sec_regs = TZCpuCtx_v2(self.version, sc_secure,
                                     self.neon_regs, ram_dump)
         return True