#endif
#if defined(CONFIG_4xx) || defined(CONFIG_BOOKE)
pte_t *ptep;
+ pmd_t *pmdp;
/* Since 4xx/Book-E supports per-page execute permission,
* we lazily flush dcache to icache. */
ptep = NULL;
- if (get_pteptr(mm, address, &ptep) && pte_present(*ptep)) {
- struct page *page = pte_page(*ptep);
-
- if (! test_bit(PG_arch_1, &page->flags)) {
- flush_dcache_icache_page(page);
- set_bit(PG_arch_1, &page->flags);
+ if (get_pteptr(mm, address, &ptep, &pmdp)) {
+ spinlock_t *ptl = pte_lockptr(mm, pmdp);
+ spin_lock(ptl);
+ if (pte_present(*ptep)) {
+ struct page *page = pte_page(*ptep);
+
+ if (!test_bit(PG_arch_1, &page->flags)) {
+ flush_dcache_icache_page(page);
+ set_bit(PG_arch_1, &page->flags);
+ }
+ pte_update(ptep, 0, _PAGE_HWEXEC);
+ _tlbie(address);
+ pte_unmap_unlock(ptep, ptl);
+ up_read(&mm->mmap_sem);
+ return 0;
}
- pte_update(ptep, 0, _PAGE_HWEXEC);
- _tlbie(address);
- pte_unmap(ptep);
- up_read(&mm->mmap_sem);
- return 0;
+ pte_unmap_unlock(ptep, ptl);
}
- if (ptep != NULL)
- pte_unmap(ptep);
#endif
/* a write */
} else if (is_write) {
* the PTE pointer is unmodified if PTE is not found.
*/
int
-get_pteptr(struct mm_struct *mm, unsigned long addr, pte_t **ptep)
+get_pteptr(struct mm_struct *mm, unsigned long addr, pte_t **ptep, pmd_t **pmdp)
{
pgd_t *pgd;
pmd_t *pmd;
if (pte) {
retval = 1;
*ptep = pte;
+ if (pmdp)
+ *pmdp = pmd;
/* XXX caller needs to do pte_unmap, yuck */
}
}
mm = &init_mm;
pa = 0;
- if (get_pteptr(mm, addr, &pte)) {
+ if (get_pteptr(mm, addr, &pte, NULL)) {
pa = (pte_val(*pte) & PAGE_MASK) | (addr & ~PAGE_MASK);
pte_unmap(pte);
}
/* an exec - 4xx/Book-E allows for per-page execute permission */
} else if (TRAP(regs) == 0x400) {
pte_t *ptep;
+ pmd_t *pmdp;
#if 0
/* It would be nice to actually enforce the VM execute
/* Since 4xx/Book-E supports per-page execute permission,
* we lazily flush dcache to icache. */
ptep = NULL;
- if (get_pteptr(mm, address, &ptep) && pte_present(*ptep)) {
- struct page *page = pte_page(*ptep);
-
- if (! test_bit(PG_arch_1, &page->flags)) {
- flush_dcache_icache_page(page);
- set_bit(PG_arch_1, &page->flags);
+ if (get_pteptr(mm, address, &ptep, &pmdp)) {
+ spinlock_t *ptl = pte_lockptr(mm, pmdp);
+ spin_lock(ptl);
+ if (pte_present(*ptep)) {
+ struct page *page = pte_page(*ptep);
+
+ if (!test_bit(PG_arch_1, &page->flags)) {
+ flush_dcache_icache_page(page);
+ set_bit(PG_arch_1, &page->flags);
+ }
+ pte_update(ptep, 0, _PAGE_HWEXEC);
+ _tlbie(address);
+ pte_unmap_unlock(ptep, ptl);
+ up_read(&mm->mmap_sem);
+ return 0;
}
- pte_update(ptep, 0, _PAGE_HWEXEC);
- _tlbie(address);
- pte_unmap(ptep);
- up_read(&mm->mmap_sem);
- return 0;
+ pte_unmap_unlock(ptep, ptl);
}
- if (ptep != NULL)
- pte_unmap(ptep);
#endif
/* a read */
} else {
* the PTE pointer is unmodified if PTE is not found.
*/
int
-get_pteptr(struct mm_struct *mm, unsigned long addr, pte_t **ptep)
+get_pteptr(struct mm_struct *mm, unsigned long addr, pte_t **ptep, pmd_t **pmdp)
{
pgd_t *pgd;
pmd_t *pmd;
if (pte) {
retval = 1;
*ptep = pte;
+ if (pmdp)
+ *pmdp = pmd;
/* XXX caller needs to do pte_unmap, yuck */
}
}
mm = &init_mm;
pa = 0;
- if (get_pteptr(mm, addr, &pte)) {
+ if (get_pteptr(mm, addr, &pte, NULL)) {
pa = (pte_val(*pte) & PAGE_MASK) | (addr & ~PAGE_MASK);
pte_unmap(pte);
}
*/
#define pgtable_cache_init() do { } while (0)
-extern int get_pteptr(struct mm_struct *mm, unsigned long addr, pte_t **ptep);
+extern int get_pteptr(struct mm_struct *mm, unsigned long addr, pte_t **ptep,
+ pmd_t **pmdp);
#include <asm-generic/pgtable.h>