aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJames Bottomley <jejb@parisc-linux.org>2006-08-23 12:00:04 -0400
committerMatthew Wilcox <willy@parisc-linux.org>2006-10-04 08:46:21 -0400
commit20f4d3cb9b94ce3fec9a6135b9ad075b82b24f41 (patch)
tree995dec90d251e8e57abca8fea552d8ae5314a493
parente45da35e180a4fc91307648d021a598495742c32 (diff)
[PARISC] parisc specific kmap API implementation for pa8800
This patch fixes the pa8800 at a gross level (there are still other subtle incoherency issues which can still cause crashes and HPMCs). What it does is try to force eject inequivalent aliases before they become visible to the L2 cache (which is where we get the incoherence problems). A new function (parisc_requires_coherency) is introduced in asm/processor.h to identify the pa8x00 processors (8800 and 8900) which have the issue. Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com> Signed-off-by: Kyle McMartin <kyle@parisc-linux.org>
-rw-r--r--arch/parisc/kernel/cache.c45
-rw-r--r--include/asm-parisc/cacheflush.h30
-rw-r--r--include/asm-parisc/page.h22
-rw-r--r--include/asm-parisc/processor.h13
4 files changed, 87 insertions, 23 deletions
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)
91 91
92 flush_kernel_dcache_page(page); 92 flush_kernel_dcache_page(page);
93 clear_bit(PG_dcache_dirty, &page->flags); 93 clear_bit(PG_dcache_dirty, &page->flags);
94 } 94 } else if (parisc_requires_coherency())
95 flush_kernel_dcache_page(page);
95} 96}
96 97
97void 98void
@@ -370,3 +371,45 @@ void parisc_setup_cache_timing(void)
370 371
371 printk(KERN_INFO "Setting cache flush threshold to %x (%d CPUs online)\n", parisc_cache_flush_threshold, num_online_cpus()); 372 printk(KERN_INFO "Setting cache flush threshold to %x (%d CPUs online)\n", parisc_cache_flush_threshold, num_online_cpus());
372} 373}
374
375extern void purge_kernel_dcache_page(unsigned long);
376extern void clear_user_page_asm(void *page, unsigned long vaddr);
377
378void
379clear_user_page(void *page, unsigned long vaddr, struct page *pg)
380{
381 purge_kernel_dcache_page((unsigned long)page);
382 purge_tlb_start();
383 pdtlb_kernel(page);
384 purge_tlb_end();
385 clear_user_page_asm(page, vaddr);
386}
387
388void flush_kernel_dcache_page_addr(void *addr)
389{
390 flush_kernel_dcache_page_asm(addr);
391 purge_tlb_start();
392 pdtlb_kernel(addr);
393 purge_tlb_end();
394}
395EXPORT_SYMBOL(flush_kernel_dcache_page_addr);
396
397void copy_user_page(void *vto, void *vfrom, unsigned long vaddr,
398 struct page *pg)
399{
400 /* no coherency needed (all in kmap/kunmap) */
401 copy_user_page_asm(vto, vfrom);
402 if (!parisc_requires_coherency())
403 flush_kernel_dcache_page_asm(vto);
404}
405EXPORT_SYMBOL(copy_user_page);
406
407#ifdef CONFIG_PA8X00
408
409void kunmap_parisc(void *addr)
410{
411 if (parisc_requires_coherency())
412 flush_kernel_dcache_page_addr(addr);
413}
414EXPORT_SYMBOL(kunmap_parisc);
415#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)
191} 191}
192#define ARCH_HAS_FLUSH_ANON_PAGE 192#define ARCH_HAS_FLUSH_ANON_PAGE
193 193
194static inline void 194#define ARCH_HAS_FLUSH_KERNEL_DCACHE_PAGE
195flush_kernel_dcache_page(struct page *page) 195void flush_kernel_dcache_page_addr(void *addr);
196static inline void flush_kernel_dcache_page(struct page *page)
196{ 197{
197 flush_kernel_dcache_page_asm(page_address(page)); 198 flush_kernel_dcache_page_addr(page_address(page));
198} 199}
199#define ARCH_HAS_FLUSH_KERNEL_DCACHE_PAGE
200 200
201#ifdef CONFIG_DEBUG_RODATA 201#ifdef CONFIG_DEBUG_RODATA
202void mark_rodata_ro(void); 202void mark_rodata_ro(void);
203#endif 203#endif
204 204
205#ifdef CONFIG_PA8X00
206/* Only pa8800, pa8900 needs this */
207#define ARCH_HAS_KMAP
208
209void kunmap_parisc(void *addr);
210
211static inline void *kmap(struct page *page)
212{
213 might_sleep();
214 return page_address(page);
215}
216
217#define kunmap(page) kunmap_parisc(page_address(page))
218
219#define kmap_atomic(page, idx) page_address(page)
220
221#define kunmap_atomic(addr, idx) kunmap_parisc(addr)
222
223#define kmap_atomic_pfn(pfn, idx) page_address(pfn_to_page(pfn))
224#define kmap_atomic_to_page(ptr) virt_to_page(ptr)
225#endif
226
205#endif /* _PARISC_CACHEFLUSH_H */ 227#endif /* _PARISC_CACHEFLUSH_H */
206 228
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 @@
26 26
27struct page; 27struct page;
28 28
29extern void purge_kernel_dcache_page(unsigned long); 29void copy_user_page_asm(void *to, void *from);
30extern void copy_user_page_asm(void *to, void *from); 30void copy_user_page(void *vto, void *vfrom, unsigned long vaddr,
31extern void clear_user_page_asm(void *page, unsigned long vaddr); 31 struct page *pg);
32 32void clear_user_page(void *page, unsigned long vaddr, struct page *pg);
33static inline void
34copy_user_page(void *vto, void *vfrom, unsigned long vaddr, struct page *pg)
35{
36 copy_user_page_asm(vto, vfrom);
37 flush_kernel_dcache_page_asm(vto);
38 /* XXX: ppc flushes icache too, should we? */
39}
40
41static inline void
42clear_user_page(void *page, unsigned long vaddr, struct page *pg)
43{
44 purge_kernel_dcache_page((unsigned long)page);
45 clear_user_page_asm(page, vaddr);
46}
47 33
48/* 34/*
49 * These are used to make use of C type-checking.. 35 * 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);
332 332
333#define cpu_relax() barrier() 333#define cpu_relax() barrier()
334 334
335/* Used as a macro to identify the combined VIPT/PIPT cached
336 * CPUs which require a guarantee of coherency (no inequivalent
337 * aliases with different data, whether clean or not) to operate */
338static inline int parisc_requires_coherency(void)
339{
340#ifdef CONFIG_PA8X00
341 /* FIXME: also pa8900 - when we see one */
342 return boot_cpu_data.cpu_type == mako;
343#else
344 return 0;
345#endif
346}
347
335#endif /* __ASSEMBLY__ */ 348#endif /* __ASSEMBLY__ */
336 349
337#endif /* __ASM_PARISC_PROCESSOR_H */ 350#endif /* __ASM_PARISC_PROCESSOR_H */