diff --git a/arch/parisc/kernel/cache.c b/arch/parisc/kernel/cache.c index bc7c4a4e26a1..7e8d697aef36 100644 --- a/arch/parisc/kernel/cache.c +++ b/arch/parisc/kernel/cache.c @@ -91,7 +91,8 @@ update_mmu_cache(struct vm_area_struct *vma, unsigned long address, pte_t pte) flush_kernel_dcache_page(page); clear_bit(PG_dcache_dirty, &page->flags); - } + } else if (parisc_requires_coherency()) + flush_kernel_dcache_page(page); } void @@ -370,3 +371,45 @@ void parisc_setup_cache_timing(void) printk(KERN_INFO "Setting cache flush threshold to %x (%d CPUs online)\n", parisc_cache_flush_threshold, num_online_cpus()); } + +extern void purge_kernel_dcache_page(unsigned long); +extern void clear_user_page_asm(void *page, unsigned long vaddr); + +void +clear_user_page(void *page, unsigned long vaddr, struct page *pg) +{ + purge_kernel_dcache_page((unsigned long)page); + purge_tlb_start(); + pdtlb_kernel(page); + purge_tlb_end(); + clear_user_page_asm(page, vaddr); +} + +void flush_kernel_dcache_page_addr(void *addr) +{ + flush_kernel_dcache_page_asm(addr); + purge_tlb_start(); + pdtlb_kernel(addr); + purge_tlb_end(); +} +EXPORT_SYMBOL(flush_kernel_dcache_page_addr); + +void copy_user_page(void *vto, void *vfrom, unsigned long vaddr, + struct page *pg) +{ + /* no coherency needed (all in kmap/kunmap) */ + copy_user_page_asm(vto, vfrom); + if (!parisc_requires_coherency()) + flush_kernel_dcache_page_asm(vto); +} +EXPORT_SYMBOL(copy_user_page); + +#ifdef CONFIG_PA8X00 + +void kunmap_parisc(void *addr) +{ + if (parisc_requires_coherency()) + flush_kernel_dcache_page_addr(addr); +} +EXPORT_SYMBOL(kunmap_parisc); +#endif diff --git a/include/asm-parisc/cacheflush.h b/include/asm-parisc/cacheflush.h index 0b459cdfbd6f..2bc41f2e0271 100644 --- a/include/asm-parisc/cacheflush.h +++ b/include/asm-parisc/cacheflush.h @@ -191,16 +191,38 @@ flush_anon_page(struct page *page, unsigned long vmaddr) } #define ARCH_HAS_FLUSH_ANON_PAGE -static inline void -flush_kernel_dcache_page(struct page *page) -{ - flush_kernel_dcache_page_asm(page_address(page)); -} #define ARCH_HAS_FLUSH_KERNEL_DCACHE_PAGE +void flush_kernel_dcache_page_addr(void *addr); +static inline void flush_kernel_dcache_page(struct page *page) +{ + flush_kernel_dcache_page_addr(page_address(page)); +} #ifdef CONFIG_DEBUG_RODATA void mark_rodata_ro(void); #endif +#ifdef CONFIG_PA8X00 +/* Only pa8800, pa8900 needs this */ +#define ARCH_HAS_KMAP + +void kunmap_parisc(void *addr); + +static inline void *kmap(struct page *page) +{ + might_sleep(); + return page_address(page); +} + +#define kunmap(page) kunmap_parisc(page_address(page)) + +#define kmap_atomic(page, idx) page_address(page) + +#define kunmap_atomic(addr, idx) kunmap_parisc(addr) + +#define kmap_atomic_pfn(pfn, idx) page_address(pfn_to_page(pfn)) +#define kmap_atomic_to_page(ptr) virt_to_page(ptr) +#endif + #endif /* _PARISC_CACHEFLUSH_H */ diff --git a/include/asm-parisc/page.h b/include/asm-parisc/page.h index 57d6d82756dd..3567208191e3 100644 --- a/include/asm-parisc/page.h +++ b/include/asm-parisc/page.h @@ -26,24 +26,10 @@ struct page; -extern void purge_kernel_dcache_page(unsigned long); -extern void copy_user_page_asm(void *to, void *from); -extern void clear_user_page_asm(void *page, unsigned long vaddr); - -static inline void -copy_user_page(void *vto, void *vfrom, unsigned long vaddr, struct page *pg) -{ - copy_user_page_asm(vto, vfrom); - flush_kernel_dcache_page_asm(vto); - /* XXX: ppc flushes icache too, should we? */ -} - -static inline void -clear_user_page(void *page, unsigned long vaddr, struct page *pg) -{ - purge_kernel_dcache_page((unsigned long)page); - clear_user_page_asm(page, vaddr); -} +void copy_user_page_asm(void *to, void *from); +void copy_user_page(void *vto, void *vfrom, unsigned long vaddr, + struct page *pg); +void clear_user_page(void *page, unsigned long vaddr, struct page *pg); /* * These are used to make use of C type-checking.. diff --git a/include/asm-parisc/processor.h b/include/asm-parisc/processor.h index c72b8fa49686..4313618c98ee 100644 --- a/include/asm-parisc/processor.h +++ b/include/asm-parisc/processor.h @@ -332,6 +332,19 @@ extern unsigned long get_wchan(struct task_struct *p); #define cpu_relax() barrier() +/* Used as a macro to identify the combined VIPT/PIPT cached + * CPUs which require a guarantee of coherency (no inequivalent + * aliases with different data, whether clean or not) to operate */ +static inline int parisc_requires_coherency(void) +{ +#ifdef CONFIG_PA8X00 + /* FIXME: also pa8900 - when we see one */ + return boot_cpu_data.cpu_type == mako; +#else + return 0; +#endif +} + #endif /* __ASSEMBLY__ */ #endif /* __ASM_PARISC_PROCESSOR_H */