diff options
| author | Anton Blanchard <anton@samba.org> | 2003-01-14 16:19:13 +1100 |
|---|---|---|
| committer | Anton Blanchard <anton@samba.org> | 2003-01-14 16:19:13 +1100 |
| commit | 45d3cf3ef7ef0e681942018513358b1fe74a27e9 (patch) | |
| tree | 903b3a85988d399c471e5da4b87190db28355e2f | |
| parent | bcd998aad6496759d239eaba760a6ca6d1a73e2c (diff) | |
| parent | 75b368dc7acc3a5ce664d57c3da4b531af3c6563 (diff) | |
Merge samba.org:/scratch/anton/linux-2.5
into samba.org:/scratch/anton/sfr
| -rw-r--r-- | arch/ppc64/mm/init.c | 64 | ||||
| -rw-r--r-- | include/asm-ppc64/cacheflush.h | 2 |
2 files changed, 35 insertions, 31 deletions
diff --git a/arch/ppc64/mm/init.c b/arch/ppc64/mm/init.c index 988b1f9f55dc..7c2bf5117d64 100644 --- a/arch/ppc64/mm/init.c +++ b/arch/ppc64/mm/init.c @@ -592,36 +592,24 @@ void __init mem_init(void) */ void flush_dcache_page(struct page *page) { + /* avoid an atomic op if possible */ if (test_bit(PG_arch_1, &page->flags)) clear_bit(PG_arch_1, &page->flags); } -void flush_icache_page(struct vm_area_struct *vma, struct page *page) -{ - if (cpu_has_noexecute()) - return; - - if ((vma->vm_flags & VM_EXEC) == 0) - return; - - if (page->mapping && !PageReserved(page) - && !test_bit(PG_arch_1, &page->flags)) { - __flush_dcache_icache(page_address(page)); - set_bit(PG_arch_1, &page->flags); - } -} - void clear_user_page(void *page, unsigned long vaddr, struct page *pg) { clear_page(page); - /* XXX we shouldnt have to do this, but glibc requires it */ - if (cpu_has_noexecute()) { - if (test_bit(PG_arch_1, &pg->flags)) - clear_bit(PG_arch_1, &pg->flags); - } else { - __flush_dcache_icache(page); - } + /* + * We shouldnt have to do this, but some versions of glibc + * require it (ld.so assumes zero filled pages are icache clean) + * - Anton + */ + + /* avoid an atomic op if possible */ + if (test_bit(PG_arch_1, &pg->flags)) + clear_bit(PG_arch_1, &pg->flags); } void copy_user_page(void *vto, void *vfrom, unsigned long vaddr, @@ -630,20 +618,23 @@ void copy_user_page(void *vto, void *vfrom, unsigned long vaddr, copy_page(vto, vfrom); /* - * Unfortunately we havent always marked our GOT and PLT sections - * as executable, so we need to flush all file regions - Anton + * We should be able to use the following optimisation, however + * there are two problems. + * Firstly a bug in some versions of binutils meant PLT sections + * were not marked executable. + * Secondly the first word in the GOT section is blrl, used + * to establish the GOT address. Until recently the GOT was + * not marked executable. + * - Anton */ #if 0 if (!vma->vm_file && ((vma->vm_flags & VM_EXEC) == 0)) return; #endif - if (cpu_has_noexecute()) { - if (test_bit(PG_arch_1, &pg->flags)) - clear_bit(PG_arch_1, &pg->flags); - } else { - __flush_dcache_icache(vto); - } + /* avoid an atomic op if possible */ + if (test_bit(PG_arch_1, &pg->flags)) + clear_bit(PG_arch_1, &pg->flags); } void flush_icache_user_range(struct vm_area_struct *vma, struct page *page, @@ -675,6 +666,19 @@ void update_mmu_cache(struct vm_area_struct *vma, unsigned long ea, pte_t *ptep; int local = 0; + /* handle i-cache coherency */ + if (!cpu_has_noexecute()) { + unsigned long pfn = pte_pfn(pte); + if (pfn_valid(pfn)) { + struct page *page = pfn_to_page(pfn); + if (!PageReserved(page) + && !test_bit(PG_arch_1, &page->flags)) { + __flush_dcache_icache(page_address(page)); + set_bit(PG_arch_1, &page->flags); + } + } + } + /* We only want HPTEs for linux PTEs that have _PAGE_ACCESSED set */ if (!pte_young(pte)) return; diff --git a/include/asm-ppc64/cacheflush.h b/include/asm-ppc64/cacheflush.h index 75d939cd219c..9a54101c4546 100644 --- a/include/asm-ppc64/cacheflush.h +++ b/include/asm-ppc64/cacheflush.h @@ -14,10 +14,10 @@ #define flush_cache_range(vma, start, end) do { } while (0) #define flush_cache_page(vma, vmaddr) do { } while (0) #define flush_page_to_ram(page) do { } while (0) +#define flush_icache_page(vma, page) do { } while (0) extern void flush_dcache_page(struct page *page); extern void flush_icache_range(unsigned long, unsigned long); -extern void flush_icache_page(struct vm_area_struct *vma, struct page *page); extern void flush_icache_user_range(struct vm_area_struct *vma, struct page *page, unsigned long addr, int len); |
