From 3cf1db68431f187e6aaf47c338f26b0fe137f4b5 Mon Sep 17 00:00:00 2001
From: Mitchel Humpherys <mitchelh@codeaurora.org>
Date: Fri, 6 Nov 2015 17:05:23 -0800
Subject: [PATCH] lrdp-v2: mm: Calculate the vmemmap dynamically

We're currently using a hard-coded value for vmemmap.  This doesn't work
anymore.  Calculate its value dynamically the same way the kernel does
it.

Change-Id: If3e06007ab69c2ee91fefede770c2fb5ccb59fe3
---
 linux-ramdump-parser-v2/mm.py | 35 +++++++++++++++++++++++++++--------
 1 file changed, 27 insertions(+), 8 deletions(-)

diff --git a/linux-ramdump-parser-v2/mm.py b/linux-ramdump-parser-v2/mm.py
index df85030..09e6484 100755
--- a/linux-ramdump-parser-v2/mm.py
+++ b/linux-ramdump-parser-v2/mm.py
@@ -9,6 +9,8 @@
 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 # GNU General Public License for more details.
 
+import bitops
+
 
 def page_buddy(ramdump, page):
     mapcount_offset = ramdump.field_offset('struct page', '_mapcount')
@@ -127,20 +129,37 @@ def page_to_pfn_sparse(ramdump, page):
     # divide by struct page size for division fun
     return (page - addr) / sizeof_page
 
-# Yes, we are hard coding the vmemmap. This isn't very likely to change unless
-# the rest of the addresses start changing as well. When that happens, the
-# entire parser will probably be broken in many other ways so a better solution
-# can be derived then.
+
+def get_vmemmap(ramdump):
+    # See: include/asm-generic/pgtable-nopud.h,
+    # arch/arm64/include/asm/pgtable-hwdef.h,
+    # arch/arm64/include/asm/pgtable.h
+    nlevels = int(ramdump.get_config_val("CONFIG_ARM64_PGTABLE_LEVELS"))
+    if ramdump.is_config_defined("CONFIG_ARM64_64K_PAGES"):
+        page_shift = 16
+    else:
+        page_shift = 12
+    pgdir_shift = ((page_shift - 3) * nlevels) + 3
+    pud_shift = pgdir_shift
+    pud_size = 1 << pud_shift
+    va_bits = int(ramdump.get_config_val("CONFIG_ARM64_VA_BITS"))
+    spsize = ramdump.sizeof('struct page')
+    vmemmap_size = bitops.align((1 << (va_bits - page_shift)) * spsize,
+                                pud_size)
+    vmalloc_end = ramdump.page_offset - pud_size - vmemmap_size
+    return vmalloc_end
+
+
 def page_to_pfn_vmemmap(ramdump, page):
-    mem_map = 0xffffffbc00000000
+    vmemmap = get_vmemmap(ramdump)
     page_size = ramdump.sizeof('struct page')
-    return ((page - mem_map) / page_size)
+    return ((page - vmemmap) / page_size)
 
 
 def pfn_to_page_vmemmap(ramdump, pfn):
-    mem_map = 0xffffffbc00000000
+    vmemmap = get_vmemmap(ramdump)
     page_size = ramdump.sizeof('struct page')
-    return mem_map + (pfn * page_size)
+    return vmemmap + (pfn * page_size)
 
 
 def page_to_pfn_flat(ramdump, page):
-- 
GitLab