diff options
Diffstat (limited to 'arch/powerpc/mm/fault.c')
-rw-r--r-- | arch/powerpc/mm/fault.c | 30 |
1 files changed, 17 insertions, 13 deletions
diff --git a/arch/powerpc/mm/fault.c b/arch/powerpc/mm/fault.c index ec4adcb4bc28..5aea0909a5ec 100644 --- a/arch/powerpc/mm/fault.c +++ b/arch/powerpc/mm/fault.c | |||
@@ -267,25 +267,29 @@ good_area: | |||
267 | #endif | 267 | #endif |
268 | #if defined(CONFIG_4xx) || defined(CONFIG_BOOKE) | 268 | #if defined(CONFIG_4xx) || defined(CONFIG_BOOKE) |
269 | pte_t *ptep; | 269 | pte_t *ptep; |
270 | pmd_t *pmdp; | ||
270 | 271 | ||
271 | /* Since 4xx/Book-E supports per-page execute permission, | 272 | /* Since 4xx/Book-E supports per-page execute permission, |
272 | * we lazily flush dcache to icache. */ | 273 | * we lazily flush dcache to icache. */ |
273 | ptep = NULL; | 274 | ptep = NULL; |
274 | if (get_pteptr(mm, address, &ptep) && pte_present(*ptep)) { | 275 | if (get_pteptr(mm, address, &ptep, &pmdp)) { |
275 | struct page *page = pte_page(*ptep); | 276 | spinlock_t *ptl = pte_lockptr(mm, pmdp); |
276 | 277 | spin_lock(ptl); | |
277 | if (! test_bit(PG_arch_1, &page->flags)) { | 278 | if (pte_present(*ptep)) { |
278 | flush_dcache_icache_page(page); | 279 | struct page *page = pte_page(*ptep); |
279 | set_bit(PG_arch_1, &page->flags); | 280 | |
281 | if (!test_bit(PG_arch_1, &page->flags)) { | ||
282 | flush_dcache_icache_page(page); | ||
283 | set_bit(PG_arch_1, &page->flags); | ||
284 | } | ||
285 | pte_update(ptep, 0, _PAGE_HWEXEC); | ||
286 | _tlbie(address); | ||
287 | pte_unmap_unlock(ptep, ptl); | ||
288 | up_read(&mm->mmap_sem); | ||
289 | return 0; | ||
280 | } | 290 | } |
281 | pte_update(ptep, 0, _PAGE_HWEXEC); | 291 | pte_unmap_unlock(ptep, ptl); |
282 | _tlbie(address); | ||
283 | pte_unmap(ptep); | ||
284 | up_read(&mm->mmap_sem); | ||
285 | return 0; | ||
286 | } | 292 | } |
287 | if (ptep != NULL) | ||
288 | pte_unmap(ptep); | ||
289 | #endif | 293 | #endif |
290 | /* a write */ | 294 | /* a write */ |
291 | } else if (is_write) { | 295 | } else if (is_write) { |