From 75feef4e2bd89e9a39d5c5b09477f13d8836d2c8 Mon Sep 17 00:00:00 2001
From: Patrick Daly <pdaly@codeaurora.org>
Date: Tue, 28 Mar 2017 14:04:43 -0700
Subject: [PATCH] lrdp-v2: mm: Add pfn iterator

Add a utility function for iterating through all valid pages.
Use it in --print-pagetracking to fix an issue where invalid pfn numbers
are being used.

Change-Id: Iea87fd9afe2515c0be47ae32fa19db0aff5f3403
---
 linux-ramdump-parser-v2/mm.py                 | 27 +++++++++++++++++++
 .../parsers/pagetracking.py                   | 11 ++------
 2 files changed, 29 insertions(+), 9 deletions(-)

diff --git a/linux-ramdump-parser-v2/mm.py b/linux-ramdump-parser-v2/mm.py
index 538af9c..efca724 100644
--- a/linux-ramdump-parser-v2/mm.py
+++ b/linux-ramdump-parser-v2/mm.py
@@ -304,3 +304,30 @@ def page_address(ramdump, page):
         pam = ramdump.read_word(pam + lh_offset)
         if pam == start:
             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
diff --git a/linux-ramdump-parser-v2/parsers/pagetracking.py b/linux-ramdump-parser-v2/parsers/pagetracking.py
index 1d37141..c627ac8 100644
--- a/linux-ramdump-parser-v2/parsers/pagetracking.py
+++ b/linux-ramdump-parser-v2/parsers/pagetracking.py
@@ -11,7 +11,7 @@
 
 from print_out import print_out_str
 from parser_util import register_parser, RamParser
-from mm import pfn_to_page, page_buddy, page_count
+from mm import pfn_to_page, page_buddy, page_count, for_each_pfn
 
 
 @register_parser('--print-pagetracking', 'print page tracking information (if available)')
@@ -22,13 +22,6 @@ class PageTracking(RamParser):
             print_out_str('CONFIG_PAGE_OWNER not defined')
             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)):
             mem_section = self.ramdump.read_word('mem_section')
 
@@ -61,7 +54,7 @@ class PageTracking(RamParser):
         out_frequency = self.ramdump.open_file('page_frequency.txt')
         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)
             order = 0
 
-- 
GitLab