Ok, the use of "1 + " and subtraction of one for PAE PDPEs has confused many people now. Make it explicit what is going on and why anding with PAGE_MASK is a better idea to strip these bits. Signed-off-by: Zachary Amsden <zach@xxxxxxxxxx> Depends-on: add-pgtable-allocation-notifiers Index: linux-2.6.13/arch/i386/mm/pgtable.c =================================================================== --- linux-2.6.13.orig/arch/i386/mm/pgtable.c 2005-08-31 14:48:17.000000000 -0700 +++ linux-2.6.13/arch/i386/mm/pgtable.c 2005-08-31 14:48:53.000000000 -0700 @@ -247,14 +247,14 @@ pgd_t *pgd_alloc(struct mm_struct *mm) if (!pmd) goto out_oom; SetPagePDE(virt_to_page(pmd)); - set_pgd(&pgd[i], __pgd(1 + __pa(pmd))); + set_pgd(&pgd[i], __pgd(_PAGE_PRESENT | __pa(pmd))); } return pgd; out_oom: for (i--; i >= 0; i--) { ClearPagePDE(pfn_to_page(pgd_val(pgd[i]) >> PAGE_SHIFT)); - kmem_cache_free(pmd_cache, (void *)__va(pgd_val(pgd[i])-1)); + kmem_cache_free(pmd_cache, (void *)__va(pgd_val(pgd[i]) & PAGE_MASK)); } kmem_cache_free(pgd_cache, pgd); return NULL; @@ -268,7 +268,7 @@ void pgd_free(pgd_t *pgd) if (PTRS_PER_PMD > 1) for (i = 0; i < USER_PTRS_PER_PGD; ++i) { ClearPagePDE(pfn_to_page(pgd_val(pgd[i]) >> PAGE_SHIFT)); - kmem_cache_free(pmd_cache, (void *)__va(pgd_val(pgd[i])-1)); + kmem_cache_free(pmd_cache, (void *)__va(pgd_val(pgd[i]) & PAGE_MASK)); } /* in the non-PAE case, free_pgtables() clears user pgd entries */ kmem_cache_free(pgd_cache, pgd); Index: linux-2.6.13/arch/i386/mm/init.c =================================================================== --- linux-2.6.13.orig/arch/i386/mm/init.c 2005-08-31 14:48:17.000000000 -0700 +++ linux-2.6.13/arch/i386/mm/init.c 2005-08-31 14:48:53.000000000 -0700 @@ -387,7 +387,7 @@ void zap_low_mappings (void) */ for (i = 0; i < USER_PTRS_PER_PGD; i++) #ifdef CONFIG_X86_PAE - set_pgd(swapper_pg_dir+i, __pgd(1 + __pa(empty_zero_page))); + set_pgd(swapper_pg_dir+i, __pgd(_PAGE_PRESENT | __pa(empty_zero_page))); #else set_pgd(swapper_pg_dir+i, __pgd(0)); #endif