Skip to content
Snippets Groups Projects
Commit d9434874 authored by Patrick Daly's avatar Patrick Daly
Browse files

lrdp: debug_image: Support guest VM cpu register dump tables

The hypervisor may populate an imem cookie with the location of
a standard dump table, instead of using the table allocated by linux.
Read the table location from this cookie instead of relying on the
linux variable 'memdump'.
On error, fall back to the old approach of reading from 'memdump'.

Change-Id: Id99bb643fb7f35de79ff7308a999cc2143d7aff0
parent 0686897d
Branches
No related tags found
No related merge requests found
......@@ -35,6 +35,7 @@ from fcmdump import FCM_Dump
MEMDUMPV2_MAGIC = 0x42445953
MAX_NUM_ENTRIES = 0x150
IMEM_OFFSET_MEM_DUMP_TABLE = 0x3f010
class client(object):
MSM_DUMP_DATA_CPU_CTX = 0x00
......@@ -598,6 +599,40 @@ class DebugImage_v2():
results.append((client_name, client_id,client_table[client_name], entry_pa_addr,end_addr))
return results
class MsmDumpTable(object):
def __init__(self):
self.name = "Anon"
self.phys_addr = 0x0
self.version = 0x0
self.num_entries = 0x0
""" Create an instance of MsmDumpTable, or None on error """
def validateMsmDumpTable(self, ram_dump, name, table_phys):
if table_phys is None:
print_out_str('debug_image.py: Table {}: Unable to read dump table base address'.format(name))
return None
version = ram_dump.read_structure_field(
table_phys, 'struct msm_dump_table', 'version',
virtual = False)
if version is None:
print_out_str('Table {}: Version is bogus! Can\'t parse debug image'.format(name))
return None
num_entries = ram_dump.read_structure_field(
table_phys, 'struct msm_dump_table', 'num_entries',
virtual = False)
if num_entries is None or num_entries > 100:
print_out_str('Table {}: num_entries is bogus! Can\'t parse debug image'.format(name))
return None
table = self.MsmDumpTable()
table.name = name
table.phys_addr = table_phys
table.version = version
table.num_entries = num_entries
return table
def parse_dump_v2(self, ram_dump):
self.dump_type_lookup_table = ram_dump.gdbmi.get_enum_lookup_table(
'msm_dump_type', 2)
......@@ -674,32 +709,34 @@ class DebugImage_v2():
dump_entry_size = ram_dump.sizeof('struct msm_dump_entry')
dump_data_size = ram_dump.sizeof('struct msm_dump_data')
mem_dump_data = ram_dump.address_of('memdump')
"""
Some multi-guest hypervisor systems override the imem location
with a table for a crashed guest. So the value from IMEM may
not match the value saved in the linux variable 'memdump'.
"""
table_phys = ram_dump.read_word(
ram_dump.board.imem_start + IMEM_OFFSET_MEM_DUMP_TABLE,
virtual = False)
root_table = self.validateMsmDumpTable(ram_dump, "IMEM", table_phys)
mem_dump_table = ram_dump.read_word(
mem_dump_data + dump_table_ptr_offset)
if root_table is None:
table_phys = ram_dump.read_structure_field(
'memdump', 'struct msm_memory_dump', 'table_phys')
root_table = self.validateMsmDumpTable(ram_dump, "RAM", table_phys)
mem_table_version = ram_dump.read_u32(
mem_dump_table + dump_table_version_offset)
if mem_table_version is None:
print_out_str('Version is bogus! Can\'t parse debug image')
return
mem_table_num_entry = ram_dump.read_u32(
mem_dump_table + dump_table_num_entry_offset)
if mem_table_num_entry is None or mem_table_num_entry > 100:
print_out_str('num_entries is bogus! Can\'t parse debug image')
if root_table is None:
return
print_out_str('\nDebug image version: {0}.{1} Number of table entries {2}'.format(
mem_table_version >> 20, mem_table_version & 0xFFFFF, mem_table_num_entry))
root_table.version >> 20, root_table.version & 0xFFFFF, root_table.num_entries))
print_out_str('--------')
for i in range(0, mem_table_num_entry):
this_entry = mem_dump_table + dump_table_entry_offset + \
for i in range(0, root_table.num_entries):
this_entry = root_table.phys_addr + dump_table_entry_offset + \
i * dump_entry_size
entry_id = ram_dump.read_u32(this_entry + dump_entry_id_offset)
entry_type = ram_dump.read_u32(this_entry + dump_entry_type_offset)
entry_addr = ram_dump.read_word(this_entry + dump_entry_addr_offset)
entry_id = ram_dump.read_u32(this_entry + dump_entry_id_offset, virtual = False)
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(
......
......@@ -51,7 +51,9 @@ extra_mem_file_names = ['EBI1CS1.BIN', 'DDRCS1.BIN', 'ebi1_cs1.bin',
'DDRCS1_5.BIN']
DDR_FILE_NAMES = ['DDRCS0.BIN', 'DDRCS1.BIN', 'DDRCS0_0.BIN',
'DDRCS1_0.BIN', 'DDRCS0_1.BIN', 'DDRCS1_1.BIN']
'DDRCS1_0.BIN', 'DDRCS0_1.BIN', 'DDRCS1_1.BIN',
'DDR_0.BIN', 'DDR_1.BIN', 'DDR_2.BIN', 'DDR_3.BIN',
'RESET_INFO.BIN']
OTHER_DUMP_FILE_NAMES = ['PIMEM.BIN', 'OCIMEM.BIN','md_shared_imem.BIN',
'md_smem_info.BIN']
RAM_FILE_NAMES = set(DDR_FILE_NAMES +
......@@ -1213,6 +1215,7 @@ class RamDump():
self.kaslr_addr = board.kaslr_addr
else:
self.kaslr_addr = None
self.board = board
return True
def resolve_virt(self, virt_or_name):
......@@ -1491,19 +1494,18 @@ class RamDump():
fn = self.read_u32 if self.sizeof('void *') == 4 else self.read_u64
return fn(addr_or_name, virtual, cpu)
def read_structure_field(self, addr_or_name, struct_name, field):
def read_structure_field(self, addr_or_name, struct_name, field, virtual=True):
"""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:
addr = self.resolve_virt(addr_or_name)
if addr is None or size is None:
return None
addr += self.field_offset(struct_name, field)
if size == 4:
return self.read_u32(virt + self.field_offset(struct_name,
field))
return self.read_u32(addr, virtual)
if size == 8:
return self.read_u64(virt + self.field_offset(struct_name,
field))
return self.read_u64(addr, virtual)
return None
def read_structure_cstring(self, addr_or_name, struct_name, field,
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment