]> git.neil.brown.name Git - history.git/commitdiff
ppc32: fix a possible race in pte_free()
authorBenjamin Herrenschmidt <benh@kernel.crashing.org>
Fri, 6 Feb 2004 02:58:23 +0000 (13:58 +1100)
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>
Fri, 6 Feb 2004 02:58:23 +0000 (13:58 +1100)
Another processor could be walking the page table in the middle of the
PTE page to be freeded. Synchronize with hash_page using the lock.

arch/ppc/mm/hashtable.S
arch/ppc/mm/pgtable.c

index e7732c4331ea9417057da29b246d87b63d7b680a..992c244010a15a93efc85dde6ef6c388e7237da7 100644 (file)
        .comm   mmu_hash_lock,4
 #endif /* CONFIG_SMP */
 
+/*
+ * Sync CPUs with hash_page taking & releasing the hash
+ * table lock
+ */
+#ifdef CONFIG_SMP
+       .text
+_GLOBAL(hash_page_sync)
+       lis     r8,mmu_hash_lock@h
+       ori     r8,r8,mmu_hash_lock@l
+       lis     r0,0x0fff
+       b       10f
+11:    lwz     r6,0(r8)
+       cmpwi   0,r6,0
+       bne     11b
+10:    lwarx   r6,0,r8
+       cmpwi   0,r6,0
+       bne-    11b
+       stwcx.  r0,0,r8
+       bne-    10b
+       isync
+       eieio
+       li      r0,0
+       stw     r0,0(r8)
+       blr     
+#endif
+
 /*
  * Load a PTE into the hash table, if possible.
  * The address is in r4, and r3 contains an access flag:
index c83b484d07872e49a01a40b2a17e228434c1f32d..b62b30ca4f78c84609efdef5b04f68c8a240598d 100644 (file)
@@ -44,6 +44,10 @@ int io_bat_index;
 
 extern char etext[], _stext[];
 
+#ifdef CONFIG_SMP
+extern void hash_page_sync(void);
+#endif
+
 #ifdef HAVE_BATS
 extern unsigned long v_mapped_by_bats(unsigned long va);
 extern unsigned long p_mapped_by_bats(unsigned long pa);
@@ -109,11 +113,17 @@ struct page *pte_alloc_one(struct mm_struct *mm, unsigned long address)
 
 void pte_free_kernel(pte_t *pte)
 {
+#ifdef CONFIG_SMP
+       hash_page_sync();
+#endif
        free_page((unsigned long)pte);
 }
 
 void pte_free(struct page *pte)
 {
+#ifdef CONFIG_SMP
+       hash_page_sync();
+#endif
        __free_page(pte);
 }