diff options
author | Eugene Surovegin <ebs@ebshome.net> | 2006-03-28 13:13:12 -0500 |
---|---|---|
committer | Paul Mackerras <paulus@samba.org> | 2006-03-28 21:44:15 -0500 |
commit | bab70a4af737f623de5b034976a311055308ab86 (patch) | |
tree | f8c0e9463de01323db2cb1a62f4eb83adb5ce7ca /arch/powerpc/mm/pgtable_32.c | |
parent | bac30d1a78d0f11c613968fc8b351a91ed465386 (diff) |
[PATCH] lock PTE before updating it in 440/BookE page fault handler
Fix 44x and BookE page fault handler to correctly lock PTE before
trying to pte_update() it, otherwise this PTE might be swapped out
after pte_present() check but before pte_uptdate() call, resulting in
corrupted PTE. This can happen with enabled preemption and low memory
condition.
Signed-off-by: Eugene Surovegin <ebs@ebshome.net>
Signed-off-by: Paul Mackerras <paulus@samba.org>
Diffstat (limited to 'arch/powerpc/mm/pgtable_32.c')
-rw-r--r-- | arch/powerpc/mm/pgtable_32.c | 6 |
1 files changed, 4 insertions, 2 deletions
diff --git a/arch/powerpc/mm/pgtable_32.c b/arch/powerpc/mm/pgtable_32.c index d296eb6b4545..90628601fac7 100644 --- a/arch/powerpc/mm/pgtable_32.c +++ b/arch/powerpc/mm/pgtable_32.c | |||
@@ -372,7 +372,7 @@ void __init io_block_mapping(unsigned long virt, phys_addr_t phys, | |||
372 | * the PTE pointer is unmodified if PTE is not found. | 372 | * the PTE pointer is unmodified if PTE is not found. |
373 | */ | 373 | */ |
374 | int | 374 | int |
375 | get_pteptr(struct mm_struct *mm, unsigned long addr, pte_t **ptep) | 375 | get_pteptr(struct mm_struct *mm, unsigned long addr, pte_t **ptep, pmd_t **pmdp) |
376 | { | 376 | { |
377 | pgd_t *pgd; | 377 | pgd_t *pgd; |
378 | pmd_t *pmd; | 378 | pmd_t *pmd; |
@@ -387,6 +387,8 @@ get_pteptr(struct mm_struct *mm, unsigned long addr, pte_t **ptep) | |||
387 | if (pte) { | 387 | if (pte) { |
388 | retval = 1; | 388 | retval = 1; |
389 | *ptep = pte; | 389 | *ptep = pte; |
390 | if (pmdp) | ||
391 | *pmdp = pmd; | ||
390 | /* XXX caller needs to do pte_unmap, yuck */ | 392 | /* XXX caller needs to do pte_unmap, yuck */ |
391 | } | 393 | } |
392 | } | 394 | } |
@@ -424,7 +426,7 @@ unsigned long iopa(unsigned long addr) | |||
424 | mm = &init_mm; | 426 | mm = &init_mm; |
425 | 427 | ||
426 | pa = 0; | 428 | pa = 0; |
427 | if (get_pteptr(mm, addr, &pte)) { | 429 | if (get_pteptr(mm, addr, &pte, NULL)) { |
428 | pa = (pte_val(*pte) & PAGE_MASK) | (addr & ~PAGE_MASK); | 430 | pa = (pte_val(*pte) & PAGE_MASK) | (addr & ~PAGE_MASK); |
429 | pte_unmap(pte); | 431 | pte_unmap(pte); |
430 | } | 432 | } |