diff options
Diffstat (limited to 'arch/ppc/mm')
-rw-r--r-- | arch/ppc/mm/fault.c | 30 | ||||
-rw-r--r-- | arch/ppc/mm/pgtable.c | 6 |
2 files changed, 21 insertions, 15 deletions
diff --git a/arch/ppc/mm/fault.c b/arch/ppc/mm/fault.c index 0217188ef465..8e08ca32531a 100644 --- a/arch/ppc/mm/fault.c +++ b/arch/ppc/mm/fault.c | |||
@@ -202,6 +202,7 @@ good_area: | |||
202 | /* an exec - 4xx/Book-E allows for per-page execute permission */ | 202 | /* an exec - 4xx/Book-E allows for per-page execute permission */ |
203 | } else if (TRAP(regs) == 0x400) { | 203 | } else if (TRAP(regs) == 0x400) { |
204 | pte_t *ptep; | 204 | pte_t *ptep; |
205 | pmd_t *pmdp; | ||
205 | 206 | ||
206 | #if 0 | 207 | #if 0 |
207 | /* It would be nice to actually enforce the VM execute | 208 | /* It would be nice to actually enforce the VM execute |
@@ -215,21 +216,24 @@ good_area: | |||
215 | /* Since 4xx/Book-E supports per-page execute permission, | 216 | /* Since 4xx/Book-E supports per-page execute permission, |
216 | * we lazily flush dcache to icache. */ | 217 | * we lazily flush dcache to icache. */ |
217 | ptep = NULL; | 218 | ptep = NULL; |
218 | if (get_pteptr(mm, address, &ptep) && pte_present(*ptep)) { | 219 | if (get_pteptr(mm, address, &ptep, &pmdp)) { |
219 | struct page *page = pte_page(*ptep); | 220 | spinlock_t *ptl = pte_lockptr(mm, pmdp); |
220 | 221 | spin_lock(ptl); | |
221 | if (! test_bit(PG_arch_1, &page->flags)) { | 222 | if (pte_present(*ptep)) { |
222 | flush_dcache_icache_page(page); | 223 | struct page *page = pte_page(*ptep); |
223 | set_bit(PG_arch_1, &page->flags); | 224 | |
225 | if (!test_bit(PG_arch_1, &page->flags)) { | ||
226 | flush_dcache_icache_page(page); | ||
227 | set_bit(PG_arch_1, &page->flags); | ||
228 | } | ||
229 | pte_update(ptep, 0, _PAGE_HWEXEC); | ||
230 | _tlbie(address); | ||
231 | pte_unmap_unlock(ptep, ptl); | ||
232 | up_read(&mm->mmap_sem); | ||
233 | return 0; | ||
224 | } | 234 | } |
225 | pte_update(ptep, 0, _PAGE_HWEXEC); | 235 | pte_unmap_unlock(ptep, ptl); |
226 | _tlbie(address); | ||
227 | pte_unmap(ptep); | ||
228 | up_read(&mm->mmap_sem); | ||
229 | return 0; | ||
230 | } | 236 | } |
231 | if (ptep != NULL) | ||
232 | pte_unmap(ptep); | ||
233 | #endif | 237 | #endif |
234 | /* a read */ | 238 | /* a read */ |
235 | } else { | 239 | } else { |
diff --git a/arch/ppc/mm/pgtable.c b/arch/ppc/mm/pgtable.c index a1924876cad6..706bca8eb144 100644 --- a/arch/ppc/mm/pgtable.c +++ b/arch/ppc/mm/pgtable.c | |||
@@ -368,7 +368,7 @@ void __init io_block_mapping(unsigned long virt, phys_addr_t phys, | |||
368 | * the PTE pointer is unmodified if PTE is not found. | 368 | * the PTE pointer is unmodified if PTE is not found. |
369 | */ | 369 | */ |
370 | int | 370 | int |
371 | get_pteptr(struct mm_struct *mm, unsigned long addr, pte_t **ptep) | 371 | get_pteptr(struct mm_struct *mm, unsigned long addr, pte_t **ptep, pmd_t **pmdp) |
372 | { | 372 | { |
373 | pgd_t *pgd; | 373 | pgd_t *pgd; |
374 | pmd_t *pmd; | 374 | pmd_t *pmd; |
@@ -383,6 +383,8 @@ get_pteptr(struct mm_struct *mm, unsigned long addr, pte_t **ptep) | |||
383 | if (pte) { | 383 | if (pte) { |
384 | retval = 1; | 384 | retval = 1; |
385 | *ptep = pte; | 385 | *ptep = pte; |
386 | if (pmdp) | ||
387 | *pmdp = pmd; | ||
386 | /* XXX caller needs to do pte_unmap, yuck */ | 388 | /* XXX caller needs to do pte_unmap, yuck */ |
387 | } | 389 | } |
388 | } | 390 | } |
@@ -420,7 +422,7 @@ unsigned long iopa(unsigned long addr) | |||
420 | mm = &init_mm; | 422 | mm = &init_mm; |
421 | 423 | ||
422 | pa = 0; | 424 | pa = 0; |
423 | if (get_pteptr(mm, addr, &pte)) { | 425 | if (get_pteptr(mm, addr, &pte, NULL)) { |
424 | pa = (pte_val(*pte) & PAGE_MASK) | (addr & ~PAGE_MASK); | 426 | pa = (pte_val(*pte) & PAGE_MASK) | (addr & ~PAGE_MASK); |
425 | pte_unmap(pte); | 427 | pte_unmap(pte); |
426 | } | 428 | } |