Skip to content
Snippets Groups Projects
Commit e02f5565 authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "lrdp-v2: mm: Add pfn iterator"

parents 3c4120aa 75feef4e
No related branches found
No related tags found
No related merge requests found
...@@ -19,6 +19,21 @@ def page_buddy(ramdump, page): ...@@ -19,6 +19,21 @@ def page_buddy(ramdump, page):
return val == 0xffffff80 return val == 0xffffff80
def page_count(ramdump, page):
"""Commit: 0139aa7b7fa12ceef095d99dc36606a5b10ab83a
mm: rename _count, field of the struct page, to _refcount"""
if (ramdump.version < (4, 6, 0)):
count = ramdump.read_structure_field(page, 'struct page',
'_count.counter')
else:
count = ramdump.read_structure_field(page, 'struct page',
'_refcount.counter')
return count
def page_ref_count(ramdump, page):
return page_count(ramdump, page)
def get_debug_flags(ramdump, page): def get_debug_flags(ramdump, page):
debug_flag_offset = ramdump.field_offset('struct page', 'debug_flags') debug_flag_offset = ramdump.field_offset('struct page', 'debug_flags')
flagval = ramdump.read_word(page + debug_flag_offset) flagval = ramdump.read_word(page + debug_flag_offset)
...@@ -152,22 +167,27 @@ def get_vmemmap(ramdump): ...@@ -152,22 +167,27 @@ def get_vmemmap(ramdump):
spsize = ramdump.sizeof('struct page') spsize = ramdump.sizeof('struct page')
vmemmap_size = bitops.align((1 << (va_bits - page_shift)) * spsize, vmemmap_size = bitops.align((1 << (va_bits - page_shift)) * spsize,
pud_size) pud_size)
pfn_offset = (ramdump.phys_offset >> page_shift)
offset = pfn_offset * spsize memstart_addr = ramdump.read_s64('memstart_addr')
page_section_mask = ~((1 << 18) - 1)
memstart_offset = (memstart_addr >> page_shift) & page_section_mask
memstart_offset *= spsize
if (ramdump.kernel_version < (3, 18, 31)): if (ramdump.kernel_version < (3, 18, 31)):
vmalloc_end = ramdump.page_offset - pud_size - vmemmap_size
# vmalloc_end = 0xFFFFFFBC00000000 # vmalloc_end = 0xFFFFFFBC00000000
vmemmap = ramdump.page_offset - pud_size - vmemmap_size
elif (ramdump.kernel_version < (4, 9, 0)): elif (ramdump.kernel_version < (4, 9, 0)):
# for version >= 3.18.31, # for version >= 3.18.31,
# vmemmap is shifted to base addr (0x80000000) pfn. # vmemmap is shifted to base addr (0x80000000) pfn.
vmalloc_end = ramdump.page_offset - pud_size - vmemmap_size - offset vmemmap = (ramdump.page_offset - pud_size - vmemmap_size -
memstart_offset)
else: else:
# for version >= 4.9.0, # for version >= 4.9.0,
struct_page_max_shift = 6
# vmemmap_size = ( 1 << (39 - 12 - 1 + 6)) # vmemmap_size = ( 1 << (39 - 12 - 1 + 6))
struct_page_max_shift = 6
vmemmap_size = ( 1 << (va_bits - page_shift - 1 + struct_page_max_shift)) vmemmap_size = ( 1 << (va_bits - page_shift - 1 + struct_page_max_shift))
vmalloc_end = ramdump.page_offset - vmemmap_size - offset vmemmap = ramdump.page_offset - vmemmap_size - memstart_offset
return vmalloc_end return vmemmap
def page_to_pfn_vmemmap(ramdump, page): def page_to_pfn_vmemmap(ramdump, page):
...@@ -284,3 +304,30 @@ def page_address(ramdump, page): ...@@ -284,3 +304,30 @@ def page_address(ramdump, page):
pam = ramdump.read_word(pam + lh_offset) pam = ramdump.read_word(pam + lh_offset)
if pam == start: if pam == start:
return None return None
def for_each_pfn(ramdump):
""" creates a generator for looping through valid pfn
Example:
for i in for_each_pfn(ramdump):
page = pfn_to_page(i)
"""
page_size = (1 << 12)
cnt = ramdump.read_structure_field('memblock', 'struct memblock',
'memory.cnt')
region = ramdump.read_structure_field('memblock', 'struct memblock',
'memory.regions')
memblock_region_size = ramdump.sizeof('struct memblock_region')
for i in range(cnt):
start = ramdump.read_structure_field(region, 'struct memblock_region',
'base')
end = start + ramdump.read_structure_field(
region, 'struct memblock_region', 'size')
pfn = start / page_size
end /= page_size
while pfn < end:
yield pfn
pfn += 1
region += memblock_region_size
...@@ -45,7 +45,8 @@ class DDRCompare(RamParser) : ...@@ -45,7 +45,8 @@ class DDRCompare(RamParser) :
bitcheck = virtual & 0x3 bitcheck = virtual & 0x3
if bitcheck: if bitcheck:
virtual = virtual - bitcheck virtual = virtual - bitcheck
physical = self.ramdump.virt_to_phys(virtual) physical = self.ramdump.virt_to_phys(
virtual + self.ramdump.kaslr_offset)
magic = hex(self.ramdump.read_u32(physical, False)).rstrip("L").lstrip("0x").zfill(8) magic = hex(self.ramdump.read_u32(physical, False)).rstrip("L").lstrip("0x").zfill(8)
if (m.group(2) != magic): if (m.group(2) != magic):
......
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
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 from mm import pfn_to_page, page_buddy, page_count, for_each_pfn
@register_parser('--print-pagetracking', 'print page tracking information (if available)') @register_parser('--print-pagetracking', 'print page tracking information (if available)')
...@@ -22,13 +22,6 @@ class PageTracking(RamParser): ...@@ -22,13 +22,6 @@ class PageTracking(RamParser):
print_out_str('CONFIG_PAGE_OWNER not defined') print_out_str('CONFIG_PAGE_OWNER not defined')
return return
min_pfn_addr = self.ramdump.address_of('min_low_pfn')
max_pfn_addr = self.ramdump.address_of('max_pfn')
min_pfn = self.ramdump.read_word(
min_pfn_addr) + (self.ramdump.phys_offset >> 12)
max_pfn = self.ramdump.read_word(
max_pfn_addr) + (self.ramdump.phys_offset >> 12)
if (self.ramdump.kernel_version >= (3, 19, 0)): if (self.ramdump.kernel_version >= (3, 19, 0)):
mem_section = self.ramdump.read_word('mem_section') mem_section = self.ramdump.read_word('mem_section')
...@@ -61,16 +54,20 @@ class PageTracking(RamParser): ...@@ -61,16 +54,20 @@ class PageTracking(RamParser):
out_frequency = self.ramdump.open_file('page_frequency.txt') out_frequency = self.ramdump.open_file('page_frequency.txt')
sorted_pages = {} sorted_pages = {}
for pfn in range(min_pfn, max_pfn): for pfn in for_each_pfn(self.ramdump):
page = pfn_to_page(self.ramdump, pfn) page = pfn_to_page(self.ramdump, pfn)
order = 0
# validate this page is free """must be allocated, and the first pfn of an order > 0 page"""
if page_buddy(self.ramdump, page): if (page_buddy(self.ramdump, page) or
page_count(self.ramdump, page) == 0):
continue continue
if (self.ramdump.kernel_version <= (3, 19, 0)): 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) page + trace_offset + nr_entries_offset)
struct_holding_trace_entries = page struct_holding_trace_entries = page
order = self.ramdump.read_structure_field(
page, 'struct page', 'order')
else: else:
phys = pfn << 12 phys = pfn << 12
if phys is None or phys is 0: if phys is None or phys is 0:
...@@ -85,11 +82,14 @@ class PageTracking(RamParser): ...@@ -85,11 +82,14 @@ class PageTracking(RamParser):
nr_trace_entries = self.ramdump.read_int( nr_trace_entries = self.ramdump.read_int(
temp_page_ext + nr_entries_offset) temp_page_ext + nr_entries_offset)
struct_holding_trace_entries = temp_page_ext struct_holding_trace_entries = temp_page_ext
order = self.ramdump.read_structure_field(
temp_page_ext, 'struct page_ext', 'order')
if nr_trace_entries <= 0 or nr_trace_entries > 16: if nr_trace_entries <= 0 or nr_trace_entries > 16:
continue continue
out_tracking.write('PFN 0x{0:x} page 0x{1:x} \n'.format(pfn, page)) out_tracking.write('PFN 0x{:x}-0x{:x} page 0x{:x}\n'.format(
pfn, pfn + (1 << order) - 1, page))
alloc_str = '' alloc_str = ''
for i in range(0, nr_trace_entries): for i in range(0, nr_trace_entries):
......
...@@ -1318,6 +1318,9 @@ class RamDump(): ...@@ -1318,6 +1318,9 @@ class RamDump():
"""reads a 4 or 8 byte field from a structure""" """reads a 4 or 8 byte field from a structure"""
size = self.sizeof("(({0} *)0)->{1}".format(struct_name, field)) size = self.sizeof("(({0} *)0)->{1}".format(struct_name, field))
virt = self.resolve_virt(addr_or_name) virt = self.resolve_virt(addr_or_name)
if virt is None or size is None:
return None
if size == 4: if size == 4:
return self.read_u32(virt + self.field_offset(struct_name, return self.read_u32(virt + self.field_offset(struct_name,
field)) field))
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment