Merge 1cb6ffe550e9a7c146098ce612212fe362efbfba on remote branch
Change-Id: I2600cc3649bff08f5af6407f97cb2146aa73cf0c
diff --git a/dcc_parser/dcc_parser.py b/dcc_parser/dcc_parser.py
index 406f101..7a77851 100644
--- a/dcc_parser/dcc_parser.py
+++ b/dcc_parser/dcc_parser.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2015, 2017, 2019-2020 The Linux Foundation. All rights reserved.
+# Copyright (c) 2015, 2017, 2019-2021 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
@@ -81,6 +81,7 @@
def read_config(config_pt):
offset = 0
base = 0
+ length = 1
list_nr.append(0)
count = 0
if options.version is None:
diff --git a/linux-ramdump-parser-v2/debug_image_v2.py b/linux-ramdump-parser-v2/debug_image_v2.py
index b4a8b20..b0c3260 100644
--- a/linux-ramdump-parser-v2/debug_image_v2.py
+++ b/linux-ramdump-parser-v2/debug_image_v2.py
@@ -161,7 +161,6 @@
def __init__(self, ramdump):
self.qdss = QDSSDump()
self.dump_type_lookup_table = []
- self.dump_table_id_lookup_table = []
self.dump_data_id_lookup_table = {}
if ramdump.kernel_version > (3, 9, 9):
self.event_call = 'struct trace_event_call'
@@ -243,8 +242,6 @@
def parse_cpu_ctx(self, version, start, end, client_id, ram_dump):
core = client_id - client.MSM_DUMP_DATA_CPU_CTX
- print_out_str(
- 'Parsing CPU{2} context start {0:x} end {1:x} version {3} client_id-> {4}'.format(start, end, core,version,client_id))
if version == 32 or version == "32":
try:
cpu_type_offset = ram_dump.field_offset(
@@ -283,12 +280,14 @@
'struct msm_dump_cpu_register_entry', 'regset_addr')
if regset_addr_offset is None:
regset_addr_offset = 0x8
-
+ cpu_index = ram_dump.read_u32(start + cpu_index_offset,False)
+
+ print_out_str(
+ 'Parsing CPU{2:x} context start {0:x} end {1:x} version {3} client_id-> {4:x}'.format(start, end, cpu_index,version,client_id))
cpu_type = ram_dump.read_u32(start + cpu_type_offset,False)
print_out_str("cpu_type = {0}".format(msm_dump_cpu_type[cpu_type]))
ctx_type = ram_dump.read_u32(start + ctx_type_offset,False)
print_out_str("ctx_type = {0}".format(msm_dump_ctx_type[ctx_type]))
- cpu_index = ram_dump.read_u32(start + cpu_index_offset,False)
print_out_str("cpu_index = {0}".format(cpu_index))
regset_num_register = ram_dump.read_u32(start + regset_num_register_offset,False)
registers = start + registers_offset
@@ -534,9 +533,7 @@
self.formats_out.write("print fmt: {0}\n".format(fmt_str))
def collect_ftrace_format(self, ram_dump):
- formats = os.path.join('qtf', 'map_files', 'formats.txt')
- formats_out = ram_dump.open_file(formats)
- self.formats_out = formats_out
+ self.formats_out = ram_dump.open_file('formats.txt')
ftrace_events_list = ram_dump.address_of('ftrace_events')
next_offset = ram_dump.field_offset(self.event_call, 'list')
@@ -545,166 +542,6 @@
self.formats_out.close
- def wait_for_completion_timeout(self, task, timeout):
- delay = 2.0
- #while the process is still executing and we haven't timed-out yet
- while task.poll() is None and timeout > 0:
- time.sleep(delay)
- timeout -= delay
- if timeout <= 0:
- print_out_str("QTF command timed out")
- task.kill()
-
- def parse_qtf(self, ram_dump):
- out_dir = ram_dump.outdir
- if platform.system() != 'Windows':
- return
-
- qtf_path = ram_dump.qtf_path
- if qtf_path is None:
- try:
- import local_settings
- try:
- qtf_path = local_settings.qtf_path
- except AttributeError as e:
- print_out_str("attribute qtf_path in local_settings.py looks bogus. Please see README.txt")
- print_out_str("Full message: %s" % e.message)
- return
- except ImportError:
- print_out_str("missing qtf_path local_settings.")
- print_out_str("Please see the README for instructions on setting up local_settings.py")
- return
-
- if qtf_path is None:
- print_out_str("!!! Incorrect path for qtf specified.")
- print_out_str("!!! Please see the README for instructions on setting up local_settings.py")
- return
-
- if not os.path.exists(qtf_path):
- print_out_str("!!! qtf_path {0} does not exist! Check your settings!".format(qtf_path))
- return
-
- if not os.access(qtf_path, os.X_OK):
- print_out_str("!!! No execute permissions on qtf path {0}".format(qtf_path))
- return
-
- if os.path.getsize(os.path.join(out_dir, 'tmc-etf.bin')) > 0:
- trace_file = os.path.join(out_dir, 'tmc-etf.bin')
- elif os.path.getsize(os.path.join(out_dir, 'tmc-etr.bin')) > 0:
- trace_file = os.path.join(out_dir, 'tmc-etr.bin')
- else:
- return
-
- port = None
- server_proc = None
- qtf_success = False
- max_tries = 3
- qtf_dir = os.path.join(out_dir, 'qtf')
- workspace = os.path.join(qtf_dir, 'qtf.workspace')
- qtf_out = os.path.join(out_dir, 'qtf.txt')
- chipset = ram_dump.hw_id
- if "sdm" not in ram_dump.hw_id.lower() and \
- "qcs" not in ram_dump.hw_id.lower():
- chipset = "msm" + ram_dump.hw_id
- hlos = 'LA'
-
- #Temp change to handle descripancy between tools usage
- if chipset == 'msmcobalt':
- chipset = 'msm8998'
-
- # Resolve any port collisions with other running qtf_server instances
- for tries in range(max_tries):
- port = random.randint(12000, 13000)
- server_proc = subprocess.Popen(
- [qtf_path, '-s', '{:d}'.format(port)], shell=True,stderr=subprocess.PIPE)
- time.sleep(15)
- server_proc.poll()
- if server_proc.returncode == 1:
- server_proc.terminate()
- continue
- else:
- qtf_success = True
- break
- if not qtf_success:
- server_proc.terminate()
- print_out_str('!!! Could not open a QTF server instance with a '
- 'unique port (last port tried: '
- '{0})'.format(str(port)))
- print_out_str('!!! Please kill all currently running qtf_server '
- 'processes and try again')
- return
- #subprocess.call('{0} -c {1} new workspace {2} {3} {4}'.format(qtf_path, port, qtf_dir, chipset, hlos))
- server_proc1 = subprocess.Popen(
- [qtf_path, '-c', '{:d}'.format(port),'new workspace {0} {1} {2}'.format(qtf_dir, chipset, hlos)], shell=True,stderr=subprocess.PIPE,stdout=subprocess.PIPE)
- server_proc1.communicate()
- self.collect_ftrace_format(ram_dump)
- server_proc1.kill()
-
- p = subprocess.Popen('{0} -c {1} open workspace {2}'.format(qtf_path, port, workspace))
- self.wait_for_completion_timeout(p,60)
- p = subprocess.Popen('{0} -c {1} open bin {2}'.format(qtf_path, port, trace_file))
- self.wait_for_completion_timeout(p,90)
- p = subprocess.Popen('{0} -c {1} stream trace table {2}'.format(qtf_path, port, qtf_out))
- self.wait_for_completion_timeout(p,300)
- p = subprocess.Popen('{0} -c {1} close'.format(qtf_path, port))
- self.wait_for_completion_timeout(p,60)
- p = subprocess.Popen('{0} -c {1} exit'.format(qtf_path, port))
- self.wait_for_completion_timeout(p,60)
- try:
- import psutil
- pid = server_proc.pid
- pid = int(pid)
- parent = psutil.Process(pid)
- # or parent.children() for recursive=False
- for child in parent.children(recursive=True):
- print_out_str("child process = {0} which needs to be killed forcefully after QTF timeout".format(child))
- if (psutil.pid_exists(child.pid)):
- try:
- child.kill()
- except Exception as e:
- print_out_str("Error: {0} while killing the child of QTF process".format(e))
- pass
- server_proc.kill()
- except Exception as e1:
- print_out_str("psutil module import error = {0}".format(e1))
- pass
-
- def parse_dcc(self, ram_dump):
- out_dir = ram_dump.outdir
- if ram_dump.ram_addr is None:
- bin_dir = ram_dump.autodump
- else:
- bin_dir = ram_dump.ram_addr
- bin_dir="\\".join(bin_dir[0][0].split('\\')[:-1])
- dcc_parser_path = os.path.join(os.path.dirname(__file__), '..', 'dcc_parser', 'dcc_parser.py')
- if dcc_parser_path is None:
- print_out_str("!!! Incorrect path for DCC specified.")
- return
-
- if not os.path.exists(dcc_parser_path):
- print_out_str("!!! dcc_parser_path {0} does not exist! Check your settings!".format(dcc_parser_path))
- return
-
- if (os.path.isfile(os.path.join(bin_dir, 'DCC_SRAM.BIN'))):
- sram_file = os.path.join(bin_dir, 'DCC_SRAM.BIN')
- cmd = [sys.executable, dcc_parser_path, "-s" , sram_file, "--out-dir", out_dir, "--config-offset", "0x6000", "--v2"]
- p = subprocess.Popen(cmd, stdout=subprocess.PIPE,
- stderr=subprocess.STDOUT,
- universal_newlines=True)
- print_out_str('--------')
- print_out_str(p.communicate()[0])
- elif os.path.isfile(os.path.join(out_dir, 'sram.bin')):
- sram_file = os.path.join(out_dir, 'sram.bin')
- p = subprocess.Popen([sys.executable, dcc_parser_path, '-s', sram_file, '--out-dir', out_dir],
- stdout=subprocess.PIPE,
- stderr=subprocess.STDOUT,
- universal_newlines=True)
- print_out_str('--------')
- print_out_str(p.communicate()[0])
- else:
- print_out_str('DCC SRAM data is not populated!!')
- return
-
def parse_sysreg(self,ram_dump):
out_dir = ram_dump.outdir
sysreg_parser_path_minidump = os.path.join(os.path.dirname(__file__), '..', 'dcc_parser',
@@ -841,8 +678,6 @@
def parse_dump_v2(self, ram_dump):
self.dump_type_lookup_table = ram_dump.gdbmi.get_enum_lookup_table(
'msm_dump_type', 2)
- self.dump_table_id_lookup_table = ram_dump.gdbmi.get_enum_lookup_table(
- 'msm_dump_table_ids', MAX_NUM_ENTRIES)
cpus = ram_dump.get_num_cpus()
# per cpu entries
for i in range(0, cpus):
@@ -978,11 +813,6 @@
entry_type = ram_dump.read_u32(this_entry + dump_entry_type_offset, virtual = False)
entry_addr = ram_dump.read_word(this_entry + dump_entry_addr_offset, virtual = False)
- if entry_id < 0 or entry_id > len(self.dump_table_id_lookup_table):
- print_out_str(
- '!!! Invalid dump table entry id found {0:x}'.format(entry_id))
- continue
-
if entry_type > len(self.dump_type_lookup_table):
print_out_str(
'!!! Invalid dump table entry type found {0:x}'.format(entry_type))
@@ -1000,8 +830,8 @@
return
print_out_str(
- 'Debug image version: {0}.{1} Entry id: {2} Entry type: {3} Number of entries: {4}'.format(
- table_version >> 20, table_version & 0xFFFFF, self.dump_table_id_lookup_table[entry_id],
+ 'Debug image version: {0}.{1} Entry type: {2} Number of entries: {3}'.format(
+ table_version >> 20, table_version & 0xFFFFF,
self.dump_type_lookup_table[entry_type], table_num_entries))
lst = self.sorted_dump_data_clients(
@@ -1090,10 +920,6 @@
entry_pa_addr = ram_dump.read_u64(this_entry + dump_entry_pa_offset)
entry_size = ram_dump.read_u64(this_entry + dump_entry_size_offset)
- if entry_id < 0 or entry_id > len(self.dump_table_id_lookup_table):
- print_out_str(
- '!!! Invalid dump table entry id found {0:x}'.format(entry_id))
- continue
end_addr = entry_pa_addr + entry_size
minidump_dump_table_value = dict(minidump_dump_table_type)
if entry_pa_addr in ram_dump.ebi_pa_name_map:
@@ -1109,8 +935,6 @@
getattr(DebugImage_v2, func)(
self, 20, client_entry,
client_end, client_id, ram_dump)
-
- self.parse_dcc(ram_dump)
if ram_dump.sysreg:
self.parse_sysreg(ram_dump)
self.qdss.dump_standard(ram_dump)
@@ -1118,6 +942,6 @@
self.qdss.save_etf_bin(ram_dump)
self.qdss.save_etf_swao_bin(ram_dump)
self.qdss.save_etr_bin(ram_dump)
- if ram_dump.qtf:
- self.parse_qtf(ram_dump)
+ if ram_dump.ftrace_format:
+ self.collect_ftrace_format(ram_dump)
diff --git a/linux-ramdump-parser-v2/mm.py b/linux-ramdump-parser-v2/mm.py
index 2beeef2..45d1aa9 100644
--- a/linux-ramdump-parser-v2/mm.py
+++ b/linux-ramdump-parser-v2/mm.py
@@ -382,6 +382,22 @@
self.rd = ramdump
self.SECTION_SIZE_BITS = 0
+ def lookup_page_ext(self, pfn):
+ if not self.rd.is_config_defined('CONFIG_PAGE_EXTENSION'):
+ return None
+
+ if not self.rd.is_config_defined('CONFIG_SPARSEMEM'):
+ contig_page_data = self.rd.address_of('contig_page_data')
+ offset = self.rd.field_offset('struct pglist_data', 'node_page_ext')
+ page_ext = self.rd.read_word(contig_page_data + offset)
+ else:
+ mem_section = pfn_to_section(self.rd, pfn)
+ offset = self.rd.field_offset('struct mem_section', 'page_ext')
+ page_ext = self.rd.read_word(mem_section + offset)
+
+ return page_ext
+
+
class Sparsemem:
def __init__(self, ramdump):
self.rd = ramdump
@@ -399,16 +415,26 @@
sections_per_root = 4096 // memsection_struct_size
root_nr = section_nr // sections_per_root
section_nr = section_nr % sections_per_root
- mem_section_base = ramdump.read_word('mem_section')
- if ramdump.is_config_defined('CONFIG_SPARSEMEM_EXTREME'):
- #struct mem_section *mem_section[NR_SECTION_ROOTS];
+ if ramdump.is_config_defined('CONFIG_SPARSEMEM_EXTREME') and \
+ ramdump.kernel_version >= (4, 14):
+ #struct mem_section **mem_section
+ mem_section_base = ramdump.read_word('mem_section')
+ offset = pointer_size * root_nr
+ ptr = ramdump.read_word(mem_section_base + offset)
+ offset = memsection_struct_size * section_nr
+ mem_section_ptr = ptr + offset
+ elif ramdump.is_config_defined('CONFIG_SPARSEMEM_EXTREME') and \
+ ramdump.kernel_version < (4, 14):
+ #struct mem_section *mem_section[NR_SECTION_ROOTS]
+ mem_section_base = ramdump.address_of('mem_section')
offset = pointer_size * root_nr
ptr = ramdump.read_word(mem_section_base + offset)
offset = memsection_struct_size * section_nr
mem_section_ptr = ptr + offset
else:
#struct mem_section mem_section[NR_SECTION_ROOTS][SECTIONS_PER_ROOT];
+ mem_section_base = ramdump.address_of('mem_section')
offset = memsection_struct_size * (section_nr + root_nr * sections_per_root)
mem_section_ptr = mem_section_base + offset
diff --git a/linux-ramdump-parser-v2/parsers/ftrace.py b/linux-ramdump-parser-v2/parsers/ftrace.py
index e8907b7..e21cd7d 100644
--- a/linux-ramdump-parser-v2/parsers/ftrace.py
+++ b/linux-ramdump-parser-v2/parsers/ftrace.py
@@ -311,7 +311,7 @@
ftrace_file_map["007"] = ftrace_core7_fd
sorted_dict = {k: ftrace_time_data[k] for k in sorted(ftrace_time_data)}
- for key in sorted_dict.keys():
+ for key in sorted(sorted_dict.keys()):
line = str(ftrace_time_data[key])
if "sched_switch:" in line:
cpu_number = line.split("[")[1]
diff --git a/linux-ramdump-parser-v2/parsers/ftrace_event.py b/linux-ramdump-parser-v2/parsers/ftrace_event.py
index 06e9159..5625f5c 100644
--- a/linux-ramdump-parser-v2/parsers/ftrace_event.py
+++ b/linux-ramdump-parser-v2/parsers/ftrace_event.py
@@ -550,105 +550,109 @@
fmt_str = fmt_str.replace('work struct','work_struct')
offset_data = event_data[0]
fmt_name_value_map = OrderedDict()
- d = str(fmt_str.split('",')[1].replace("'", ''))
- pr = str(fmt_str.split('",')[0].replace("'", ''))
- pr = str(pr.split('",')[0].replace('"', ''))
- pr = str(pr.split('",')[0].replace('[', ''))
- pr = str(pr.split('",')[0].replace(']', ''))
- if "cpuhp_latency" == event_name:
- pr = pr.replace("USEC ret: %d","USEC_ret:%d")
- if "thermal_device_update" == event_name:
- pr = pr.replace("received event","received_event")
- temp_a = []
- for ii in d.split(","):
- ii = str(ii).replace("'","").replace(" ","")
- temp_a.append(ii)
- j = 0
- temp_a = []
- pr_f = []
- if "workqueue_execute" in event_name:
- for ki in pr.split(": "):
- pr_f.append(str(ki))
- else:
- if ", " in pr and event_name != 'user_fault':
- for ki in pr.split(", "):
- if len(ki) >= 1:
- pr_f.append(str(ki).replace(" ",""))
+ try:
+ d = str(fmt_str.split('",')[1].replace("'", ''))
+ pr = str(fmt_str.split('",')[0].replace("'", ''))
+ pr = str(pr.split('",')[0].replace('"', ''))
+ pr = str(pr.split('",')[0].replace('[', ''))
+ pr = str(pr.split('",')[0].replace(']', ''))
+ if "cpuhp_latency" == event_name:
+ pr = pr.replace("USEC ret: %d","USEC_ret:%d")
+ if "thermal_device_update" == event_name:
+ pr = pr.replace("received event","received_event")
+ temp_a = []
+ for ii in d.split(","):
+ ii = str(ii).replace("'","").replace(" ","")
+ temp_a.append(ii)
+ j = 0
+ temp_a = []
+ pr_f = []
+ if "workqueue_execute" in event_name:
+ for ki in pr.split(": "):
+ pr_f.append(str(ki))
else:
- for ki in pr.split(" "):
- if len(ki) >= 1:
- pr_f.append(str(ki).replace(" ",""))
- for item,item_list in offset_data.items():
- type_str,offset,size = item_list
- if 'unsigned char' in type_str or 'long' in type_str or 'int' in type_str or 'u32' in type_str or 'bool' in type_str or 'pid_t' in type_str:
- v = self.ramdump.read_u32(ftrace_raw_entry + offset)
- fmt_name_value_map[item] = v
- elif 'char' in type_str or '__data_loc char' in type_str or 'const char *' in type_str or '__data_loc char[]' in type_str:
- if '__data_loc' in type_str:
+ if ", " in pr and event_name != 'user_fault':
+ for ki in pr.split(", "):
+ if len(ki) >= 1:
+ pr_f.append(str(ki).replace(" ",""))
+ else:
+ for ki in pr.split(" "):
+ if len(ki) >= 1:
+ pr_f.append(str(ki).replace(" ",""))
+ for item,item_list in offset_data.items():
+ type_str,offset,size = item_list
+ if 'unsigned char' in type_str or 'long' in type_str or 'int' in type_str or 'u32' in type_str or 'bool' in type_str or 'pid_t' in type_str:
v = self.ramdump.read_u32(ftrace_raw_entry + offset)
- v = self.ramdump.read_cstring(ftrace_raw_entry + (v & 0xffff), (v >> 16))
- if isinstance(v, bytes):
- v = self.ramdump.read_cstring(ftrace_raw_entry + (offset*4))
- else:
- v = self.ramdump.read_cstring(ftrace_raw_entry + offset)
- fmt_name_value_map[item] = v
- elif 'unsigned long' in type_str or 'u64' in type_str or 'void *' in type_str:
- if self.ramdump.arm64:
- v = self.ramdump.read_u64(ftrace_raw_entry + offset)
- else:
- v = self.ramdump.read_u32(ftrace_raw_entry + offset)
- if "func" not in item:
- fmt_name_value_map[item] = hex(int(v))
- else:
fmt_name_value_map[item] = v
- elif 'unsigned short' in type_str or 'u16' in type_str:
- v = self.ramdump.read_u16(ftrace_raw_entry + offset)
- fmt_name_value_map[item] = v
- elif 'short' in type_str or 'signed short' in type_str or 's16' in type_str:
- v = self.ramdump.read_s32(ftrace_raw_entry + offset)
- fmt_name_value_map[item] = v
- elif 's64' in type_str:
- v = self.ramdump.read_s64(ftrace_raw_entry + offset)
- fmt_name_value_map[item] = v
- else:
- v = self.ramdump.read_u32(ftrace_raw_entry + offset)
- fmt_name_value_map[item] = v
-
- if "softirq" in event_name:
- if v > len(softirq_action_list) -1:
- action = v
- else:
- action = softirq_action_list[v]
- fmt_name_value_map['action'] = action
- temp_a.append(v)
- j = j + 1
- temp = ""
- t1 = len(temp_a)
- t2 = len(pr_f)
- f = False
- try:
- for keyinfo in fmt_name_value_map:
- if "function" == keyinfo:
- wq_function1 = self.ramdump.get_symbol_info1(fmt_name_value_map[keyinfo])
- tt = keyinfo + "=" + wq_function1
- if "func" in keyinfo:
- wq_function1 = self.ramdump.get_symbol_info1(fmt_name_value_map[keyinfo])
- if wq_function1 and len(wq_function1) > 1 and wq_function1 != 'No':
- tt = keyinfo + "=" + wq_function1
+ elif 'char' in type_str or '__data_loc char' in type_str or 'const char *' in type_str or '__data_loc char[]' in type_str:
+ if '__data_loc' in type_str:
+ v = self.ramdump.read_u32(ftrace_raw_entry + offset)
+ v = self.ramdump.read_cstring(ftrace_raw_entry + (v & 0xffff), (v >> 16))
+ if isinstance(v, bytes):
+ v = self.ramdump.read_cstring(ftrace_raw_entry + (offset*4))
else:
- tt = keyinfo + "=" + str(hex(fmt_name_value_map[keyinfo]))
+ v = self.ramdump.read_cstring(ftrace_raw_entry + offset)
+ fmt_name_value_map[item] = v
+ elif 'unsigned long' in type_str or 'u64' in type_str or 'void *' in type_str:
+ if self.ramdump.arm64:
+ v = self.ramdump.read_u64(ftrace_raw_entry + offset)
+ else:
+ v = self.ramdump.read_u32(ftrace_raw_entry + offset)
+ if "func" not in item:
+ fmt_name_value_map[item] = hex(int(v))
+ else:
+ fmt_name_value_map[item] = v
+ elif 'unsigned short' in type_str or 'u16' in type_str:
+ v = self.ramdump.read_u16(ftrace_raw_entry + offset)
+ fmt_name_value_map[item] = v
+ elif 'short' in type_str or 'signed short' in type_str or 's16' in type_str:
+ v = self.ramdump.read_s32(ftrace_raw_entry + offset)
+ fmt_name_value_map[item] = v
+ elif 's64' in type_str:
+ v = self.ramdump.read_s64(ftrace_raw_entry + offset)
+ fmt_name_value_map[item] = v
else:
- tt = keyinfo + "=" + str(fmt_name_value_map[keyinfo])
- temp = temp + tt + " "
- except Exception as err:
- print_out_str("missing event = {0} err = {1}".format(event_name,str(err)))
- pass
- try:
- temp = temp + "\n"
- temp_data = " {4} {0} {1:.6f}: {2} {3}".format(self.cpu, round(local_timestamp / 1000000000.0, 6),event_name,temp,curr_com)
- t = local_timestamp / 1000000000.0
- self.ftrace_time_data[t] = temp_data
+ v = self.ramdump.read_u32(ftrace_raw_entry + offset)
+ fmt_name_value_map[item] = v
+
+ if "softirq" in event_name:
+ if v > len(softirq_action_list) -1:
+ action = v
+ else:
+ action = softirq_action_list[v]
+ fmt_name_value_map['action'] = action
+ temp_a.append(v)
+ j = j + 1
temp = ""
+ t1 = len(temp_a)
+ t2 = len(pr_f)
+ f = False
+ try:
+ for keyinfo in fmt_name_value_map:
+ if "function" == keyinfo and isinstance(fmt_name_value_map[keyinfo], int):
+ wq_function1 = self.ramdump.get_symbol_info1(fmt_name_value_map[keyinfo])
+ tt = keyinfo + "=" + wq_function1
+ if "func" in keyinfo and isinstance(fmt_name_value_map[keyinfo], int):
+ wq_function1 = self.ramdump.get_symbol_info1(fmt_name_value_map[keyinfo])
+ if wq_function1 and len(wq_function1) > 1 and wq_function1 != 'No':
+ tt = keyinfo + "=" + wq_function1
+ else:
+ tt = keyinfo + "=" + str(hex(fmt_name_value_map[keyinfo]))
+ else:
+ tt = keyinfo + "=" + str(fmt_name_value_map[keyinfo])
+ temp = temp + tt + " "
+ except Exception as err:
+ print_out_str("missing event = {0} err = {1}".format(event_name,str(err)))
+ pass
+ try:
+ temp = temp + "\n"
+ temp_data = " {4} {0} {1:.6f}: {2} {3}".format(self.cpu, round(local_timestamp / 1000000000.0, 6),event_name,temp,curr_com)
+ t = local_timestamp / 1000000000.0
+ self.ftrace_time_data[t] = temp_data
+ temp = ""
+ except Exception as err:
+ print_out_str("missing event = {0} err = {1}".format(event_name,str(err)))
+ pass
except Exception as err:
print_out_str("missing event = {0} err = {1}".format(event_name,str(err)))
pass
diff --git a/linux-ramdump-parser-v2/parsers/gpu/gpu_eventlog.py b/linux-ramdump-parser-v2/parsers/gpu/gpu_eventlog.py
new file mode 100644
index 0000000..65d76e6
--- /dev/null
+++ b/linux-ramdump-parser-v2/parsers/gpu/gpu_eventlog.py
@@ -0,0 +1,222 @@
+# Copyright (c) 2021 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.
+
+from ctypes import c_uint32, c_uint64, c_char, sizeof, Structure
+
+MAGIC = 0xabbaabba
+
+LOG_SKIP = 1
+LOG_FIRE_EVENT = 2
+LOG_CMDBATCH_SUBMITTED_EVENT = 3
+LOG_CMDBATCH_RETIRED_EVENT = 4
+LOG_SYNCPOINT_FENCE_EVENT = 5
+LOG_SYNCPOINT_FENCE_EXPIRE_EVENT = 6
+LOG_TIMELINE_FENCE_ALLOC_EVENT = 7
+LOG_TIMELINE_FENCE_RELEASE_EVENT = 8
+
+KGSL_EVENT_RETIRED = 1
+KGSL_EVENT_CANCELLED = 2
+
+NANO_TO_SEC = 1000000000
+
+
+class fire_event (Structure):
+ _fields_ = [('id', c_uint32),
+ ('ts', c_uint32),
+ ('type', c_uint32),
+ ('age', c_uint32)]
+
+
+class cmdbatch_submitted (Structure):
+ _fields_ = [('id', c_uint32),
+ ('ts', c_uint32),
+ ('prio', c_uint32),
+ ('flags', c_uint64)]
+
+
+class cmdbatch_retired (Structure):
+ _fields_ = [('id', c_uint32),
+ ('ts', c_uint32),
+ ('prio', c_uint32),
+ ('flag', c_uint64),
+ ('start', c_uint64),
+ ('retire', c_uint64)]
+
+
+class syncpoint_fence (Structure):
+ _fields_ = [('id', c_uint32),
+ ('name', c_char*74)]
+
+
+class timeline_fence (Structure):
+ _fields_ = [('id', c_uint32),
+ ('seqno', c_uint64)]
+
+
+def fire_event_write(func_writeln, dump, kgsl_eventlog_buffer, header):
+ if header["payload_size"] != sizeof(fire_event):
+ return True
+ id = dump.read_u32(kgsl_eventlog_buffer + fire_event.id.offset)
+ ts = dump.read_u32(kgsl_eventlog_buffer + fire_event.ts.offset)
+ type = dump.read_u32(kgsl_eventlog_buffer + fire_event.type.offset)
+ age = dump.read_u32(kgsl_eventlog_buffer + fire_event.age.offset)
+ if type == KGSL_EVENT_RETIRED:
+ type = "retired"
+ elif type == KGSL_EVENT_CANCELLED:
+ type = "cancelled"
+
+ format_str = "pid:{0:<12}{1:<16.6f}" \
+ "kgsl_fire_event: ctx={2} ts={3} type={4} age={5}"
+ func_writeln(format_str.format(header["pid"], header["time"],
+ id, ts, type, age))
+ return False
+
+
+def cmdbatch_submitted_event_write(func_writeln, dump, kgsl_eventlog_buffer,
+ header):
+ if header["payload_size"] != sizeof(cmdbatch_submitted):
+ return True
+ id = dump.read_u32(kgsl_eventlog_buffer + cmdbatch_submitted.id.offset)
+ ts = dump.read_u32(kgsl_eventlog_buffer + cmdbatch_submitted.ts.offset)
+ prio = dump.read_u32(kgsl_eventlog_buffer +
+ cmdbatch_submitted.prio.offset)
+ flags = dump.read_u64(kgsl_eventlog_buffer +
+ cmdbatch_submitted.flags.offset)
+ format_str = "pid:{0:<12}{1:<16.6f}" \
+ "adreno_cmdbatch_submitted: ctx={2} ctx_prio={3} " \
+ "ts={4} flags={5}"
+ func_writeln(format_str.format(header["pid"], header["time"],
+ id, prio, ts, flags))
+ return False
+
+
+def cmdbatch_retired_event_write(func_writeln, dump, kgsl_eventlog_buffer,
+ header):
+ if header["payload_size"] != sizeof(cmdbatch_retired):
+ return True
+ id = dump.read_u32(kgsl_eventlog_buffer + cmdbatch_retired.id.offset)
+ ts = dump.read_u32(kgsl_eventlog_buffer + cmdbatch_retired.ts.offset)
+ prio = dump.read_u32(kgsl_eventlog_buffer + cmdbatch_retired.prio.offset)
+ flag = dump.read_u64(kgsl_eventlog_buffer + cmdbatch_retired.flag.offset)
+ start = dump.read_u64(kgsl_eventlog_buffer +
+ cmdbatch_retired.start.offset)
+ retire = dump.read_u64(kgsl_eventlog_buffer +
+ cmdbatch_retired.retire.offset)
+ format_str = "pid:{0:<12}{1:<16.6f}" \
+ "adreno_cmdbatch_retired: ctx={2} ctx_prio={3} " \
+ "ts={4} flags={5} start={6} retire={7}"
+ func_writeln(format_str.format(header["pid"], header["time"], id,
+ prio, ts, flag, start, retire))
+ return False
+
+
+def syncpoint_fence_event_write(func_writeln, dump, kgsl_eventlog_buffer,
+ header):
+ if header["payload_size"] != sizeof(syncpoint_fence):
+ return True
+ id = dump.read_u32(kgsl_eventlog_buffer + syncpoint_fence.id.offset)
+ name = dump.read_cstring(kgsl_eventlog_buffer +
+ syncpoint_fence.name.offset, 74)
+ if header["event_id"] == LOG_SYNCPOINT_FENCE_EVENT:
+ event = "syncpoint_fence"
+ elif header["event_id"] == LOG_SYNCPOINT_FENCE_EXPIRE_EVENT:
+ event = "syncpoint_fence_expire"
+
+ format_str = "pid:{0:<12}{1:<16.6f}" \
+ "{2}: ctx={3} name={4}"
+ func_writeln(format_str.format(header["pid"], header["time"],
+ event, id, name))
+ return False
+
+
+def timeline_fence_event_write(func_writeln, dump, kgsl_eventlog_buffer,
+ header):
+ if header["payload_size"] != sizeof(timeline_fence):
+ return True
+ id = dump.read_u32(kgsl_eventlog_buffer + timeline_fence.id.offset)
+ seqno = dump.read_u64(kgsl_eventlog_buffer + timeline_fence.seqno.offset)
+ if header["event_id"] == LOG_TIMELINE_FENCE_ALLOC_EVENT:
+ event = "kgsl_timeline_fence_alloc"
+ elif header["event_id"] == LOG_TIMELINE_FENCE_RELEASE_EVENT:
+ event = "kgsl_timeline_fence_release"
+
+ format_str = "pid:{0:<12}{1:<16.6f}" \
+ "{2}: timeline={3} seqno={4}"
+ func_writeln(format_str.format(header["pid"], header["time"], event,
+ id, seqno))
+ return False
+
+
+def parse_eventlog_buffer(func_writeln, dump):
+ kgsl_eventlog_buffer = dump.read('kgsl_eventlog')
+ format_str = '{0:<15} {1:<16}{2}'
+ func_writeln(format_str.format("PID", "Timestamp", "Function"))
+ min_timestamp = None
+ offset = 0
+ ret = True
+ header = {}
+ while offset < 8192:
+ header["magic_num"] = dump.read_structure_field(
+ kgsl_eventlog_buffer, 'struct kgsl_log_header',
+ 'magic')
+ header["event_id"] = dump.read_structure_field(
+ kgsl_eventlog_buffer,
+ 'struct kgsl_log_header', 'eventid')
+ header["time"] = dump.read_structure_field(
+ kgsl_eventlog_buffer,
+ 'struct kgsl_log_header', 'time') / NANO_TO_SEC
+ header["pid"] = dump.read_structure_field(
+ kgsl_eventlog_buffer,
+ 'struct kgsl_log_header', 'pid')
+ header["payload_size"] = dump.read_structure_field(
+ kgsl_eventlog_buffer,
+ 'struct kgsl_log_header', 'size')
+
+ if (header["magic_num"] != MAGIC) or (header["event_id"] > 8) or \
+ (header["event_id"] < 1):
+ offset += 1
+ kgsl_eventlog_buffer += 1
+ continue
+
+ if min_timestamp is None:
+ min_timestamp = header["time"]
+
+ kgsl_eventlog_buffer += dump.sizeof('struct kgsl_log_header')
+ if min_timestamp > header["time"]:
+ func_writeln("End of logging".center(90, '-') + '\n')
+ min_timestamp = header["time"]
+ if header["event_id"] == LOG_SKIP:
+ break
+ elif header["event_id"] == LOG_FIRE_EVENT:
+ ret = fire_event_write(func_writeln, dump, kgsl_eventlog_buffer,
+ header)
+ elif header["event_id"] == LOG_CMDBATCH_SUBMITTED_EVENT:
+ ret = cmdbatch_submitted_event_write(func_writeln, dump,
+ kgsl_eventlog_buffer, header)
+ elif header["event_id"] == LOG_CMDBATCH_RETIRED_EVENT:
+ ret = cmdbatch_retired_event_write(func_writeln, dump,
+ kgsl_eventlog_buffer, header)
+ elif (header["event_id"] == LOG_SYNCPOINT_FENCE_EVENT) or \
+ (header["event_id"] == LOG_SYNCPOINT_FENCE_EXPIRE_EVENT):
+ ret = syncpoint_fence_event_write(func_writeln, dump,
+ kgsl_eventlog_buffer, header)
+ elif (header["event_id"] == LOG_TIMELINE_FENCE_ALLOC_EVENT) or \
+ (header["event_id"] == LOG_TIMELINE_FENCE_RELEASE_EVENT):
+ ret = timeline_fence_event_write(func_writeln, dump,
+ kgsl_eventlog_buffer, header)
+ if ret:
+ offset += 1
+ kgsl_eventlog_buffer += 1
+ continue
+
+ offset += dump.sizeof('struct kgsl_log_header') + \
+ header["payload_size"]
+ kgsl_eventlog_buffer += header["payload_size"]
diff --git a/linux-ramdump-parser-v2/parsers/gpu/gpu_snapshot.py b/linux-ramdump-parser-v2/parsers/gpu/gpu_snapshot.py
new file mode 100644
index 0000000..f48c7b3
--- /dev/null
+++ b/linux-ramdump-parser-v2/parsers/gpu/gpu_snapshot.py
@@ -0,0 +1,289 @@
+# Copyright (c) 2021 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.
+
+from ctypes import c_int, c_int64, c_uint, c_ushort, sizeof, Structure
+
+# High word is static, low word is snapshot version ID
+SNAPSHOT_MAGIC = 0x504D0002
+
+# Section header
+SNAPSHOT_SECTION_MAGIC = 0xABCD
+
+# Snapshot Sections
+KGSL_SNAPSHOT_SECTION_OS = 0x0101
+KGSL_SNAPSHOT_SECTION_END = 0xFFFF
+KGSL_SNAPSHOT_SECTION_RB_V2 = 0x0302
+KGSL_SNAPSHOT_SECTION_GPU_OBJECT_V2 = 0x0B02
+KGSL_SNAPSHOT_SECTION_MEMLIST_V2 = 0x0E02
+KGSL_SNAPSHOT_SECTION_MEM_HISTORY = 0x1202
+KGSL_SNAPSHOT_SECTION_IB_V2 = 0x0402
+KGSL_SNAPSHOT_SECTION_REGS = 0x0201
+KGSL_SNAPSHOT_SECTION_MVC = 0x1501
+KGSL_SNAPSHOT_SECTION_INDEXED_REGS = 0x0501
+KGSL_SNAPSHOT_SECTION_DEBUG = 0x0901
+KGSL_SNAPSHOT_SECTION_DEBUGBUS = 0x0A01
+KGSL_SNAPSHOT_SECTION_SHADER = 0x1201
+KGSL_SNAPSHOT_SECTION_GMU = 0x1601
+KGSL_SNAPSHOT_SECTION_GMU_MEMORY = 0x1701
+
+# Ringbuffer
+KGSL_RB_SIZE = (32 * 1024)
+KGSL_RB_DWORDS = (KGSL_RB_SIZE >> 2)
+
+# GMU Sections
+GMU_SECTION_TYPE_OTHER = 0
+GMU_SECTION_TYPE_HFIMEM = 1
+GMU_SECTION_TYPE_LOG = 2
+GMU_SECTION_TYPE_BWMEM = 3
+GMU_SECTION_TYPE_DEBUG = 4
+GMU_SECTION_TYPE_DCACHE = 5
+GMU_SECTION_TYPE_ICACHE = 6
+GMU_SECTION_TYPE_UNCACHE = 7
+GMU_SECTION_TYPE_REASON = 8
+GMU_SECTION_TYPE_VERSION = 9
+
+# GMU Memory Sections
+SNAPSHOT_GMU_MEM_UNKNOWN = 0
+SNAPSHOT_GMU_MEM_HFI = 1
+SNAPSHOT_GMU_MEM_LOG = 2
+SNAPSHOT_GMU_MEM_BWTABLE = 3
+SNAPSHOT_GMU_MEM_DEBUG = 4
+SNAPSHOT_GMU_MEM_BIN_BLOCK = 5
+
+
+# KGSL structures
+class kgsl_snapshot_header(Structure):
+ _pack_ = 1
+ _fields_ = [('magic', c_uint),
+ ('gpuid', c_uint),
+ ('chipid', c_uint)]
+
+
+class kgsl_snapshot_section_header(Structure):
+ _pack_ = 1
+ _fields_ = [('magic', c_ushort),
+ ('id', c_ushort),
+ ('size', c_uint)]
+
+
+class kgsl_snapshot_rb_v2(Structure):
+ _pack_ = 1
+ _fields_ = [('start', c_int),
+ ('end', c_int),
+ ('rbsize', c_int),
+ ('wptr', c_int),
+ ('rptr', c_int),
+ ('count', c_int),
+ ('timestamp_queued', c_uint),
+ ('timestamp_retired', c_uint),
+ ('gpuaddr', c_int64),
+ ('id', c_uint)]
+
+
+class kgsl_snapshot_gmu_mem(Structure):
+ _pack_ = 1
+ _fields_ = [('type', c_int),
+ ('hostaddr', c_int64),
+ ('gmuaddr', c_int64),
+ ('gpuaddr', c_int64)]
+
+
+def gmu_log(devp, dump, chipid):
+ if chipid >= 0x7000000:
+ gmu_dev = dump.sibling_field_addr(devp, 'struct genc_device',
+ 'adreno_dev', 'gmu')
+ gmu_logs = dump.read_structure_field(gmu_dev,
+ 'struct genc_gmu_device',
+ 'gmu_log')
+ else:
+ gmu_dev = dump.sibling_field_addr(devp, 'struct a6xx_device',
+ 'adreno_dev', 'gmu')
+ gmu_logs = dump.read_structure_field(gmu_dev,
+ 'struct a6xx_gmu_device',
+ 'gmu_log')
+
+ gmu_log_hostptr = dump.read_structure_field(gmu_logs,
+ 'struct gmu_memdesc',
+ 'hostptr')
+ gmu_log_size = dump.read_structure_field(gmu_logs,
+ 'struct gmu_memdesc', 'size')
+ gmu_log_gmuaddr = dump.read_structure_field(gmu_logs,
+ 'struct gmu_memdesc',
+ 'gmuaddr')
+ return (gmu_log_hostptr, gmu_log_size, gmu_log_gmuaddr)
+
+
+def hfi_mem(devp, dump, chipid):
+ if chipid >= 0x7000000:
+ gmu_dev = dump.sibling_field_addr(devp, 'struct genc_device',
+ 'adreno_dev', 'gmu')
+ hfi = dump.struct_field_addr(gmu_dev, 'struct genc_gmu_device',
+ 'hfi')
+ hfi_mem = dump.read_structure_field(hfi, 'struct genc_hfi',
+ 'hfi_mem')
+ else:
+ gmu_dev = dump.sibling_field_addr(devp, 'struct a6xx_device',
+ 'adreno_dev', 'gmu')
+ hfi = dump.struct_field_addr(gmu_dev, 'struct a6xx_gmu_device',
+ 'hfi')
+ hfi_mem = dump.read_structure_field(hfi, 'struct a6xx_hfi',
+ 'hfi_mem')
+
+ hfi_mem_hostptr = dump.read_structure_field(hfi_mem,
+ 'struct gmu_memdesc',
+ 'hostptr')
+ hfi_mem_size = dump.read_structure_field(hfi_mem,
+ 'struct gmu_memdesc', 'size')
+ hfi_mem_gmuaddr = dump.read_structure_field(hfi_mem,
+ 'struct gmu_memdesc',
+ 'gmuaddr')
+ return (hfi_mem_hostptr, hfi_mem_size, hfi_mem_gmuaddr)
+
+
+def snapshot_gmu_mem_section(devp, dump, chipid, file, hdr_type):
+ if hdr_type == SNAPSHOT_GMU_MEM_HFI:
+ (gmu_mem_hostptr, gmu_mem_size, gmu_mem_gmuaddr) = hfi_mem(devp, dump,
+ chipid)
+ elif hdr_type == SNAPSHOT_GMU_MEM_LOG:
+ (gmu_mem_hostptr, gmu_mem_size, gmu_mem_gmuaddr) = gmu_log(devp, dump,
+ chipid)
+ else:
+ return
+
+ section_header = kgsl_snapshot_section_header()
+ section_header.magic = SNAPSHOT_SECTION_MAGIC
+ section_header.id = KGSL_SNAPSHOT_SECTION_GMU_MEMORY
+ section_header.size = (gmu_mem_size + sizeof(kgsl_snapshot_gmu_mem) +
+ sizeof(kgsl_snapshot_section_header))
+ file.write(section_header)
+
+ mem_hdr = kgsl_snapshot_gmu_mem()
+ mem_hdr.type = hdr_type
+ mem_hdr.hostaddr = gmu_mem_hostptr
+ mem_hdr.gmuaddr = gmu_mem_gmuaddr
+ mem_hdr.gpuaddr = 0
+ file.write(mem_hdr)
+
+ data = dump.read_binarystring(gmu_mem_hostptr, gmu_mem_size)
+ file.write(data)
+
+
+def snapshot_rb_section(devp, dump, file, rb_type):
+ # Scratch buffer information
+ scratch_obj = dump.read_structure_field(devp,
+ 'struct kgsl_device',
+ 'scratch')
+ scratch_hostptr = dump.read_structure_field(scratch_obj,
+ 'struct kgsl_memdesc',
+ 'hostptr')
+
+ # Memstore information
+ memstore_obj = dump.read_structure_field(devp,
+ 'struct kgsl_device',
+ 'memstore')
+ memstore_hostptr = dump.read_structure_field(memstore_obj,
+ 'struct kgsl_memdesc',
+ 'hostptr')
+
+ # RB information
+ rb = dump.read_structure_field(devp,
+ 'struct adreno_device', rb_type)
+ if (not rb):
+ return
+
+ rb_id = dump.read_structure_field(rb,
+ 'struct adreno_ringbuffer',
+ 'id')
+ rb_wptr = dump.read_structure_field(rb,
+ 'struct adreno_ringbuffer',
+ 'wptr')
+ rb_rptr = dump.read_s32(scratch_hostptr + rb_id * 4)
+ rb_queued_ts = dump.read_structure_field(rb,
+ 'struct adreno_ringbuffer',
+ 'timestamp')
+ rb_buffer_desc = dump.read_structure_field(rb,
+ 'struct adreno_ringbuffer',
+ 'buffer_desc')
+ rb_gpuaddr = dump.read_structure_field(rb_buffer_desc,
+ 'struct kgsl_memdesc',
+ 'gpuaddr')
+ rb_hostptr = dump.read_structure_field(rb_buffer_desc,
+ 'struct kgsl_memdesc',
+ 'hostptr')
+ rb_size = dump.read_structure_field(rb_buffer_desc,
+ 'struct kgsl_memdesc', 'size')
+ rb_retired_ts = dump.read_s32(memstore_hostptr +
+ ((rb_id + 0x32E) * 0x28 + 0x8))
+
+ # RB section
+ section_header = kgsl_snapshot_section_header()
+ section_header.magic = SNAPSHOT_SECTION_MAGIC
+ section_header.id = KGSL_SNAPSHOT_SECTION_RB_V2
+ section_header.size = (KGSL_RB_SIZE + sizeof(kgsl_snapshot_rb_v2) +
+ sizeof(kgsl_snapshot_section_header))
+ file.write(section_header)
+
+ rb_header = kgsl_snapshot_rb_v2()
+ rb_header.start = 0
+ rb_header.end = KGSL_RB_DWORDS
+ rb_header.wptr = rb_wptr
+ rb_header.rptr = rb_rptr
+ rb_header.rbsize = KGSL_RB_DWORDS
+ rb_header.count = KGSL_RB_DWORDS
+ rb_header.timestamp_queued = rb_queued_ts
+ rb_header.timestamp_retired = rb_retired_ts
+ rb_header.gpuaddr = rb_gpuaddr
+ rb_header.id = rb_id
+ file.write(rb_header)
+
+ data = dump.read_binarystring(rb_hostptr, rb_size)
+ file.write(data)
+
+
+def create_snapshot_from_ramdump(devp, dump):
+ # GPU revision
+ gpucore = dump.read_structure_field(devp,
+ 'struct adreno_device',
+ 'gpucore')
+ gpurev = dump.read_structure_field(gpucore,
+ 'struct adreno_gpu_core', 'gpurev')
+
+ # Gpu chip id
+ chipid = dump.read_structure_field(devp,
+ 'struct adreno_device',
+ 'chipid')
+
+ file_name = 'mini_snapshot.bpmd'
+ file = dump.open_file('gpu_parser/' + file_name, 'wb')
+
+ # Dump snapshot header
+ header = kgsl_snapshot_header()
+ header.magic = SNAPSHOT_MAGIC
+ header.gpuid = (0x0003 << 16) | gpurev
+ header.chipid = chipid
+ file.write(header)
+
+ # Dump RBs
+ snapshot_rb_section(devp, dump, file, 'cur_rb')
+ snapshot_rb_section(devp, dump, file, 'prev_rb')
+
+ # Dump GMU info
+ snapshot_gmu_mem_section(devp, dump, chipid, file, SNAPSHOT_GMU_MEM_HFI)
+ snapshot_gmu_mem_section(devp, dump, chipid, file, SNAPSHOT_GMU_MEM_LOG)
+
+ # Dump last section
+ last_section = kgsl_snapshot_section_header()
+ last_section.magic = SNAPSHOT_SECTION_MAGIC
+ last_section.id = KGSL_SNAPSHOT_SECTION_END
+ last_section.size = sizeof(kgsl_snapshot_section_header)
+ file.write(last_section)
+
+ file.close()
diff --git a/linux-ramdump-parser-v2/parsers/gpu/gpuinfo_510.py b/linux-ramdump-parser-v2/parsers/gpu/gpuinfo_510.py
index cad34eb..794a655 100644
--- a/linux-ramdump-parser-v2/parsers/gpu/gpuinfo_510.py
+++ b/linux-ramdump-parser-v2/parsers/gpu/gpuinfo_510.py
@@ -9,11 +9,15 @@
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
-from parser_util import RamParser
-from print_out import print_out_str
import linux_list
-import traceback
import linux_radix_tree
+import traceback
+
+from parser_util import RamParser
+from parsers.gpu.gpu_snapshot import create_snapshot_from_ramdump
+from parsers.gpu.gpu_eventlog import parse_eventlog_buffer
+from print_out import print_out_str
+
# Global Configurations
ADRENO_DISPATCH_DRAWQUEUE_SIZE = 128
@@ -53,6 +57,7 @@
(self.parse_fence_data, "Fences", 'gpu_sync_fences.txt'),
(self.parse_open_process_mementry, "Open Process Mementries",
'open_process_mementries.txt'),
+ (self.parse_eventlog_data, "Eventlog Buffer", 'eventlog.txt'),
]
self.rtw = linux_radix_tree.RadixTreeWalker(dump)
@@ -297,6 +302,9 @@
self.writeln('\t' + str(pool_order[i]) + ' order pool size: ' +
str_convert_to_kb(pool_size[i]*PAGE_SIZE))
+ def parse_eventlog_data(self, dump):
+ parse_eventlog_buffer(self.writeln, dump)
+
def parse_dispatcher_data(self, dump):
dispatcher_addr = dump.struct_field_addr(self.devp,
'struct adreno_device',
@@ -935,6 +943,7 @@
atomic_snapshot = dump.read_bool(atomic_snapshot_addr)
if not atomic_snapshot:
self.writeln('No atomic snapshot detected.')
+ self.create_mini_snapshot(dump)
return
atomic_snapshot_offset = dump.field_offset(
@@ -946,6 +955,7 @@
if atomic_snapshot_base == 0 or atomic_snapshot_size == 0:
self.writeln('Invalid atomic snapshot.')
+ self.create_mini_snapshot(dump)
return
self.writeln('Atomic Snapshot Details:')
@@ -958,3 +968,6 @@
self.writeln('\nData dumped to atomic_snapshot.bpmd')
file.write(data)
file.close()
+
+ def create_mini_snapshot(self, dump):
+ create_snapshot_from_ramdump(self.devp, dump)
diff --git a/linux-ramdump-parser-v2/parsers/gpu/gpuinfo_54.py b/linux-ramdump-parser-v2/parsers/gpu/gpuinfo_54.py
index f37bee2..9de000e 100644
--- a/linux-ramdump-parser-v2/parsers/gpu/gpuinfo_54.py
+++ b/linux-ramdump-parser-v2/parsers/gpu/gpuinfo_54.py
@@ -9,11 +9,14 @@
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
-from parser_util import RamParser
-from print_out import print_out_str
import linux_list
-import traceback
import linux_radix_tree
+import traceback
+
+from parser_util import RamParser
+from parsers.gpu.gpu_snapshot import create_snapshot_from_ramdump
+from print_out import print_out_str
+
# Global Configurations
ADRENO_DISPATCH_DRAWQUEUE_SIZE = 128
@@ -1151,6 +1154,7 @@
atomic_snapshot = dump.read_bool(atomic_snapshot_addr)
if not atomic_snapshot:
self.writeln('No atomic snapshot detected.')
+ self.create_mini_snapshot(dump)
return
atomic_snapshot_offset = dump.field_offset(
@@ -1162,6 +1166,7 @@
if atomic_snapshot_base == 0 or atomic_snapshot_size == 0:
self.writeln('Invalid atomic snapshot.')
+ self.create_mini_snapshot(dump)
return
self.writeln('Atomic Snapshot Details:')
@@ -1174,3 +1179,6 @@
self.writeln('\nData dumped to atomic_snapshot.bpmd')
file.write(data)
file.close()
+
+ def create_mini_snapshot(self, dump):
+ create_snapshot_from_ramdump(self.devp, dump)
diff --git a/linux-ramdump-parser-v2/parsers/gpuinfo.py b/linux-ramdump-parser-v2/parsers/gpuinfo.py
index f3ebee6..d866f77 100644
--- a/linux-ramdump-parser-v2/parsers/gpuinfo.py
+++ b/linux-ramdump-parser-v2/parsers/gpuinfo.py
@@ -22,7 +22,8 @@
super(GpuParser, self).__init__(dump)
def parse(self):
- if not self.ramdump.is_config_defined('CONFIG_QCOM_KGSL'):
+ if not (self.ramdump.is_config_defined('CONFIG_QCOM_KGSL') or
+ 'msm_kgsl' in self.ramdump.ko_file_names):
print_out_str(
"No GPU support detected... Skipping GPU parser.")
return
diff --git a/linux-ramdump-parser-v2/parsers/ion_buffer_parse.py b/linux-ramdump-parser-v2/parsers/ion_buffer_parse.py
index f1aea7c..e143947 100644
--- a/linux-ramdump-parser-v2/parsers/ion_buffer_parse.py
+++ b/linux-ramdump-parser-v2/parsers/ion_buffer_parse.py
@@ -37,6 +37,7 @@
grand_total = 0
TASK_NAME_LENGTH = 16
ion_heap_buffers = []
+dmabuf_heap_names = ["qcom_dma_heaps"]
def bytes_to_KB(bytes):
@@ -50,7 +51,34 @@
if bytes != 0:
val = (bytes // 1024) // 1024
return val
-
+
+def get_dmabuf_heap_names(self, ramdump, ion_info):
+ heap_list = ramdump.address_of('heap_list')
+ if heap_list is None:
+ ion_info.write("NOTE: 'heap_list' list not found to extract the "
+ "dmabuf heap type list")
+ return False
+
+ list_offset = ramdump.field_offset('struct dma_heap', 'list')
+ name_offset = ramdump.field_offset('struct dma_heap', 'name')
+ next_offset = ramdump.field_offset('struct list_head', 'next')
+ prev_offset = ramdump.field_offset('struct list_head', 'prev')
+
+ head = ramdump.read_word(heap_list + next_offset)
+ while (head != heap_list):
+ dma_heap_addr = head - list_offset
+ dma_heap_name_addr = ramdump.read_word(dma_heap_addr + name_offset)
+ dma_heap_name = ramdump.read_cstring(dma_heap_name_addr, 48)
+ dmabuf_heap_names.append(dma_heap_name)
+
+ head = ramdump.read_word(head + next_offset)
+ prev = ramdump.read_word(head + prev_offset)
+ if head == 0 or prev == 0:
+ ion_info.write("NOTE: 'dmabuf heap_list' is corrupted")
+ return False
+
+ return True
+
def ion_buffer_info(self, ramdump, ion_info):
ion_info = ramdump.open_file('ionbuffer.txt')
db_list = ramdump.address_of('db_list')
@@ -76,6 +104,10 @@
ion_info.write("{0:40} {1:4} {2:15} {3:10} {4:10} {5:10} {6:20}\n".format(
'File_addr', 'REF', 'Name', 'Size', 'Exp', 'Heap', 'Size in KB'))
dma_buf_info = []
+ if (ramdump.kernel_version >= (5, 10)):
+ if get_dmabuf_heap_names(self, ramdump, ion_info) is False:
+ return
+
while (head != db_list):
dma_buf_addr = head - list_node_offset
size = ramdump.read_word(dma_buf_addr + size_offset)
@@ -86,7 +118,7 @@
exp_name = ramdump.read_cstring(exp_name, 48)
ionheap_name = None
if (ramdump.kernel_version >= (5, 10)):
- if 'qcom_dma_heaps' in exp_name:
+ if exp_name in dmabuf_heap_names:
ion_buffer = ramdump.read_structure_field(dma_buf_addr, 'struct dma_buf', 'priv')
ion_heap = ramdump.read_structure_field(ion_buffer, 'struct qcom_sg_buffer', 'heap')
ionheap_name_addr = ramdump.read_structure_field(ion_heap, 'struct dma_heap', 'name')
@@ -121,7 +153,7 @@
exp_name = ramdump.read_word(dma_buf_addr + exp_name_offset)
exp_name = ramdump.read_cstring(exp_name, 48)
if (ramdump.kernel_version >= (5, 10)):
- if exp_name == 'qcom_dma_heaps':
+ if exp_name in dmabuf_heap_names:
ion_buffer = ramdump.read_structure_field(dma_buf_addr, 'struct dma_buf', 'priv')
ion_heap = ramdump.read_structure_field(ion_buffer, 'struct qcom_sg_buffer', 'heap')
ionheap_name_addr = ramdump.read_structure_field(ion_heap, 'struct dma_heap', 'name')
diff --git a/linux-ramdump-parser-v2/parsers/lpm.py b/linux-ramdump-parser-v2/parsers/lpm.py
index 1856450..8e9cb40 100644
--- a/linux-ramdump-parser-v2/parsers/lpm.py
+++ b/linux-ramdump-parser-v2/parsers/lpm.py
@@ -164,6 +164,9 @@
name += ":idle_states:S{}"
state_count = self.ramdump.read_structure_field(node, 'struct generic_pm_domain', 'state_count')
+ #sanity check for state count , CPUIDLE_STATE_MAX
+ if state_count >= 10:
+ return
accounting_time = self.ramdump.read_structure_field(node, 'struct generic_pm_domain', 'accounting_time')
gpd_power_state_size = self.ramdump.sizeof('struct genpd_power_state')
power_state_offset = self.ramdump.field_offset('struct generic_pm_domain', 'states')
diff --git a/linux-ramdump-parser-v2/parsers/mdpinfo.py b/linux-ramdump-parser-v2/parsers/mdpinfo.py
index d9517f3..4eb87fe 100644
--- a/linux-ramdump-parser-v2/parsers/mdpinfo.py
+++ b/linux-ramdump-parser-v2/parsers/mdpinfo.py
@@ -47,7 +47,7 @@
_fields = {
'evtlog': Struct.get_pointer,
'reglog': Struct.get_pointer,
- 'reg_base_list': Struct.get_pointer,
+ 'reg_base_list': Struct.get_address,
'enable_reg_dump' : Struct.get_u32,
'panic_on_err' : Struct.get_u32,
'dbgbus_sde': Struct.get_address,
@@ -2611,16 +2611,16 @@
struct_name="struct sde_dbg_reglog",
fields={'enable': Struct.get_u32,
'last': Struct.get_u32,
- 'curr': Struct.get_u32,
+ 'curr': Struct.get_u64,
'logs': Struct.get_address,
'last_dump': Struct.get_u32})
SDE_REGLOG_ENTRY = 1024
self.outfile.write('%-21.5s%-11.5s%-13.7s%-13.5s%s\n' % ("TIME", "PID", "ADDRESS", "VAL", "BLK_ID"))
sde_reglog_start = 0
sde_reglog_repeat = 0
- sde_reglog_curr = reg_log.curr % SDE_REGLOG_ENTRY
+ sde_reglog_curr = abs(reg_log.curr % SDE_REGLOG_ENTRY)
if (sde_reglog_curr != reg_log.last):
- sde_reglog_start = sde_reglog_curr
+ sde_reglog_start = sde_reglog_curr + 1
else:
sde_reglog_repeat = 1
sde_reglog_count = 0
@@ -2661,38 +2661,38 @@
evtlog = f_evtlog.readline()
reglog = f_reglog.readline()
curr_timestamp = 0
-
+ self.outfile.write('{:<54}{:<29}{:<6}{:<3}{:<200}\n'.format("EVTLOG_REGLOG_MERGED", "TIMESTAMP", "PID", "CPU", "DATA"))
while (evtlog and reglog):
if "FUNCTION_NAME" in evtlog:
evtlog = f_evtlog.readline()
if "TIME" in reglog:
reglog = f_reglog.readline()
+ if "COMMIT" in evtlog:
+ evtlog = f_evtlog.readline()
if not evtlog or not reglog:
break
- evtlog_tmp = re.split(r'==>|: |\n', evtlog)
+ evtlog_tmp = re.split(r'==>|: |\n', evtlog, 2)
data_tmp = evtlog_tmp[2].split("[", 1)
reglog_tmp = re.sub(r'\s+', ' ', reglog)
reglog_tmp = reglog.split()
if (int(evtlog_tmp[1]) > int(reglog_tmp[0])):
self.outfile.write('{:<54}{:<29}{:<6}{:<3}{:<200}'.format("sde_reg_write", "==>"+str(reglog_tmp[0])+": "+str(int(reglog_tmp[0]) - curr_timestamp), "["+reglog_tmp[1]+"]","[N]", reglog_tmp[2] + " " + reglog_tmp[3] + " " + reglog_tmp[4]))
- self.outfile.write('\n')
reglog = f_reglog.readline()
curr_timestamp = int(reglog_tmp[0])
+ self.outfile.write('\n')
else:
self.outfile.write('{:<54}{:<29}{:<200}'.format(evtlog_tmp[0], "==>"+str(evtlog_tmp[1])+": "+str(int(evtlog_tmp[1]) - curr_timestamp),"["+data_tmp[1]))
evtlog = f_evtlog.readline()
curr_timestamp = int(evtlog_tmp[1])
- self.outfile.write('\n')
while(evtlog):
- evtlog_tmp = re.split(r'==>|: |\n', evtlog)
+ evtlog_tmp = re.split(r'==>|: |\n', evtlog, 2)
data_tmp = evtlog_tmp[2].split("[", 1)
self.outfile.write('{:<54}{:<29}{:<200}'.format(evtlog_tmp[0], "==>"+str(evtlog_tmp[1])+": "+str(int(evtlog_tmp[1]) - curr_timestamp),"["+data_tmp[1]))
evtlog = f_evtlog.readline()
curr_timestamp = int(evtlog_tmp[1])
- self.outfile.write('\n')
while(reglog):
reglog_tmp = re.sub(r'\s+', ' ', reglog)
@@ -2728,13 +2728,13 @@
self.outfile.write('=================================sde debug bus points=================================\n\n')
self.outfile.write('{:<12}{:<12}{:<12}{:<15}'.format("wr_addr", "block_id", "test_id", "val"))
- self.outfile.write('\n')
+ self.outfile.write('\n\n')
while (i < dbgbus_sde_cmn.content_size):
j = 0
while (j < 16):
self.outfile.write('%-10.8x ' % (self.ramdump.read_u32(dbgbus_sde_cmn.dumped_content + (i*4) + j)))
j = j + 4
- self.outfile.write('\n\n')
+ self.outfile.write('\n')
i = i + 4
i = 0
diff --git a/linux-ramdump-parser-v2/parsers/memstat.py b/linux-ramdump-parser-v2/parsers/memstat.py
index 15c0cdc..cd4174b 100644
--- a/linux-ramdump-parser-v2/parsers/memstat.py
+++ b/linux-ramdump-parser-v2/parsers/memstat.py
@@ -12,12 +12,19 @@
from parser_util import register_parser, RamParser
import os
import linux_list as llist
+import linux_radix_tree
VM_ALLOC = 0x00000002
@register_parser('--print-memstat', 'Print memory stats ')
class MemStats(RamParser):
+ def __init__(self, dump):
+ super(MemStats, self).__init__(dump)
+
+ if (self.ramdump.kernel_version >= (5, 4)):
+ self.zram_dev_rtw = linux_radix_tree.RadixTreeWalker(self.ramdump)
+ self.zram_mem_mb = 0
def list_func(self, vmlist):
vm = self.ramdump.read_word(vmlist + self.vm_offset)
@@ -148,6 +155,21 @@
grandtotal = self.bytes_to_mb(grandtotal)
return grandtotal
+ def calculate_zram_dev_mem_allocated(self, zram):
+ mem_pool = zram + self.ramdump.field_offset('struct zram', 'mem_pool')
+ mem_pool = self.ramdump.read_word(mem_pool)
+
+ pages_allocated = mem_pool + self.ramdump.field_offset('struct zs_pool',
+ 'pages_allocated')
+
+ stat_val = self.ramdump.read_word(pages_allocated)
+ if stat_val is None:
+ stat_val = 0
+ else:
+ stat_val = self.pages_to_mb(stat_val)
+
+ self.zram_mem_mb += stat_val
+
def print_mem_stats(self, out_mem_stat):
# Total memory
if(self.ramdump.kernel_version > (4, 20, 0)):
@@ -217,43 +239,42 @@
if zram_index_idr is None:
stat_val = 0
else:
- #From Kernel 9.5, The 'struct radix_tree_root', 'rnode' is replaced by 'struct xarray', 'xa_head'
- # refer LA.UM.9.14/kernel/msm-5.4/include/linux/xarray.h
+ #'struct radix_tree_root' was replaced by 'struct xarray' on kernel 5.4+
if self.ramdump.kernel_version >= (5, 4):
- idr_layer_ary_offset = self.ramdump.field_offset(
- 'struct xarray', 'xa_head')
- idr_layer_ary = self.ramdump.read_word(zram_index_idr +
+ self.zram_dev_rtw.walk_radix_tree(zram_index_idr,
+ self.calculate_zram_dev_mem_allocated)
+ stat_val = self.zram_mem_mb
+ else:
+ if self.ramdump.kernel_version >= (4, 14):
+ idr_layer_ary_offset = self.ramdump.field_offset(
+ 'struct radix_tree_root', 'rnode')
+ idr_layer_ary = self.ramdump.read_word(zram_index_idr +
+ idr_layer_ary_offset)
+ else:
+ idr_layer_ary_offset = self.ramdump.field_offset(
+ 'struct idr_layer', 'ary')
+ idr_layer_ary = self.ramdump.read_word(zram_index_idr +
idr_layer_ary_offset)
- elif self.ramdump.kernel_version >= (4, 14):
- idr_layer_ary_offset = self.ramdump.field_offset(
- 'struct radix_tree_root', 'rnode')
- idr_layer_ary = self.ramdump.read_word(zram_index_idr +
- idr_layer_ary_offset)
- else:
- idr_layer_ary_offset = self.ramdump.field_offset(
- 'struct idr_layer', 'ary')
- idr_layer_ary = self.ramdump.read_word(zram_index_idr +
- idr_layer_ary_offset)
- try:
- zram_meta = idr_layer_ary + self.ramdump.field_offset(
- 'struct zram', 'meta')
- zram_meta = self.ramdump.read_word(zram_meta)
- mem_pool = zram_meta + self.ramdump.field_offset(
- 'struct zram_meta', 'mem_pool')
- mem_pool = self.ramdump.read_word(mem_pool)
- except TypeError:
- mem_pool = idr_layer_ary + self.ramdump.field_offset(
- 'struct zram', 'mem_pool')
- mem_pool = self.ramdump.read_word(mem_pool)
- if mem_pool is None:
- stat_val = 0
- else:
- page_allocated = mem_pool + self.ramdump.field_offset(
- 'struct zs_pool', 'pages_allocated')
- stat_val = self.ramdump.read_word(page_allocated)
- if stat_val is None:
+ try:
+ zram_meta = idr_layer_ary + self.ramdump.field_offset(
+ 'struct zram', 'meta')
+ zram_meta = self.ramdump.read_word(zram_meta)
+ mem_pool = zram_meta + self.ramdump.field_offset(
+ 'struct zram_meta', 'mem_pool')
+ mem_pool = self.ramdump.read_word(mem_pool)
+ except TypeError:
+ mem_pool = idr_layer_ary + self.ramdump.field_offset(
+ 'struct zram', 'mem_pool')
+ mem_pool = self.ramdump.read_word(mem_pool)
+ if mem_pool is None:
stat_val = 0
- stat_val = self.pages_to_mb(stat_val)
+ else:
+ page_allocated = mem_pool + self.ramdump.field_offset(
+ 'struct zs_pool', 'pages_allocated')
+ stat_val = self.ramdump.read_word(page_allocated)
+ if stat_val is None:
+ stat_val = 0
+ stat_val = self.pages_to_mb(stat_val)
else:
zram_devices_word = self.ramdump.read_word('zram_devices')
if zram_devices_word is not None:
diff --git a/linux-ramdump-parser-v2/parsers/pagetracking.py b/linux-ramdump-parser-v2/parsers/pagetracking.py
index 33bef51..47896ef 100644
--- a/linux-ramdump-parser-v2/parsers/pagetracking.py
+++ b/linux-ramdump-parser-v2/parsers/pagetracking.py
@@ -23,13 +23,6 @@
def __init__(self, *args):
super(PageTracking, self).__init__(*args)
self.trace_entry_size = self.ramdump.sizeof('unsigned long')
- if self.ramdump.is_config_defined('CONFIG_SPARSEMEM'):
- self.page_ext_offset = self.ramdump.field_offset(
- 'struct mem_section', 'page_ext')
- else:
- self.page_ext_offset = self.ramdump.field_offset(
- 'struct pglist_data', 'node_page_ext')
-
self.trace_offset = 0
self.nr_entries_offset = 0
self.trace_entries_offset = 0
@@ -99,8 +92,7 @@
phys = pfn << 12
if phys is None or phys == 0:
return -1, -1, -1, -1
- mem_section = pfn_to_section(self.ramdump, pfn)
- page_ext = self.ramdump.read_word(mem_section + self.page_ext_offset)
+ page_ext = self.ramdump.mm.lookup_page_ext(pfn)
"""
page_ext will be null here if the first page of a section is not valid.
See page_ext_init().
@@ -237,15 +229,13 @@
def parse(self):
ranges = None
if self.ramdump.minidump:
- addr = self.ramdump.address_of('md_pageowner_dump_addr')
- if addr is None:
- print_out_str("NOTE: " +
- "Pageowner Minidump is not supported")
- return
for eb_file in self.ramdump.ebi_files:
path1 = eb_file[3]
path = os.path.join(path1.split("MD_S")[0], "md_PAGEOWNER.bin")
- input_file = open(path, 'r')
+ if not os.path.exists(path):
+ print_out_str(path + " not found")
+ return
+ input_file = open(path, 'r', errors="ignore")
lines = input_file.readlines()
i = 0
functions = defaultdict(list)
diff --git a/linux-ramdump-parser-v2/parsers/slabinfo.py b/linux-ramdump-parser-v2/parsers/slabinfo.py
index b356cce..a4cf530 100755
--- a/linux-ramdump-parser-v2/parsers/slabinfo.py
+++ b/linux-ramdump-parser-v2/parsers/slabinfo.py
@@ -532,15 +532,13 @@
def parse(self):
if self.ramdump.minidump:
- addr = self.ramdump.address_of('md_slabowner_dump_addr')
- if addr is None:
- print_out_str("NOTE: " +
- "slabowner Minidump is not supported")
- return
for eb_file in self.ramdump.ebi_files:
path1 = eb_file[3]
path = os.path.join(path1.split("MD_S")[0], "md_SLABOWNER.bin")
- input_file = open(path, 'r')
+ if not os.path.exists(path):
+ print_out_str(path + " not found")
+ return
+ input_file = open(path, 'r', errors="ignore")
output_file = self.ramdump.open_file("slabowner_dump.txt", 'w')
lines = input_file.readlines()
i = 0
diff --git a/linux-ramdump-parser-v2/parsers/taskdump.py b/linux-ramdump-parser-v2/parsers/taskdump.py
index 4ac6ce9..c652d73 100644
--- a/linux-ramdump-parser-v2/parsers/taskdump.py
+++ b/linux-ramdump-parser-v2/parsers/taskdump.py
@@ -159,7 +159,7 @@
task_last_enqueued_ts = 0
task_last_sleep_ts = 0
- if offset_last_enqueued_ts is None and ramdump.is_config_defined('CONFIG_SCHED_WALT'):
+ if offset_last_enqueued_ts is None and (ramdump.is_config_defined('CONFIG_SCHED_WALT') or 'sched_walt' in ramdump.ko_file_names):
offset_last_enqueued_ts = ramdump.field_offset('struct walt_task_struct', 'last_enqueued_ts')
if (ramdump.kernel_version >= (5, 10, 0)):
walt_task_struct_offset = ramdump.field_offset('struct task_struct', 'android_vendor_data1')
@@ -171,7 +171,7 @@
task_last_enqueued_ts = ramdump.read_u64(next_thread_last_enqueued)
if task_last_enqueued_ts is None:
task_last_enqueued_ts = 0
- if offset_last_sleep_ts is None and ramdump.is_config_defined('CONFIG_SCHED_WALT'):
+ if offset_last_sleep_ts is None and (ramdump.is_config_defined('CONFIG_SCHED_WALT') or 'sched_walt' in ramdump.ko_file_names):
offset_last_sleep_ts = ramdump.field_offset('struct walt_task_struct', 'last_sleep_ts ')
if (ramdump.kernel_version >= (5, 10, 0)):
walt_task_struct_offset = ramdump.field_offset('struct task_struct', 'android_vendor_data1')
@@ -216,13 +216,13 @@
task_out.write(
'=====================================================\n')
first = 1
- task_out.write(' Task name: {0} pid: {1} cpu: {2} prio: {7} start: {'
+ task_out.write(' Task name: {0} [affinity: 0x{11:x}] pid: {1} cpu: {2} prio: {7} start: {'
'6:x}\n state: 0x{3:x}[{8}] exit_state: 0x{4:x}'
' stack base: 0x{5:x}\n'
' Last_enqueued_ts:{9:18.9f} Last_sleep_ts:{10:18.9f}\n'.format(
thread_task_name, thread_task_pid, task_cpu, task_state,
task_exit_state, addr_stack, next_thread_start, thread_task_prio, task_state_str,
- task_last_enqueued_ts/1000000000.0, task_last_sleep_ts/1000000000.0))
+ task_last_enqueued_ts/1000000000.0, task_last_sleep_ts/1000000000.0,thread_task_affine))
if task_on_cpu == 1:
taskhighlight_out.write("Task currently running on CPU. Please check dmesg_tz for callstack")
else:
diff --git a/linux-ramdump-parser-v2/parsers/thermal_data.py b/linux-ramdump-parser-v2/parsers/thermal_data.py
index 8bd47cb..1804441 100755
--- a/linux-ramdump-parser-v2/parsers/thermal_data.py
+++ b/linux-ramdump-parser-v2/parsers/thermal_data.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2015, 2020 The Linux Foundation. All rights reserved.
+# Copyright (c) 2015, 2020-2021 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,7 +11,10 @@
from print_out import print_out_str
from parser_util import register_parser, RamParser
+import linux_list as llist
+TSENS_MAX_SENSORS = 16
+DEBUG_SIZE = 10
@register_parser(
'--thermal-info', 'Useful information from thermal data structures')
@@ -75,10 +78,47 @@
time_stamp,
sensor_mapping)
+ def list_func(self, tsens_device_p):
+ dev_o = self.ramdump.field_offset('struct tsens_device', 'dev')
+ dev = self.ramdump.read_word(dev_o + tsens_device_p)
+ kobj_o = self.ramdump.field_offset('struct device', ' kobj')
+ kobj = (dev + kobj_o)
+ name_o = self.ramdump.field_offset('struct kobject', 'name')
+ name_addr = self.ramdump.read_word(name_o + kobj)
+ name = self.ramdump.read_cstring(name_addr)
+ if name is not None:
+ print("%s" % (name), file=self.output_file)
+ tsens_dbg_o = self.ramdump.field_offset('struct tsens_device', 'tsens_dbg')
+ tsens_dbg = tsens_device_p + tsens_dbg_o
+ sensor_dbg_info_o = self.ramdump.field_offset('struct tsens_dbg_context', 'sensor_dbg_info')
+ sensor_dbg_info = sensor_dbg_info_o + tsens_dbg
+ self.output_file.write('v.v (struct tsens_device)0x{:8x} 0x{:8x}\n'.format(tsens_device_p, sensor_dbg_info))
+ for i in range(0, TSENS_MAX_SENSORS):
+ idx = self.ramdump.read_u32(self.ramdump.array_index(sensor_dbg_info, 'struct tsens_dbg', i))
+ tsens_dbg_addr = self.ramdump.array_index(sensor_dbg_info, 'struct tsens_dbg', i)
+ print (" idx: %d tsens_dbg_addr 0x%x" %(idx, tsens_dbg_addr), file=self.output_file)
+ time_stmp_o = self.ramdump.field_offset('struct tsens_dbg', 'time_stmp')
+ temp_o = self.ramdump.field_offset('struct tsens_dbg', 'temp')
+ print(" time_stmp temp ", file=self.output_file)
+ for j in range(0, DEBUG_SIZE):
+ time_stmp = self.ramdump.read_word(self.ramdump.array_index(time_stmp_o + tsens_dbg_addr, 'unsigned long long', j))
+ temp = self.ramdump.read_u64(
+ self.ramdump.array_index(temp_o + tsens_dbg_addr, 'unsigned long', j))
+ print(" %d %d" % (time_stmp, temp), file=self.output_file)
+
+
+ def get_thermal_info(self):
+ tsens_device_list = self.ramdump.address_of('tsens_device_list')
+ list_offset = self.ramdump.field_offset('struct tsens_device', 'list')
+ list_walker = llist.ListWalker(self.ramdump, tsens_device_list, list_offset)
+ list_walker.walk(tsens_device_list, self.list_func)
+
def parse(self):
self.output_file = self.ramdump.open_file('thermal_info.txt')
-
- self.tmdev_data(self.ramdump)
+ if self.ramdump.kernel_version >= (5, 4):
+ self.get_thermal_info()
+ else:
+ self.tmdev_data(self.ramdump)
self.output_file.close()
print_out_str("--- Wrote the output to thermal_info.txt")
diff --git a/linux-ramdump-parser-v2/parsers/timerlist.py b/linux-ramdump-parser-v2/parsers/timerlist.py
index a6805c1..591a2d6 100644
--- a/linux-ramdump-parser-v2/parsers/timerlist.py
+++ b/linux-ramdump-parser-v2/parsers/timerlist.py
@@ -69,7 +69,7 @@
else:
data = ""
- if function == "delayed_work_timer_fn":
+ if function.split('[')[0] == "delayed_work_timer_fn":
timer_list_offset = self.ramdump.field_offset('struct delayed_work', 'timer')
work_addr = node - timer_list_offset
func_addr = work_addr + self.ramdump.field_offset('struct work_struct', 'func')
diff --git a/linux-ramdump-parser-v2/ramdump.py b/linux-ramdump-parser-v2/ramdump.py
index 25bb105..2e1e11b 100644
--- a/linux-ramdump-parser-v2/ramdump.py
+++ b/linux-ramdump-parser-v2/ramdump.py
@@ -598,6 +598,7 @@
self.arm64 = options.arm64
self.ndk_compatible = False
self.lookup_table = []
+ self.ko_file_names = []
if gdb_ndk_path:
self.gdbmi = gdbmi.GdbMI(self.gdb_ndk_path, self.vmlinux,
@@ -624,7 +625,7 @@
self.page_offset = 0xc0000000
self.thread_size = 8192
self.qtf_path = options.qtf_path
- self.qtf = options.qtf
+ self.ftrace_format = options.ftrace_format
self.skip_qdss_bin = options.skip_qdss_bin
self.debug = options.debug
self.dcc = False
@@ -1208,7 +1209,6 @@
if not self.minidump:
if self.arm64:
- startup_script.write('Register.Set NS 1\n')
if self.svm:
startup_script.write('Data.Set SPR:0x30201 %Quad 0x{0:x}\n'.format(
self.ttbr_data))
@@ -1256,15 +1256,8 @@
startup_script.write('Data.Set SPR:0x30A30 %Quad 0x0000000000000000\n')
startup_script.write('Data.Set SPR:0x30100 %Quad 0x0000000004C5D93D\n')
- startup_script.write('TRANSlation.COMMON NS:0xF000000000000000--0xffffffffffffffff\n')
- startup_script.write('trans.tablewalk on\n')
- startup_script.write('trans.on\n')
- if not self.svm:
- startup_script.write('Register.Set CPSR 0x3C5\n')
- startup_script.write('MMU.Delete\n')
- startup_script.write('MMU.SCAN PT 0xFFFFFF8000000000--0xFFFFFFFFFFFFFFFF\n')
- startup_script.write('mmu.on\n')
- startup_script.write('mmu.pt.list 0xffffff8000000000\n')
+ startup_script.write('Register.Set NS 1\n')
+ startup_script.write('Register.Set CPSR 0x1C5\n')
else:
# ARM-32: MMU is enabled by default on most platforms.
mmu_enabled = 1
@@ -1292,12 +1285,22 @@
dloadelf = 'data.load.elf {} /nocode\n'.format(where)
startup_script.write(dloadelf)
+ if self.arm64:
+ startup_script.write('TRANSlation.COMMON NS:0xF000000000000000--0xffffffffffffffff\n')
+ startup_script.write('trans.tablewalk on\n')
+ startup_script.write('trans.on\n')
+ if not self.svm and self.cpu_type != 'ARMV9-A':
+ startup_script.write('MMU.Delete\n')
+ startup_script.write('MMU.SCAN PT 0xFFFFFF8000000000--0xFFFFFFFFFFFFFFFF\n')
+ startup_script.write('mmu.on\n')
+ startup_script.write('mmu.pt.list 0xffffff8000000000\n')
+
if t32_host_system != 'Linux':
if self.arm64:
startup_script.write(
- 'task.config C:\\T32\\demo\\arm64\\kernel\\linux\\linux-3.x\\linux3.t32\n')
+ 'task.config C:\\T32\\demo\\arm64\\kernel\\linux\\awareness\\linux.t32 /ACCESS NS:\n')
startup_script.write(
- 'menu.reprogram C:\\T32\\demo\\arm64\\kernel\\linux\\linux-3.x\\linux.men\n')
+ 'menu.reprogram C:\\T32\\demo\\arm64\\kernel\\linux\\awareness\\linux.men\n')
else:
if self.kernel_version > (3, 0, 0):
startup_script.write(
@@ -1327,15 +1330,25 @@
startup_script.write(
'menu.reprogram /opt/t32/demo/arm/kernel/linux/linux.men\n')
- for mod_tbl_ent in self.module_table.module_table:
- mod_sym_path = mod_tbl_ent.get_sym_path()
- if mod_sym_path != '':
- where = os.path.abspath(mod_sym_path)
- if 'wlan' in mod_tbl_ent.name:
- ld_mod_sym = "Data.LOAD.Elf " + where + " " + str(hex(mod_tbl_ent.module_offset)) + " /NoCODE /NoClear /NAME " + mod_tbl_ent.name + " /reloctype 0x3" + "\n"
- else:
- ld_mod_sym = "Data.LOAD.Elf " + where + " /NoCODE /NoClear /NAME " + mod_tbl_ent.name + " /reloctype 0x3" + "\n"
- startup_script.write(ld_mod_sym)
+ if self.cpu_type == 'ARMV9-A':
+ mod_dir = os.path.dirname(self.vmlinux)
+ mod_dir = os.path.abspath(mod_dir)
+ startup_script.write('sYmbol.AUTOLOAD.CHECKCOMMAND ' + '"do C:\\T32\\demo\\arm64\\kernel\\linux\\awareness\\autoload.cmm"' + '\n')
+ startup_script.write('sYmbol.SourcePATH.Set ' + '"' + mod_dir + '"' + "\n")
+ startup_script.write('TASK.sYmbol.Option AutoLoad Module\n')
+ startup_script.write('TASK.sYmbol.Option AutoLoad noprocess\n')
+ startup_script.write('sYmbol.AutoLOAD.List\n')
+ startup_script.write('sYmbol.AutoLOAD.CHECK\n')
+ else:
+ for mod_tbl_ent in self.module_table.module_table:
+ mod_sym_path = mod_tbl_ent.get_sym_path()
+ if mod_sym_path != '':
+ where = os.path.abspath(mod_sym_path)
+ if 'wlan' in mod_tbl_ent.name:
+ ld_mod_sym = "Data.LOAD.Elf " + where + " " + str(hex(mod_tbl_ent.module_offset)) + " /NoCODE /NoClear /NAME " + mod_tbl_ent.name + " /reloctype 0x3" + "\n"
+ else:
+ ld_mod_sym = "Data.LOAD.Elf " + where + " /NoCODE /NoClear /NAME " + mod_tbl_ent.name + " /reloctype 0x3" + "\n"
+ startup_script.write(ld_mod_sym)
if not self.minidump:
startup_script.write('task.dtask\n')
@@ -1358,7 +1371,7 @@
elif is_cortex_a53:
t32_binary = 'C:\\T32\\bin\\windows64\\t32MARM64.exe'
else:
- t32_binary = 'c:\\t32\\t32MARM.exe'
+ t32_binary = 'c:\\T32\\bin\\windows64\\t32MARM.exe'
t32_bat.write(('start '+ t32_binary + ' -c ' + out_path + '/t32_config.t32, ' +
out_path + '/t32_startup_script.cmm'))
t32_bat.close()
@@ -1730,6 +1743,7 @@
if ko_file_list.get(name, '').endswith('.ko.unstripped') and file.endswith('.ko'):
return
ko_file_list[name] = file
+ self.ko_file_names.append(name)
self.walk_depth(path, on_file)
for mod_tbl_ent in self.module_table.module_table:
@@ -1873,8 +1887,9 @@
else:
addr1 = addr
#print "hex of address in get_symbol_info1 {0}".format(hex(addr1))
+ addr1, desc = self.step_through_jump_table(addr1)
symbol_obj = self.gdbmi.get_symbol_info(addr1)
- return symbol_obj.symbol
+ return symbol_obj.symbol + desc
def type_of(self, symbol):
"""
@@ -1936,6 +1951,30 @@
except gdbmi.GdbMIException:
pass
+ def step_through_jump_table(self, addr):
+ """
+ Steps through a jump table, if the address points to a unconditional branch
+ """
+
+ if addr is None:
+ return addr, ''
+
+ fn_addr = addr
+ if self.is_config_defined('CONFIG_ARM64_BTI_KERNEL'):
+ # Skip past BTI instruction to the real branch instr
+ fn_addr += 4
+ if self.cpu_type in ['ARMV9-A', 'CORTEXA53']:
+ instr = self.read_u32(fn_addr)
+ if instr is None or (instr & 0xFC000000) != 0x14000000:
+ return addr, ''
+ imm26_mask = 0x3FFFFFF
+ offset = instr & imm26_mask
+ if (offset & imm26_mask) >> 25:
+ offset -= (imm26_mask + 1)
+ fn_addr += 4 * offset
+ return fn_addr, '[jt]'
+ return addr, ''
+
def unwind_lookup(self, addr, symbol_size=0):
"""
Returns closest symbols <= addr and either the relative offset
@@ -1950,6 +1989,8 @@
low = 0
high = len(self.lookup_table) - 1
+ addr, desc = self.step_through_jump_table(addr)
+
if addr is None or addr < table[low][0] or addr > table[high][0]:
return None
@@ -1978,9 +2019,9 @@
size = table[low + 1][0] - table[low][0]
if symbol_size == 0:
- return (table[low][1], offset)
+ return (table[low][1] + desc, offset)
else:
- return (table[low][1], size)
+ return (table[low][1] + desc, size)
def read_physical(self, addr, length):
if not isinstance(addr, int) or not isinstance(length, int):
diff --git a/linux-ramdump-parser-v2/ramparse.py b/linux-ramdump-parser-v2/ramparse.py
index 0af1fc4..2cf9aa7 100644
--- a/linux-ramdump-parser-v2/ramparse.py
+++ b/linux-ramdump-parser-v2/ramparse.py
@@ -114,8 +114,10 @@
help='Run an interactive python interpreter with the ramdump loaded')
parser.add_option('', '--classic-shell', action='store_true',
help='Like --shell, but forces the use of the classic python shell, even if ipython is installed')
- parser.add_option('', '--qtf', action='store_true', dest='qtf',
+ parser.add_option('', '--qtf', action='store_true', dest='ftrace_format',
help='Use QTF tool to parse and save QDSS trace data')
+ parser.add_option('', '--ftrace-formats', action='store_true', dest='ftrace_format',
+ help='Extracts formats.txt used for generating ftrace')
parser.add_option('', '--qtf-path', dest='qtf_path',
help='QTF tool executable')
parser.add_option('', '--skip-qdss-bin', action='store_true',
diff --git a/linux-ramdump-parser-v2/scandump_reader.py b/linux-ramdump-parser-v2/scandump_reader.py
index 11fd7d8..e121ba4 100644
--- a/linux-ramdump-parser-v2/scandump_reader.py
+++ b/linux-ramdump-parser-v2/scandump_reader.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2016-2018, The Linux Foundation. All rights reserved.
+# Copyright (c) 2016-2018,2021 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
@@ -157,7 +157,7 @@
fd = open(output, "r")
for line in fd:
match_flag = False
- matchObj = re.match('^REGISTER.SET ([xse].*[0-9]+)\s(0x[0-9a-f]{0,})', line, re.M | re.I)
+ matchObj = re.match('^REGISTER.SET ([xse].*[0-9]+)\s+(0x[0-9a-f]{0,})', line, re.M | re.I)
if matchObj:
regVal = matchObj.group(2)
if regVal == "0x":
@@ -165,24 +165,24 @@
self.regs[(matchObj.group(1)).lower()] = int(regVal, 16)
match_flag = True
else:
- matchObj = re.match('^REGISTER.SET (PC)\s(0x[0-9a-f]{0,})', line, re.M | re.I)
+ matchObj = re.match('^REGISTER.SET (PC)\s+(0x[0-9a-f]{0,})', line, re.M | re.I)
if matchObj:
regVal = matchObj.group(2)
if regVal == "0x":
regVal = "0x0000000000000000"
pc_val = regVal
- matchObj_altpc = re.match('^REGISTER.SET (ALT_PC_1)\s(0x[0-9a-f]{0,})', line, re.M | re.I)
+ matchObj_altpc = re.match('^REGISTER.SET (ALT_PC_1)\s+(0x[0-9a-f]{0,})', line, re.M | re.I)
if matchObj_altpc:
alt_pc_1 = matchObj_altpc.group(2)
if alt_pc_1 == "0x":
alt_pc_1 = "0x0000000000000000"
- matchObj_altpc = re.match('^REGISTER.SET (ALT_PC_2)\s(0x[0-9a-f]{0,})', line, re.M | re.I)
+ matchObj_altpc = re.match('^REGISTER.SET (ALT_PC_2)\s+(0x[0-9a-f]{0,})', line, re.M | re.I)
if matchObj_altpc:
alt_pc_2 = matchObj_altpc.group(2)
if alt_pc_2 == "0x":
alt_pc_2 = "0x0000000000000000"
- matchObj = re.match('^REGISTER.SET ([xse].*[0-9]+)\s([0-9a-f])', line, re.M | re.I)
+ matchObj = re.match('^REGISTER.SET ([xse].*[0-9]+)\s+([0-9a-f])', line, re.M | re.I)
if matchObj and match_flag == False:
regVal = matchObj.group(2)
if regVal == "0":
diff --git a/linux-ramdump-parser-v2/sched_info.py b/linux-ramdump-parser-v2/sched_info.py
index fe6af85..b8df3a6 100644
--- a/linux-ramdump-parser-v2/sched_info.py
+++ b/linux-ramdump-parser-v2/sched_info.py
@@ -46,7 +46,8 @@
cpu_isolated_bits = ramdump.read_word('__cpu_isolated_mask')
elif (ramdump.kernel_version >= (4, 4, 0)):
cpu_isolated_bits = ramdump.read_word('cpu_isolated_bits')
-
+ if cpu_isolated_bits == None:
+ cpu_isolated_bits = 0
return cpu_isolated_bits