Re: Linux 2.4.1-ac15

Andrea Arcangeli (andrea@suse.de)
Sat, 24 Feb 2001 05:54:08 +0100


This new one should be better. Using the spinlock for the SMP serialization is
ok because that's an extremely slow path.

diff -urN -X /home/andrea/bin/dontdiff 2.4.2/arch/i386/mm/fault.c 2.4.2aa/arch/i386/mm/fault.c
--- 2.4.2/arch/i386/mm/fault.c Thu Feb 22 03:44:53 2001
+++ 2.4.2aa/arch/i386/mm/fault.c Sat Feb 24 05:41:11 2001
@@ -326,23 +326,27 @@
int offset = __pgd_offset(address);
pgd_t *pgd, *pgd_k;
pmd_t *pmd, *pmd_k;
+ static spinlock_t lazy_vmalloc_lock = SPIN_LOCK_UNLOCKED;
+ unsigned long flags;

pgd = tsk->active_mm->pgd + offset;
pgd_k = init_mm.pgd + offset;

- if (!pgd_present(*pgd)) {
- if (!pgd_present(*pgd_k))
- goto bad_area_nosemaphore;
+ spin_lock_irqsave(&lazy_vmalloc_lock, flags);
+ if (!pgd_present(*pgd) && pgd_present(*pgd_k)) {
set_pgd(pgd, *pgd_k);
+ spin_unlock_irqrestore(&lazy_vmalloc_lock, flags);
return;
}
-
pmd = pmd_offset(pgd, address);
pmd_k = pmd_offset(pgd_k, address);

- if (pmd_present(*pmd) || !pmd_present(*pmd_k))
- goto bad_area_nosemaphore;
- set_pmd(pmd, *pmd_k);
- return;
+ if (!pmd_present(*pmd) && pmd_present(*pmd_k)) {
+ set_pmd(pmd, *pmd_k);
+ spin_unlock_irqrestore(&lazy_vmalloc_lock, flags);
+ return;
+ }
+ spin_unlock_irqrestore(&lazy_vmalloc_lock, flags);
+ goto bad_area_nosemaphore;
}
}
diff -urN -X /home/andrea/bin/dontdiff 2.4.2/arch/i386/mm/init.c 2.4.2aa/arch/i386/mm/init.c
--- 2.4.2/arch/i386/mm/init.c Sat Feb 10 02:34:03 2001
+++ 2.4.2aa/arch/i386/mm/init.c Fri Feb 23 19:09:25 2001
@@ -116,21 +116,13 @@
pte_t *pte;

pte = (pte_t *) __get_free_page(GFP_KERNEL);
- if (pmd_none(*pmd)) {
- if (pte) {
- clear_page(pte);
- set_pmd(pmd, __pmd(_KERNPG_TABLE + __pa(pte)));
- return pte + offset;
- }
- set_pmd(pmd, __pmd(_KERNPG_TABLE + __pa(get_bad_pte_table())));
- return NULL;
+ if (pte) {
+ clear_page(pte);
+ set_pmd(pmd, __pmd(_KERNPG_TABLE + __pa(pte)));
+ return pte + offset;
}
- free_page((unsigned long)pte);
- if (pmd_bad(*pmd)) {
- __handle_bad_pmd_kernel(pmd);
- return NULL;
- }
- return (pte_t *) pmd_page(*pmd) + offset;
+ set_pmd(pmd, __pmd(_KERNPG_TABLE + __pa(get_bad_pte_table())));
+ return NULL;
}

pte_t *get_pte_slow(pmd_t *pmd, unsigned long offset)
diff -urN -X /home/andrea/bin/dontdiff 2.4.2/include/asm-i386/pgalloc-3level.h 2.4.2aa/include/asm-i386/pgalloc-3level.h
--- 2.4.2/include/asm-i386/pgalloc-3level.h Fri Dec 3 20:12:23 1999
+++ 2.4.2aa/include/asm-i386/pgalloc-3level.h Fri Feb 23 19:03:14 2001
@@ -53,12 +53,9 @@
if (!page)
page = get_pmd_slow();
if (page) {
- if (pgd_none(*pgd)) {
- set_pgd(pgd, __pgd(1 + __pa(page)));
- __flush_tlb();
- return page + address;
- } else
- free_pmd_fast(page);
+ set_pgd(pgd, __pgd(1 + __pa(page)));
+ __flush_tlb();
+ return page + address;
} else
return NULL;
}

non pae mode is still untested but it should now have a chance to work.

Andrea
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/