From c64a912a02b7fe73289afc9abe74b29a2b493d0c Mon Sep 17 00:00:00 2001 From: Ankur Bansal <ankban@codeaurora.org> Date: Thu, 30 Aug 2018 22:31:33 +0530 Subject: [PATCH] lrdp_V2 : Add range feature in pagetracking.py Add range feature in pagetracking.py. sometimes we need page owner of particular page or physical address and we need to run complete pagetracking which is taking more time. now with this we can get the owner call stack by providing the below option in few seconds. Ex of flags given in ramparser cmd : 1) pagetracking for range from phy_addr1 to phy_add2 --print-pagetrcking ranges=addr1-addr2 2) page owner for particular page --print-pagetracking page=<page> Change-Id: I5113b5da4a71865ae2813fa48a1b306fb72eb8ff Signed-off-by: Ankur Bansal <ankban@codeaurora.org> --- .../parsers/pagetracking.py | 334 ++++++++++-------- 1 file changed, 191 insertions(+), 143 deletions(-) diff --git a/linux-ramdump-parser-v2/parsers/pagetracking.py b/linux-ramdump-parser-v2/parsers/pagetracking.py index d21165c..c5ddb39 100644 --- a/linux-ramdump-parser-v2/parsers/pagetracking.py +++ b/linux-ramdump-parser-v2/parsers/pagetracking.py @@ -12,30 +12,52 @@ from print_out import print_out_str from parser_util import register_parser, RamParser from mm import pfn_to_page, page_buddy, page_count, for_each_pfn +from mm import page_to_pfn +import sys @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 + 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') - if (self.ramdump.kernel_version >= (3, 19, 0)): - if self.ramdump.is_config_defined('CONFIG_SPARSEMEM'): - mem_section = self.ramdump.read_word('mem_section') - if self.ramdump.kernel_version >= (4, 14): - mem_section = self.ramdump.read_word(mem_section) - else: - mem_section = self.ramdump.address_of('contig_page_data') + if self.ramdump.is_config_defined('CONFIG_SPARSEMEM'): + self.mem_section_size = self.ramdump.sizeof("struct mem_section") + else: + self.mem_section_size = 0 + + ''' + Following based upon definition in include/linux/mmzone.h + + #ifndef CONFIG_FORCE_MAX_ZONEORDER + #define MAX_ORDER 11 + #else + #define MAX_ORDER CONFIG_FORCE_MAX_ZONEORDER + #endif + ''' + try: + self.max_order = int(self.ramdump.get_config_val( + "CONFIG_FORCE_MAX_ZONEORDER")) + except: + self.max_order = 11 + + self.stack_slabs = self.ramdump.address_of('stack_slabs') + self.stack_slabs_size = self.ramdump.sizeof('void *') + def page_trace(self, pfn, 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') @@ -43,166 +65,192 @@ class PageTracking(RamParser): 'struct stack_trace', 'nr_entries') trace_entries_offset = self.ramdump.field_offset( 'struct page', 'trace_entries') - else: - if self.ramdump.is_config_defined('CONFIG_SPARSEMEM'): - page_ext_offset = self.ramdump.field_offset( - 'struct mem_section', 'page_ext') - else: - page_ext_offset = self.ramdump.field_offset( - 'struct pglist_data', 'node_page_ext') + else: trace_offset = self.ramdump.field_offset( - 'struct page_ext', 'trace') + 'struct page_ext', 'trace') if self.ramdump.is_config_defined('CONFIG_STACKDEPOT'): trace_entries_offset = self.ramdump.field_offset( - 'struct stack_record', 'entries') + 'struct stack_record', 'entries') else: trace_entries_offset = self.ramdump.field_offset( - 'struct page_ext', 'trace_entries') - + 'struct page_ext', 'trace_entries') nr_entries_offset = self.ramdump.field_offset( - 'struct page_ext', 'nr_entries') - if self.ramdump.is_config_defined('CONFIG_SPARSEMEM'): - mem_section_size = self.ramdump.sizeof("struct mem_section") - else: - mem_section_size = 0; + 'struct page_ext', 'nr_entries') + page_ext_size = self.ramdump.sizeof("struct page_ext") - if self.ramdump.kernel_version >= (4,9,0): + if self.ramdump.kernel_version >= (4, 9, 0): page_owner_size = self.ramdump.sizeof("struct page_owner") page_ext_size = page_ext_size + page_owner_size page_owner_ops_offset = self.ramdump.read_structure_field( 'page_owner_ops', 'struct page_ext_operations', 'offset') + page = pfn_to_page(self.ramdump, pfn) + order = 0 - out_tracking = self.ramdump.open_file('page_tracking.txt') - out_frequency = self.ramdump.open_file('page_frequency.txt') - sorted_pages = {} - - ''' - Following based upon definition in include/linux/mmzone.h + 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 == 0: + return + if self.ramdump.is_config_defined('CONFIG_MEMORY_HOTPLUG'): + section_size_bits = int(self.ramdump.get_config_val( + 'CONFIG_HOTPLUG_SIZE_BITS')) + offset = phys >> section_size_bits + else: + offset = phys >> 30 + if self.ramdump.is_config_defined('CONFIG_SPARSEMEM'): + mem_section_0_offset = ( + mem_section + offset * self.mem_section_size) + page_ext = self.ramdump.read_word( + mem_section_0_offset + self.page_ext_offset) + else: + page_ext = self.ramdump.read_word( + mem_section + self.page_ext_offset) - #ifndef CONFIG_FORCE_MAX_ZONEORDER - #define MAX_ORDER 11 - #else - #define MAX_ORDER CONFIG_FORCE_MAX_ZONEORDER - #endif - ''' - try: - max_order = int(self.ramdump.get_config_val("CONFIG_FORCE_MAX_ZONEORDER")) - except: - max_order = 11 + if self.ramdump.arm64: + temp_page_ext = page_ext + (pfn * page_ext_size) + else: + pfn_index = pfn - (self.ramdump.phys_offset >> 12) + temp_page_ext = page_ext + (pfn_index * page_ext_size) - for pfn in for_each_pfn(self.ramdump): - page = pfn_to_page(self.ramdump, pfn) - order = 0 + if self.ramdump.kernel_version >= (4, 9, 0): + temp_page_ext = temp_page_ext + page_owner_ops_offset + order = self.ramdump.read_structure_field( + temp_page_ext, 'struct page_owner', 'order') + else: + order = self.ramdump.read_structure_field( + temp_page_ext, 'struct page_ext', 'order') - """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 - if (self.ramdump.kernel_version <= (3, 19, 0)): + if not self.ramdump.is_config_defined('CONFIG_STACKDEPOT'): 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') + temp_page_ext + nr_entries_offset) + struct_holding_trace_entries = temp_page_ext else: - phys = pfn << 12 - if phys is None or phys is 0: - continue - if self.ramdump.is_config_defined('CONFIG_MEMORY_HOTPLUG'): - section_size_bits = int(self.ramdump.get_config_val( - 'CONFIG_HOTPLUG_SIZE_BITS')) - offset = phys >> section_size_bits + if self.ramdump.kernel_version >= (4, 9, 0): + handle = self.ramdump.read_structure_field( + temp_page_ext, 'struct page_owner', 'handle') else: - offset = phys >> 30 + handle = self.ramdump.read_structure_field( + temp_page_ext, 'struct page_ext', 'handle') - if self.ramdump.is_config_defined('CONFIG_SPARSEMEM'): - mem_section_0_offset = ( - mem_section + (offset * mem_section_size)) - page_ext = self.ramdump.read_word( - mem_section_0_offset + page_ext_offset) - else: - page_ext = self.ramdump.read_word( - mem_section + page_ext_offset) + slabindex = handle & 0x1fffff + handle_offset = (handle >> 0x15) & 0x3ff + handle_offset = handle_offset << 4 + slab = self.ramdump.read_word( + self.stack_slabs + (self.stack_slabs_size * slabindex)) + stack = slab + handle_offset - if self.ramdump.arm64: - temp_page_ext = page_ext + (pfn * page_ext_size) - else: - pfn_index = pfn - (self.ramdump.phys_offset >> 12) - temp_page_ext = page_ext + (pfn_index * page_ext_size) + nr_trace_entries = self.ramdump.read_structure_field( + stack, 'struct stack_record', 'size') - if self.ramdump.kernel_version >= (4,9,0): - temp_page_ext = temp_page_ext + page_owner_ops_offset - order = self.ramdump.read_structure_field( - temp_page_ext, 'struct page_owner', 'order') - else: - order = self.ramdump.read_structure_field( - temp_page_ext, 'struct page_ext', 'order') - if not self.ramdump.is_config_defined('CONFIG_STACKDEPOT'): + struct_holding_trace_entries = stack - nr_trace_entries = self.ramdump.read_int( - temp_page_ext + nr_entries_offset) - struct_holding_trace_entries = temp_page_ext + if nr_trace_entries <= 0 or nr_trace_entries > 16: + return + if order >= self.max_order: + return - else: - if self.ramdump.kernel_version >= (4,9,0): - handle = self.ramdump.read_structure_field( - temp_page_ext, 'struct page_owner', 'handle') - else: - handle = self.ramdump.read_structure_field( - temp_page_ext, 'struct page_ext', 'handle') - - slabindex = handle & 0x1fffff - handle_offset = (handle >> 0x15) & 0x3ff - handle_offset = handle_offset << 4 - - stack_slabs = self.ramdump.address_of('stack_slabs') - stack_slabs_size = self.ramdump.sizeof('void *') - slab = self.ramdump.read_word(stack_slabs + ( stack_slabs_size * slabindex)) - stack = slab + handle_offset - - nr_trace_entries = self.ramdump.read_structure_field( - stack, 'struct stack_record', 'size') - - struct_holding_trace_entries = stack - - - if nr_trace_entries <= 0 or nr_trace_entries > 16: - continue - - if order >= max_order: - out_tracking.write('PFN 0x{:x} page 0x{:x} skip as order 0x{:x}\n'.format( - pfn, page, order)) - continue - - 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( - struct_holding_trace_entries + trace_entries_offset + i * trace_entry_size) - - if addr == 0: - break - look = self.ramdump.unwind_lookup(addr) - if look is None: - break - symname, offset = look - unwind_dat = ' [<{0:x}>] {1}+0x{2:x}\n'.format( - addr, symname, offset) - out_tracking.write(unwind_dat) - alloc_str = alloc_str + unwind_dat - - if alloc_str in sorted_pages: - sorted_pages[alloc_str] = sorted_pages[alloc_str] + 1 + alloc_str = '' + for i in range(0, nr_trace_entries): + addr = self.ramdump.read_word( + struct_holding_trace_entries + trace_entries_offset + i * + self.trace_entry_size) + + if not addr: + break + look = self.ramdump.unwind_lookup(addr) + if look is None: + break + symname, offset = look + unwind_dat = ' [<{0:x}>] {1}+0x{2:x}\n'.format( + addr, symname, offset) + alloc_str = alloc_str + unwind_dat + + return alloc_str, order + + def parse(self): + ranges = None + for arg in sys.argv: + if "ranges=" in arg: + g_optimization = True + k, ranges = arg.split("=") + start, end = ranges.split('-') + start_pfn = int(start, 16) >> 12 + end_pfn = int(end, 16) >> 12 + break + elif "page=" in arg: + g_optimization = True + k, page = arg.split('=') + page = int(page, 16) + start_pfn = page_to_pfn(self.ramdump, page) + end_pfn = start_pfn + 1 + break + else: + g_optimization = False + if not self.ramdump.is_config_defined('CONFIG_PAGE_OWNER'): + print_out_str('CONFIG_PAGE_OWNER not defined') + return + + if (self.ramdump.kernel_version >= (3, 19, 0)): + if self.ramdump.is_config_defined('CONFIG_SPARSEMEM'): + mem_section = self.ramdump.read_word('mem_section') + if self.ramdump.kernel_version >= (4, 14): + mem_section = self.ramdump.read_word(mem_section) else: - sorted_pages[alloc_str] = 1 + mem_section = self.ramdump.address_of('contig_page_data') - out_tracking.write('\n') + out_tracking = self.ramdump.open_file('page_tracking.txt') + out_frequency = self.ramdump.open_file('page_frequency.txt') + sorted_pages = {} + str = "PFN : 0x{0:x}-0x{1:x} Page : 0x{2:x}\n{3}\n" + + if g_optimization is True: + for pfn in range(start_pfn, end_pfn): + page = pfn_to_page(self.ramdump, pfn) + order = 0 + if (page_buddy(self.ramdump, page) or + page_count(self.ramdump, page) == 0): + continue + function_list, order = self.page_trace(pfn, mem_section) + if order >= self.max_order: + out_tracking.write('PFN 0x{:x} page 0x{:x} skip as order ' + '0x{:x}\n'.format(pfn, page, order)) + out_tracking.write(str.format(pfn, pfn + (1 << order) - 1, + page, function_list)) + if function_list in sorted_pages: + sorted_pages[function_list] = sorted_pages[function_list]\ + + 1 + else: + sorted_pages[function_list] = 1 + + else: + for pfn in for_each_pfn(self.ramdump): + page = pfn_to_page(self.ramdump, pfn) + order = 0 + if (page_buddy(self.ramdump, page) or + page_count(self.ramdump, page) == 0): + continue + function_list, order = self.page_trace(pfn, mem_section) + if order >= self.max_order: + out_tracking.write('PFN 0x{:x} page 0x{:x} skip as order ' + '0x{:x}\n'.format(pfn, page, order)) + + out_tracking.write(str.format(pfn, pfn + (1 << order) - 1, + page, function_list)) + + if function_list in sorted_pages: + sorted_pages[function_list] = sorted_pages[function_list]\ + + 1 + else: + sorted_pages[function_list] = 1 sortlist = sorted(sorted_pages.iteritems(), key=lambda(k, v): (v), reverse=True) -- GitLab