Index: linux-2.6.13-rc4-mm1/arch/i386/mm/pgtable.c =================================================================== --- linux-2.6.13-rc4-mm1.orig/arch/i386/mm/pgtable.c 2005-08-04 05:42:32.000000000 -0700 +++ linux-2.6.13-rc4-mm1/arch/i386/mm/pgtable.c 2005-08-05 13:04:14.000000000 -0700 @@ -214,8 +214,16 @@ clone_pgd_range((pgd_t *)pgd + USER_PTRS_PER_PGD, swapper_pg_dir + USER_PTRS_PER_PGD, PTRS_PER_PGD - USER_PTRS_PER_PGD); - if (PTRS_PER_PMD > 1) + if (PTRS_PER_PMD > 1) { + int i; + for (i = 0; i < USER_PTRS_PER_PGD; ++i) { + pmd_t *pmd = kmem_cache_alloc(pmd_cache, GFP_KERNEL); + if (!pmd) + panic("oom"); + set_pgd(&((pgd_t *)pgd)[i], __pgd(1 + __pa(pmd))); + } return; + } pgd_list_add(pgd); spin_unlock_irqrestore(&pgd_lock, flags); @@ -226,6 +234,14 @@ { unsigned long flags; /* can be called from interrupt context */ + /* in the PAE case user pgd entries are overwritten before usage */ + if (PTRS_PER_PMD > 1) { + int i; + for (i = 0; i < USER_PTRS_PER_PGD; ++i) + kmem_cache_free(pmd_cache, (void *)__va(pgd_val(((pgd_t *)pgd)[i])-1)); + return; + } + spin_lock_irqsave(&pgd_lock, flags); pgd_list_del(pgd); spin_unlock_irqrestore(&pgd_lock, flags); @@ -233,35 +249,12 @@ pgd_t *pgd_alloc(struct mm_struct *mm) { - int i; pgd_t *pgd = kmem_cache_alloc(pgd_cache, GFP_KERNEL); - - if (PTRS_PER_PMD == 1 || !pgd) - return pgd; - - for (i = 0; i < USER_PTRS_PER_PGD; ++i) { - pmd_t *pmd = kmem_cache_alloc(pmd_cache, GFP_KERNEL); - if (!pmd) - goto out_oom; - set_pgd(&pgd[i], __pgd(1 + __pa(pmd))); - } return pgd; -out_oom: - for (i--; i >= 0; i--) - kmem_cache_free(pmd_cache, (void *)__va(pgd_val(pgd[i])-1)); - kmem_cache_free(pgd_cache, pgd); - return NULL; } void pgd_free(pgd_t *pgd) { - int i; - - /* in the PAE case user pgd entries are overwritten before usage */ - if (PTRS_PER_PMD > 1) - for (i = 0; i < USER_PTRS_PER_PGD; ++i) - kmem_cache_free(pmd_cache, (void *)__va(pgd_val(pgd[i])-1)); - /* in the non-PAE case, free_pgtables() clears user pgd entries */ kmem_cache_free(pgd_cache, pgd); } Index: linux-2.6.13-rc4-mm1/arch/i386/mm/init.c =================================================================== --- linux-2.6.13-rc4-mm1.orig/arch/i386/mm/init.c 2005-08-04 04:01:27.000000000 -0700 +++ linux-2.6.13-rc4-mm1/arch/i386/mm/init.c 2005-08-05 13:02:34.000000000 -0700 @@ -635,7 +635,7 @@ PTRS_PER_PGD*sizeof(pgd_t), 0, pgd_ctor, - PTRS_PER_PMD == 1 ? pgd_dtor : NULL); + pgd_dtor); if (!pgd_cache) panic("pgtable_cache_init(): Cannot create pgd cache"); }