Skip to content
Snippets Groups Projects
Commit c64a912a authored by Ankur Bansal's avatar Ankur Bansal
Browse files

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: default avatarAnkur Bansal <ankban@codeaurora.org>
parent f23c453e
No related branches found
No related tags found
No related merge requests found
...@@ -12,30 +12,52 @@ ...@@ -12,30 +12,52 @@
from print_out import print_out_str from print_out import print_out_str
from parser_util import register_parser, RamParser from parser_util import register_parser, RamParser
from mm import pfn_to_page, page_buddy, page_count, for_each_pfn 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)') @register_parser('--print-pagetracking', 'print page tracking information (if available)')
class PageTracking(RamParser): class PageTracking(RamParser):
def parse(self): def __init__(self, *args):
if not self.ramdump.is_config_defined('CONFIG_PAGE_OWNER'): super(PageTracking, self).__init__(*args)
print_out_str('CONFIG_PAGE_OWNER not defined') self.trace_entry_size = self.ramdump.sizeof('unsigned long')
return 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'):
if self.ramdump.is_config_defined('CONFIG_SPARSEMEM'): self.mem_section_size = self.ramdump.sizeof("struct mem_section")
mem_section = self.ramdump.read_word('mem_section') else:
if self.ramdump.kernel_version >= (4, 14): self.mem_section_size = 0
mem_section = self.ramdump.read_word(mem_section)
else: '''
mem_section = self.ramdump.address_of('contig_page_data') 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 trace_offset = 0
nr_entries_offset = 0 nr_entries_offset = 0
trace_entries_offset = 0 trace_entries_offset = 0
offset = 0 offset = 0
struct_holding_trace_entries = 0 struct_holding_trace_entries = 0
trace_entry_size = self.ramdump.sizeof("unsigned long")
if (self.ramdump.kernel_version <= (3, 19, 0)): if (self.ramdump.kernel_version <= (3, 19, 0)):
trace_offset = self.ramdump.field_offset('struct page', 'trace') trace_offset = self.ramdump.field_offset('struct page', 'trace')
...@@ -43,166 +65,192 @@ class PageTracking(RamParser): ...@@ -43,166 +65,192 @@ class PageTracking(RamParser):
'struct stack_trace', 'nr_entries') 'struct stack_trace', 'nr_entries')
trace_entries_offset = self.ramdump.field_offset( trace_entries_offset = self.ramdump.field_offset(
'struct page', 'trace_entries') '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( trace_offset = self.ramdump.field_offset(
'struct page_ext', 'trace') 'struct page_ext', 'trace')
if self.ramdump.is_config_defined('CONFIG_STACKDEPOT'): if self.ramdump.is_config_defined('CONFIG_STACKDEPOT'):
trace_entries_offset = self.ramdump.field_offset( trace_entries_offset = self.ramdump.field_offset(
'struct stack_record', 'entries') 'struct stack_record', 'entries')
else: else:
trace_entries_offset = self.ramdump.field_offset( trace_entries_offset = self.ramdump.field_offset(
'struct page_ext', 'trace_entries') 'struct page_ext', 'trace_entries')
nr_entries_offset = self.ramdump.field_offset( nr_entries_offset = self.ramdump.field_offset(
'struct page_ext', 'nr_entries') '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;
page_ext_size = self.ramdump.sizeof("struct page_ext") 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_owner_size = self.ramdump.sizeof("struct page_owner")
page_ext_size = page_ext_size + page_owner_size page_ext_size = page_ext_size + page_owner_size
page_owner_ops_offset = self.ramdump.read_structure_field( page_owner_ops_offset = self.ramdump.read_structure_field(
'page_owner_ops', 'struct page_ext_operations', 'offset') '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') if (self.ramdump.kernel_version <= (3, 19, 0)):
out_frequency = self.ramdump.open_file('page_frequency.txt') nr_trace_entries = self.ramdump.read_int(
sorted_pages = {} page + trace_offset + nr_entries_offset)
struct_holding_trace_entries = page
''' order = self.ramdump.read_structure_field(
Following based upon definition in include/linux/mmzone.h 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 if self.ramdump.arm64:
#define MAX_ORDER 11 temp_page_ext = page_ext + (pfn * page_ext_size)
#else else:
#define MAX_ORDER CONFIG_FORCE_MAX_ZONEORDER pfn_index = pfn - (self.ramdump.phys_offset >> 12)
#endif temp_page_ext = page_ext + (pfn_index * page_ext_size)
'''
try:
max_order = int(self.ramdump.get_config_val("CONFIG_FORCE_MAX_ZONEORDER"))
except:
max_order = 11
for pfn in for_each_pfn(self.ramdump): if self.ramdump.kernel_version >= (4, 9, 0):
page = pfn_to_page(self.ramdump, pfn) temp_page_ext = temp_page_ext + page_owner_ops_offset
order = 0 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 not self.ramdump.is_config_defined('CONFIG_STACKDEPOT'):
if (page_buddy(self.ramdump, page) or
page_count(self.ramdump, page) == 0):
continue
if (self.ramdump.kernel_version <= (3, 19, 0)):
nr_trace_entries = self.ramdump.read_int( nr_trace_entries = self.ramdump.read_int(
page + trace_offset + nr_entries_offset) temp_page_ext + nr_entries_offset)
struct_holding_trace_entries = page struct_holding_trace_entries = temp_page_ext
order = self.ramdump.read_structure_field(
page, 'struct page', 'order')
else: else:
phys = pfn << 12 if self.ramdump.kernel_version >= (4, 9, 0):
if phys is None or phys is 0: handle = self.ramdump.read_structure_field(
continue temp_page_ext, 'struct page_owner', 'handle')
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: 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'): slabindex = handle & 0x1fffff
mem_section_0_offset = ( handle_offset = (handle >> 0x15) & 0x3ff
mem_section + (offset * mem_section_size)) handle_offset = handle_offset << 4
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)
slab = self.ramdump.read_word(
self.stack_slabs + (self.stack_slabs_size * slabindex))
stack = slab + handle_offset
if self.ramdump.arm64: nr_trace_entries = self.ramdump.read_structure_field(
temp_page_ext = page_ext + (pfn * page_ext_size) stack, 'struct stack_record', 'size')
else:
pfn_index = pfn - (self.ramdump.phys_offset >> 12)
temp_page_ext = page_ext + (pfn_index * page_ext_size)
if self.ramdump.kernel_version >= (4,9,0): struct_holding_trace_entries = stack
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'):
nr_trace_entries = self.ramdump.read_int( if nr_trace_entries <= 0 or nr_trace_entries > 16:
temp_page_ext + nr_entries_offset) return
struct_holding_trace_entries = temp_page_ext if order >= self.max_order:
return
else: alloc_str = ''
if self.ramdump.kernel_version >= (4,9,0): for i in range(0, nr_trace_entries):
handle = self.ramdump.read_structure_field( addr = self.ramdump.read_word(
temp_page_ext, 'struct page_owner', 'handle') struct_holding_trace_entries + trace_entries_offset + i *
else: self.trace_entry_size)
handle = self.ramdump.read_structure_field(
temp_page_ext, 'struct page_ext', 'handle') if not addr:
break
slabindex = handle & 0x1fffff look = self.ramdump.unwind_lookup(addr)
handle_offset = (handle >> 0x15) & 0x3ff if look is None:
handle_offset = handle_offset << 4 break
symname, offset = look
stack_slabs = self.ramdump.address_of('stack_slabs') unwind_dat = ' [<{0:x}>] {1}+0x{2:x}\n'.format(
stack_slabs_size = self.ramdump.sizeof('void *') addr, symname, offset)
slab = self.ramdump.read_word(stack_slabs + ( stack_slabs_size * slabindex)) alloc_str = alloc_str + unwind_dat
stack = slab + handle_offset
return alloc_str, order
nr_trace_entries = self.ramdump.read_structure_field(
stack, 'struct stack_record', 'size') def parse(self):
ranges = None
struct_holding_trace_entries = stack for arg in sys.argv:
if "ranges=" in arg:
g_optimization = True
if nr_trace_entries <= 0 or nr_trace_entries > 16: k, ranges = arg.split("=")
continue start, end = ranges.split('-')
start_pfn = int(start, 16) >> 12
if order >= max_order: end_pfn = int(end, 16) >> 12
out_tracking.write('PFN 0x{:x} page 0x{:x} skip as order 0x{:x}\n'.format( break
pfn, page, order)) elif "page=" in arg:
continue g_optimization = True
k, page = arg.split('=')
out_tracking.write('PFN 0x{:x}-0x{:x} page 0x{:x}\n'.format( page = int(page, 16)
pfn, pfn + (1 << order) - 1, page)) start_pfn = page_to_pfn(self.ramdump, page)
end_pfn = start_pfn + 1
alloc_str = '' break
for i in range(0, nr_trace_entries): else:
addr = self.ramdump.read_word( g_optimization = False
struct_holding_trace_entries + trace_entries_offset + i * trace_entry_size) if not self.ramdump.is_config_defined('CONFIG_PAGE_OWNER'):
print_out_str('CONFIG_PAGE_OWNER not defined')
if addr == 0: return
break
look = self.ramdump.unwind_lookup(addr) if (self.ramdump.kernel_version >= (3, 19, 0)):
if look is None: if self.ramdump.is_config_defined('CONFIG_SPARSEMEM'):
break mem_section = self.ramdump.read_word('mem_section')
symname, offset = look if self.ramdump.kernel_version >= (4, 14):
unwind_dat = ' [<{0:x}>] {1}+0x{2:x}\n'.format( mem_section = self.ramdump.read_word(mem_section)
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
else: 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(), sortlist = sorted(sorted_pages.iteritems(),
key=lambda(k, v): (v), reverse=True) key=lambda(k, v): (v), reverse=True)
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment