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 @@
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)
......
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