![[LWN Logo]](/images/lcorner.png) |
|
![[LWN.net]](/images/Included.png) |
===== kernel/fork.c 1.5 vs edited =====
--- 1.5/kernel/fork.c Sat Feb 10 20:54:34 2001
+++ edited/kernel/fork.c Thu Mar 8 13:50:44 2001
@@ -203,7 +203,9 @@
atomic_set(&mm->mm_count, 1);
init_MUTEX(&mm->mmap_sem);
mm->page_table_lock = SPIN_LOCK_UNLOCKED;
+ lock_kernel();
mm->pgd = pgd_alloc();
+ unlock_kernel();
if (mm->pgd)
return mm;
free_mm(mm);
@@ -234,7 +236,9 @@
inline void __mmdrop(struct mm_struct *mm)
{
if (mm == &init_mm) BUG();
+ lock_kernel();
pgd_free(mm->pgd);
+ unlock_kernel();
destroy_context(mm);
free_mm(mm);
}
===== mm/vmalloc.c 1.3 vs edited =====
--- 1.3/mm/vmalloc.c Sat Feb 10 20:54:34 2001
+++ edited/mm/vmalloc.c Thu Mar 8 12:55:42 2001
@@ -146,6 +146,7 @@
lock_kernel();
do {
pmd_t *pmd;
+ pgd_t olddir = *dir;
pmd = pmd_alloc_kernel(dir, address);
ret = -ENOMEM;
@@ -155,6 +156,8 @@
ret = -ENOMEM;
if (alloc_area_pmd(pmd, address, end - address, gfp_mask, prot))
break;
+ if (pgd_val(olddir) != pgd_val(*dir))
+ set_pgdir(address, *dir);
address = (address + PGDIR_SIZE) & PGDIR_MASK;
dir++;
===== include/asm-i386/pgalloc.h 1.1 vs edited =====
--- 1.1/include/asm-i386/pgalloc.h Sat Jan 6 10:26:31 2001
+++ edited/include/asm-i386/pgalloc.h Thu Mar 8 12:50:47 2001
@@ -152,6 +152,33 @@
extern int do_check_pgt_cache(int, int);
+extern inline void set_pgdir(unsigned long address, pgd_t entry)
+{
+ struct task_struct * p;
+ pgd_t *pgd;
+#ifdef CONFIG_SMP
+ int i;
+#endif
+
+ read_lock(&tasklist_lock);
+ for_each_task(p) {
+ if (!p->mm)
+ continue;
+ *pgd_offset(p->mm,address) = entry;
+ }
+ read_unlock(&tasklist_lock);
+#ifndef CONFIG_SMP
+ for (pgd = (pgd_t *)pgd_quicklist; pgd; pgd = (pgd_t *)*(unsigned long *)pgd)
+ pgd[address >> PGDIR_SHIFT] = entry;
+#else
+ /* To pgd_alloc/pgd_free, one holds master kernel lock and so does our callee, so we can
+ modify pgd caches of other CPUs as well. -jj */
+ for (i = 0; i < NR_CPUS; i++)
+ for (pgd = (pgd_t *)cpu_data[i].pgd_quick; pgd; pgd = (pgd_t *)*(unsigned long *)pgd)
+ pgd[address >> PGDIR_SHIFT] = entry;
+#endif
+}
+
/*
* TLB flushing:
*
===== arch/i386/mm/ioremap.c 1.1 vs edited =====
--- 1.1/arch/i386/mm/ioremap.c Sat Jan 6 10:29:43 2001
+++ edited/arch/i386/mm/ioremap.c Thu Mar 8 12:50:47 2001
@@ -78,6 +78,7 @@
if (remap_area_pmd(pmd, address, end - address,
phys_addr + address, flags))
return -ENOMEM;
+ set_pgdir(address, *dir);
address = (address + PGDIR_SIZE) & PGDIR_MASK;
dir++;
} while (address && (address < end));