diff --git a/linux-ramdump-parser-v2/bitops.py b/linux-ramdump-parser-v2/bitops.py
index 4f9da69254b587f587f3a94f642bb65c20a4dc50..ab1901af4e756bb1c1b287836fddf4671c29a947 100644
--- a/linux-ramdump-parser-v2/bitops.py
+++ b/linux-ramdump-parser-v2/bitops.py
@@ -9,6 +9,8 @@
 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 # GNU General Public License for more details.
 
+import ctypes
+
 
 def bm(msb, lsb):
     'Creates a bitmask from msb to lsb'
@@ -25,3 +27,10 @@ def is_set(val, bit):
     if (val >> bit) & 0x1:
         return True
     return False
+
+
+def align(x, a):
+    """Round x up to the nearest multiple of a"""
+    # See include/uapi/linux/kernel.h
+    notmask = ctypes.c_uint64(~(a - 1)).value
+    return (x + a - 1) & notmask
diff --git a/linux-ramdump-parser-v2/debug_image_v2.py b/linux-ramdump-parser-v2/debug_image_v2.py
index 061f1fd3c4969bc159b5bfd84929d11b73b43182..f63d37b67ee35fe097c2c4e7bccac9883ed37862 100644
--- a/linux-ramdump-parser-v2/debug_image_v2.py
+++ b/linux-ramdump-parser-v2/debug_image_v2.py
@@ -169,8 +169,11 @@ class DebugImage_v2():
         cache_type = lookup_cache_type(ramdump.hw_id, client_id, version)
         try:
             cache_type.parse(start, end, ramdump, outfile)
+        except NotImplementedError:
+            print_out_str('Cache dumping not supported for %s on this target'
+                          % client_name)
         except:
-            print_out_str('!!! Exception while running {0}'.format(client_name))
+            print_out_str('!!! Unhandled exception while running {0}'.format(client_name))
             print_out_exception()
         outfile.close()
 
diff --git a/linux-ramdump-parser-v2/mm.py b/linux-ramdump-parser-v2/mm.py
index 72e611ffa1660a07f0382d06df6f4e9fcec3a7bb..09e648461dfbd000de1cab41e114d07df44f0b28 100755
--- a/linux-ramdump-parser-v2/mm.py
+++ b/linux-ramdump-parser-v2/mm.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
+# Copyright (c) 2013-2015, The Linux Foundation. All rights reserved.
 #
 # This program is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License version 2 and
@@ -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,21 +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')
-    pfn_offset = ramdump.phys_offset >> 12
-    return mem_map + (pfn * page_size)
+    return vmemmap + (pfn * page_size)
 
 
 def page_to_pfn_flat(ramdump, page):
diff --git a/linux-ramdump-parser-v2/ramdump.py b/linux-ramdump-parser-v2/ramdump.py
index feb9f6a890cf898a9533db8e10b3cb7330b76167..10af03725cd90aeea57c8eb22bce16d87ed8044e 100644
--- a/linux-ramdump-parser-v2/ramdump.py
+++ b/linux-ramdump-parser-v2/ramdump.py
@@ -496,6 +496,7 @@ class RamDump():
             self.phys_offset = options.phys_offset
         self.lookup_table = []
         self.config = []
+        self.config_dict = {}
         if self.arm64:
             self.page_offset = 0xffffffc000000000
             self.thread_size = 16384
@@ -618,8 +619,14 @@ class RamDump():
         os.remove(zconfig.name)
         for l in t:
             self.config.append(l.rstrip().decode('ascii', 'ignore'))
+            if not l.startswith('#') and l.strip() != '':
+                cfg, val = l.split('=')
+                self.config_dict[cfg] = val.strip()
         return True
 
+    def get_config_val(self, config):
+        return self.config_dict.get(config)
+
     def is_config_defined(self, config):
         s = config + '=y'
         return s in self.config