struct page *vm_normal_page(struct vm_area_struct *vma, unsigned long addr,
                                pte_t pte)
 {
-       unsigned long pfn;
+       unsigned long pfn = pte_pfn(pte);
 
        if (HAVE_PTE_SPECIAL) {
-               if (likely(!pte_special(pte))) {
-                       VM_BUG_ON(!pfn_valid(pte_pfn(pte)));
-                       return pte_page(pte);
-               }
-               VM_BUG_ON(!(vma->vm_flags & (VM_PFNMAP | VM_MIXEDMAP)));
+               if (likely(!pte_special(pte)))
+                       goto check_pfn;
+               if (!(vma->vm_flags & (VM_PFNMAP | VM_MIXEDMAP)))
+                       print_bad_pte(vma, addr, pte, NULL);
                return NULL;
        }
 
        /* !HAVE_PTE_SPECIAL case follows: */
 
-       pfn = pte_pfn(pte);
-
        if (unlikely(vma->vm_flags & (VM_PFNMAP|VM_MIXEDMAP))) {
                if (vma->vm_flags & VM_MIXEDMAP) {
                        if (!pfn_valid(pfn))
                }
        }
 
-       VM_BUG_ON(!pfn_valid(pfn));
+check_pfn:
+       if (unlikely(pfn > highest_memmap_pfn)) {
+               print_bad_pte(vma, addr, pte, NULL);
+               return NULL;
+       }
 
        /*
         * NOTE! We still have PageReserved() pages in the page tables.
-        *
         * eg. VDSO mappings can cause them to exist.
         */
 out:
 
 
 unsigned long totalram_pages __read_mostly;
 unsigned long totalreserve_pages __read_mostly;
+unsigned long highest_memmap_pfn __read_mostly;
 int percpu_pagelist_fraction;
 
 #ifdef CONFIG_HUGETLB_PAGE_SIZE_VARIABLE
        unsigned long pfn;
        struct zone *z;
 
+       if (highest_memmap_pfn < end_pfn - 1)
+               highest_memmap_pfn = end_pfn - 1;
+
        z = &NODE_DATA(nid)->node_zones[zone];
        for (pfn = start_pfn; pfn < end_pfn; pfn++) {
                /*