--- linux-2.4.22_linuxppc_2_4/arch/ppc/mm/fault.c 2003-08-29 11:13:00.000000000 +0200 +++ linux-2.4.22_linuxppc_2_4_insightv2p/arch/ppc/mm/fault.c 2003-08-29 16:35:26.000000000 +0200 @@ -26,6 +26,7 @@ #include #include #include +#include #include #include @@ -51,6 +52,7 @@ unsigned int probingmem; extern void die_if_kernel(char *, struct pt_regs *, long); void bad_page_fault(struct pt_regs *, unsigned long, int sig); void do_page_fault(struct pt_regs *, unsigned long, unsigned long); +extern int get_pteptr(struct mm_struct *mm, unsigned long addr, pte_t **ptep); /* * Check whether the instruction at regs->nip is a store using @@ -202,6 +204,28 @@ good_area: if (is_write) { if (!(vma->vm_flags & VM_WRITE)) goto bad_area; +#if defined(CONFIG_4xx) + /* an exec - 4xx/BookE allows for per-page execute permission */ + } else if (regs->trap == 0x400) { + pte_t *ptep; + + + /* Since 4xx supports per-page execute permission, + * we lazily flush dcache to icache. */ + 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(kmap(page)); + kunmap(page); + set_bit(PG_arch_1, &page->flags); + } + pte_update(ptep, 0, _PAGE_HWEXEC); + _tlbie(address); + up_read(&mm->mmap_sem); + return; + } +#endif /* a read */ } else { /* protection fault */