History

parisc: Rewrite cache flush code for PA8800/PA8900

Originally, I was convinced that we needed to use tmpalias flushes everwhere, for both user and kernel flushes. However, when I modified flush_kernel_dcache_page_addr, to use a tmpalias flush, my c8000 would crash quite early when booting. The PDC returns alias values of 0 for the icache and dcache. This indicates that either the alias boundary is greater than 16MB or equivalent aliasing doesn't work. I modified the tmpalias code to make it easy to try alternate boundaries. I tried boundaries up to 128MB but still kernel tmpalias flushes didn't work on c8000. This led me to conclude that tmpalias flushes don't work on PA8800 and PA8900 machines, and that we needed to flush directly using the virtual address of user and kernel pages. This is likely the major cause of instability on the c8000 and rp34xx machines. Flushing user pages requires doing a temporary context switch as we have to flush pages that don't belong to the current context. Further, we have to deal with pages that aren't present. If a page isn't present, the flush instructions fault on every line. Other code has been rearranged and simplified based on testing. For example, I introduced a flush_cache_dup_mm routine. flush_cache_mm and flush_cache_dup_mm differ in that flush_cache_mm calls purge_cache_pages and flush_cache_dup_mm calls flush_cache_pages. In some implementations, pdc is more efficient than fdc. Based on my testing, I don't believe there's any performance benefit on the c8000.

John David Anglin committed 4 years ago

Commit 2de8b4c1 parent 67c35a33 files · +236 −127Browse files

Unified · Split

3 files
  1. arch/parisc/include/asm/cacheflush.h +7 −24
  2. arch/parisc/include/asm/page.h +4 −2
  3. arch/parisc/kernel/cache.c +225 −101
arch/parisc/include/asm/cacheflush.h+7−24
@@ -59,20 +59,12 @@ void flush_dcache_page(struct page *page); · 58 unmodified lines
59 flush_kernel_icache_range_asm(s,e); \59 flush_kernel_icache_range_asm(s,e); \
60} while (0)60} while (0)
61 61
62#define copy_to_user_page(vma, page, vaddr, dst, src, len) \62void copy_to_user_page(struct vm_area_struct *vma, struct page *page,
63do { \63 unsigned long user_vaddr, void *dst, void *src, int len);
64 flush_cache_page(vma, vaddr, page_to_pfn(page)); \64void copy_from_user_page(struct vm_area_struct *vma, struct page *page,
65 memcpy(dst, src, len); \65 unsigned long user_vaddr, void *dst, void *src, int len);
66 flush_kernel_dcache_range_asm((unsigned long)dst, (unsigned long)dst + len); \66void flush_cache_page(struct vm_area_struct *vma, unsigned long vmaddr,
67} while (0)67 unsigned long pfn);
68
69#define copy_from_user_page(vma, page, vaddr, dst, src, len) \
70do { \
71 flush_cache_page(vma, vaddr, page_to_pfn(page)); \
72 memcpy(dst, src, len); \
73} while (0)
74
75void flush_cache_page(struct vm_area_struct *vma, unsigned long vmaddr, unsigned long pfn);
76void flush_cache_range(struct vm_area_struct *vma,68void flush_cache_range(struct vm_area_struct *vma,
77 unsigned long start, unsigned long end);69 unsigned long start, unsigned long end);
78 70
@@ -80,16 +72,7 @@ void flush_cache_range(struct vm_area_struct *vma, · 1 unmodified line
80void flush_dcache_page_asm(unsigned long phys_addr, unsigned long vaddr);72void flush_dcache_page_asm(unsigned long phys_addr, unsigned long vaddr);
81 73
82#define ARCH_HAS_FLUSH_ANON_PAGE74#define ARCH_HAS_FLUSH_ANON_PAGE
83static inline void75void flush_anon_page(struct vm_area_struct *vma, struct page *page, unsigned long vmaddr);
84flush_anon_page(struct vm_area_struct *vma, struct page *page, unsigned long vmaddr)
85{
86 if (PageAnon(page)) {
87 flush_tlb_page(vma, vmaddr);
88 preempt_disable();
89 flush_dcache_page_asm(page_to_phys(page), vmaddr);
90 preempt_enable();
91 }
92}
93 76
94#define ARCH_HAS_FLUSH_ON_KUNMAP77#define ARCH_HAS_FLUSH_ON_KUNMAP
95static inline void kunmap_flush_on_unmap(void *addr)78static inline void kunmap_flush_on_unmap(void *addr)
arch/parisc/include/asm/page.h+4−2
@@ -26,12 +26,14 @@ · 25 unmodified lines
26#define copy_page(to, from) copy_page_asm((void *)(to), (void *)(from))26#define copy_page(to, from) copy_page_asm((void *)(to), (void *)(from))
27 27
28struct page;28struct page;
29struct vm_area_struct;
29 30
30void clear_page_asm(void *page);31void clear_page_asm(void *page);
31void copy_page_asm(void *to, void *from);32void copy_page_asm(void *to, void *from);
32#define clear_user_page(vto, vaddr, page) clear_page_asm(vto)33#define clear_user_page(vto, vaddr, page) clear_page_asm(vto)
33void copy_user_page(void *vto, void *vfrom, unsigned long vaddr,34void copy_user_highpage(struct page *to, struct page *from, unsigned long vaddr,
34 struct page *pg);35 struct vm_area_struct *vma);
36#define __HAVE_ARCH_COPY_USER_HIGHPAGE
35 37
36/*38/*
37 * These are used to make use of C type-checking..39 * These are used to make use of C type-checking..
arch/parisc/kernel/cache.c+225−101
@@ -27,6 +27,7 @@ · 26 unmodified lines
27#include <asm/processor.h>27#include <asm/processor.h>
28#include <asm/sections.h>28#include <asm/sections.h>
29#include <asm/shmparam.h>29#include <asm/shmparam.h>
30#include <asm/mmu_context.h>
30 31
31int split_tlb __ro_after_init;32int split_tlb __ro_after_init;
32int dcache_stride __ro_after_init;33int dcache_stride __ro_after_init;
@@ -91,7 +92,7 @@ static inline void flush_data_cache(void) · 58 unmodified lines
91}92}
92 93
93 94
94/* Virtual address of pfn. */95/* Kernel virtual address of pfn. */
95#define pfn_va(pfn) __va(PFN_PHYS(pfn))96#define pfn_va(pfn) __va(PFN_PHYS(pfn))
96 97
97void98void
@@ -124,11 +125,13 @@ show_cache_info(struct seq_file *m) · 26 unmodified lines
124 cache_info.ic_size/1024 );125 cache_info.ic_size/1024 );
125 if (cache_info.dc_loop != 1)126 if (cache_info.dc_loop != 1)
126 snprintf(buf, 32, "%lu-way associative", cache_info.dc_loop);127 snprintf(buf, 32, "%lu-way associative", cache_info.dc_loop);
127 seq_printf(m, "D-cache\t\t: %ld KB (%s%s, %s)\n",128 seq_printf(m, "D-cache\t\t: %ld KB (%s%s, %s, alias=%d)\n",
128 cache_info.dc_size/1024,129 cache_info.dc_size/1024,
129 (cache_info.dc_conf.cc_wt ? "WT":"WB"),130 (cache_info.dc_conf.cc_wt ? "WT":"WB"),
130 (cache_info.dc_conf.cc_sh ? ", shared I/D":""),131 (cache_info.dc_conf.cc_sh ? ", shared I/D":""),
131 ((cache_info.dc_loop == 1) ? "direct mapped" : buf));132 ((cache_info.dc_loop == 1) ? "direct mapped" : buf),
133 cache_info.dc_conf.cc_alias
134 );
132 seq_printf(m, "ITLB entries\t: %ld\n" "DTLB entries\t: %ld%s\n",135 seq_printf(m, "ITLB entries\t: %ld\n" "DTLB entries\t: %ld%s\n",
133 cache_info.it_size,136 cache_info.it_size,
134 cache_info.dt_size,137 cache_info.dt_size,
@@ -324,25 +327,81 @@ __flush_cache_page(struct vm_area_struct *vma, unsigned long vmaddr, · 189 unmodified lines
324 preempt_enable();327 preempt_enable();
325}328}
326 329
327static inline void330static void flush_user_cache_page(struct vm_area_struct *vma, unsigned long vmaddr)
328__purge_cache_page(struct vm_area_struct *vma, unsigned long vmaddr,
329 unsigned long physaddr)
330{331{
331 if (!static_branch_likely(&parisc_has_cache))332 unsigned long flags, space, pgd, prot;
332 return;333#ifdef CONFIG_TLB_PTLOCK
334 unsigned long pgd_lock;
335#endif
336
337 vmaddr &= PAGE_MASK;
338
333 preempt_disable();339 preempt_disable();
334 purge_dcache_page_asm(physaddr, vmaddr);340
341 /* Set context for flush */
342 local_irq_save(flags);
343 prot = mfctl(8);
344 space = mfsp(SR_USER);
345 pgd = mfctl(25);
346#ifdef CONFIG_TLB_PTLOCK
347 pgd_lock = mfctl(28);
348#endif
349 switch_mm_irqs_off(NULL, vma->vm_mm, NULL);
350 local_irq_restore(flags);
351
352 flush_user_dcache_range_asm(vmaddr, vmaddr + PAGE_SIZE);
335 if (vma->vm_flags & VM_EXEC)353 if (vma->vm_flags & VM_EXEC)
336 flush_icache_page_asm(physaddr, vmaddr);354 flush_user_icache_range_asm(vmaddr, vmaddr + PAGE_SIZE);
355 flush_tlb_page(vma, vmaddr);
356
357 /* Restore previous context */
358 local_irq_save(flags);
359#ifdef CONFIG_TLB_PTLOCK
360 mtctl(pgd_lock, 28);
361#endif
362 mtctl(pgd, 25);
363 mtsp(space, SR_USER);
364 mtctl(prot, 8);
365 local_irq_restore(flags);
366
337 preempt_enable();367 preempt_enable();
338}368}
339 369
370static inline pte_t *get_ptep(struct mm_struct *mm, unsigned long addr)
371{
372 pte_t *ptep = NULL;
373 pgd_t *pgd = mm->pgd;
374 p4d_t *p4d;
375 pud_t *pud;
376 pmd_t *pmd;
377
378 if (!pgd_none(*pgd)) {
379 p4d = p4d_offset(pgd, addr);
380 if (!p4d_none(*p4d)) {
381 pud = pud_offset(p4d, addr);
382 if (!pud_none(*pud)) {
383 pmd = pmd_offset(pud, addr);
384 if (!pmd_none(*pmd))
385 ptep = pte_offset_map(pmd, addr);
386 }
387 }
388 }
389 return ptep;
390}
391
392static inline bool pte_needs_flush(pte_t pte)
393{
394 return (pte_val(pte) & (_PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_NO_CACHE))
395 == (_PAGE_PRESENT | _PAGE_ACCESSED);
396}
397
340void flush_dcache_page(struct page *page)398void flush_dcache_page(struct page *page)
341{399{
342 struct address_space *mapping = page_mapping_file(page);400 struct address_space *mapping = page_mapping_file(page);
343 struct vm_area_struct *mpnt;401 struct vm_area_struct *mpnt;
344 unsigned long offset;402 unsigned long offset;
345 unsigned long addr, old_addr = 0;403 unsigned long addr, old_addr = 0;
404 unsigned long count = 0;
346 pgoff_t pgoff;405 pgoff_t pgoff;
347 406
348 if (mapping && !mapping_mapped(mapping)) {407 if (mapping && !mapping_mapped(mapping)) {
@@ -357,33 +416,52 @@ void flush_dcache_page(struct page *page) · 8 unmodified lines
357 416
358 pgoff = page->index;417 pgoff = page->index;
359 418
360 /* We have carefully arranged in arch_get_unmapped_area() that419 /*
420 * We have carefully arranged in arch_get_unmapped_area() that
361 * *any* mappings of a file are always congruently mapped (whether421 * *any* mappings of a file are always congruently mapped (whether
362 * declared as MAP_PRIVATE or MAP_SHARED), so we only need422 * declared as MAP_PRIVATE or MAP_SHARED), so we only need
363 * to flush one address here for them all to become coherent */423 * to flush one address here for them all to become coherent
364 424 * on machines that support equivalent aliasing
425 */
365 flush_dcache_mmap_lock(mapping);426 flush_dcache_mmap_lock(mapping);
366 vma_interval_tree_foreach(mpnt, &mapping->i_mmap, pgoff, pgoff) {427 vma_interval_tree_foreach(mpnt, &mapping->i_mmap, pgoff, pgoff) {
367 offset = (pgoff - mpnt->vm_pgoff) << PAGE_SHIFT;428 offset = (pgoff - mpnt->vm_pgoff) << PAGE_SHIFT;
368 addr = mpnt->vm_start + offset;429 addr = mpnt->vm_start + offset;
430 if (parisc_requires_coherency()) {
431 pte_t *ptep;
369 432
370 /* The TLB is the engine of coherence on parisc: The433 ptep = get_ptep(mpnt->vm_mm, addr);
371 * CPU is entitled to speculate any page with a TLB434 if (ptep && pte_needs_flush(*ptep))
372 * mapping, so here we kill the mapping then flush the435 flush_user_cache_page(mpnt, addr);
373 * page along a special flush only alias mapping.436 } else {
374 * This guarantees that the page is no-longer in the437 /*
375 * cache for any process and nor may it be438 * The TLB is the engine of coherence on parisc:
376 * speculatively read in (until the user or kernel439 * The CPU is entitled to speculate any page
377 * specifically accesses it, of course) */440 * with a TLB mapping, so here we kill the
378 441 * mapping then flush the page along a special
379 flush_tlb_page(mpnt, addr);442 * flush only alias mapping. This guarantees that
380 if (old_addr == 0 || (old_addr & (SHM_COLOUR - 1))443 * the page is no-longer in the cache for any
381 != (addr & (SHM_COLOUR - 1))) {444 * process and nor may it be speculatively read
382 __flush_cache_page(mpnt, addr, page_to_phys(page));445 * in (until the user or kernel specifically
383 if (parisc_requires_coherency() && old_addr)446 * accesses it, of course)
384 printk(KERN_ERR "INEQUIVALENT ALIASES 0x%lx and 0x%lx in file %pD\n", old_addr, addr, mpnt->vm_file);447 */
385 old_addr = addr;448 flush_tlb_page(mpnt, addr);
449 if (old_addr == 0 || (old_addr & (SHM_COLOUR - 1))
450 != (addr & (SHM_COLOUR - 1))) {
451 __flush_cache_page(mpnt, addr, page_to_phys(page));
452 /*
453 * Software is allowed to have any number
454 * of private mappings to a page.
455 */
456 if (!(mpnt->vm_flags & VM_SHARED))
457 continue;
458 if (old_addr)
459 pr_err("INEQUIVALENT ALIASES 0x%lx and 0x%lx in file %pD\n",
460 old_addr, addr, mpnt->vm_file);
461 old_addr = addr;
462 }
386 }463 }
464 WARN_ON(++count == 4096);
387 }465 }
388 flush_dcache_mmap_unlock(mapping);466 flush_dcache_mmap_unlock(mapping);
389}467}
@@ -403,7 +481,7 @@ void __init parisc_setup_cache_timing(void) · 13 unmodified lines
403{481{
404 unsigned long rangetime, alltime;482 unsigned long rangetime, alltime;
405 unsigned long size;483 unsigned long size;
406 unsigned long threshold;484 unsigned long threshold, threshold2;
407 485
408 alltime = mfctl(16);486 alltime = mfctl(16);
409 flush_data_cache();487 flush_data_cache();
@@ -417,11 +495,16 @@ void __init parisc_setup_cache_timing(void) · 7 unmodified lines
417 printk(KERN_DEBUG "Whole cache flush %lu cycles, flushing %lu bytes %lu cycles\n",495 printk(KERN_DEBUG "Whole cache flush %lu cycles, flushing %lu bytes %lu cycles\n",
418 alltime, size, rangetime);496 alltime, size, rangetime);
419 497
420 threshold = L1_CACHE_ALIGN(size * alltime / rangetime);498 threshold = L1_CACHE_ALIGN((unsigned long)((uint64_t)size * alltime / rangetime));
421 if (threshold > cache_info.dc_size)499 pr_info("Calculated flush threshold is %lu KiB\n",
422 threshold = cache_info.dc_size;500 threshold/1024);
423 if (threshold)501
424 parisc_cache_flush_threshold = threshold;502 /*
503 * The threshold computed above isn't very reliable. The following
504 * heuristic works reasonably well on c8000/rp3440.
505 */
506 threshold2 = cache_info.dc_size * num_online_cpus();
507 parisc_cache_flush_threshold = threshold2;
425 printk(KERN_INFO "Cache flush threshold set to %lu KiB\n",508 printk(KERN_INFO "Cache flush threshold set to %lu KiB\n",
426 parisc_cache_flush_threshold/1024);509 parisc_cache_flush_threshold/1024);
427 510
@@ -477,19 +560,47 @@ void flush_kernel_dcache_page_addr(void *addr) · 49 unmodified lines
477}560}
478EXPORT_SYMBOL(flush_kernel_dcache_page_addr);561EXPORT_SYMBOL(flush_kernel_dcache_page_addr);
479 562
480void copy_user_page(void *vto, void *vfrom, unsigned long vaddr,563static void flush_cache_page_if_present(struct vm_area_struct *vma,
481 struct page *pg)564 unsigned long vmaddr, unsigned long pfn)
482{565{
483 /* Copy using kernel mapping. No coherency is needed (all in566 pte_t *ptep = get_ptep(vma->vm_mm, vmaddr);
484 kunmap) for the `to' page. However, the `from' page needs to567
485 be flushed through a mapping equivalent to the user mapping568 /*
486 before it can be accessed through the kernel mapping. */569 * The pte check is racy and sometimes the flush will trigger
487 preempt_disable();570 * a non-access TLB miss. Hopefully, the page has already been
488 flush_dcache_page_asm(__pa(vfrom), vaddr);571 * flushed.
489 copy_page_asm(vto, vfrom);572 */
490 preempt_enable();573 if (ptep && pte_needs_flush(*ptep))
574 flush_cache_page(vma, vmaddr, pfn);
575}
576
577void copy_user_highpage(struct page *to, struct page *from,
578 unsigned long vaddr, struct vm_area_struct *vma)
579{
580 void *kto, *kfrom;
581
582 kfrom = kmap_local_page(from);
583 kto = kmap_local_page(to);
584 flush_cache_page_if_present(vma, vaddr, page_to_pfn(from));
585 copy_page_asm(kto, kfrom);
586 kunmap_local(kto);
587 kunmap_local(kfrom);
588}
589
590void copy_to_user_page(struct vm_area_struct *vma, struct page *page,
591 unsigned long user_vaddr, void *dst, void *src, int len)
592{
593 flush_cache_page_if_present(vma, user_vaddr, page_to_pfn(page));
594 memcpy(dst, src, len);
595 flush_kernel_dcache_range_asm((unsigned long)dst, (unsigned long)dst + len);
596}
597
598void copy_from_user_page(struct vm_area_struct *vma, struct page *page,
599 unsigned long user_vaddr, void *dst, void *src, int len)
600{
601 flush_cache_page_if_present(vma, user_vaddr, page_to_pfn(page));
602 memcpy(dst, src, len);
491}603}
492EXPORT_SYMBOL(copy_user_page);
493 604
494/* __flush_tlb_range()605/* __flush_tlb_range()
495 *606 *
@@ -520,92 +631,105 @@ int __flush_tlb_range(unsigned long sid, unsigned long start, · 24 unmodified lines
520 return 0;631 return 0;
521}632}
522 633
523static inline unsigned long mm_total_size(struct mm_struct *mm)634static void flush_cache_pages(struct vm_area_struct *vma, unsigned long start, unsigned long end)
524{635{
525 struct vm_area_struct *vma;636 unsigned long addr, pfn;
526 unsigned long usize = 0;637 pte_t *ptep;
527
528 for (vma = mm->mmap; vma; vma = vma->vm_next)
529 usize += vma->vm_end - vma->vm_start;
530 return usize;
531}
532
533static inline pte_t *get_ptep(pgd_t *pgd, unsigned long addr)
534{
535 pte_t *ptep = NULL;
536 638
537 if (!pgd_none(*pgd)) {639 for (addr = start; addr < end; addr += PAGE_SIZE) {
538 p4d_t *p4d = p4d_offset(pgd, addr);640 /*
539 if (!p4d_none(*p4d)) {641 * The vma can contain pages that aren't present. Although
540 pud_t *pud = pud_offset(p4d, addr);642 * the pte search is expensive, we need the pte to find the
541 if (!pud_none(*pud)) {643 * page pfn and to check whether the page should be flushed.
542 pmd_t *pmd = pmd_offset(pud, addr);644 */
543 if (!pmd_none(*pmd))645 ptep = get_ptep(vma->vm_mm, addr);
544 ptep = pte_offset_map(pmd, addr);646 if (ptep && pte_needs_flush(*ptep)) {
647 if (parisc_requires_coherency()) {
648 flush_user_cache_page(vma, addr);
649 } else {
650 pfn = pte_pfn(*ptep);
651 if (WARN_ON(!pfn_valid(pfn)))
652 return;
653 __flush_cache_page(vma, addr, PFN_PHYS(pfn));
545 }654 }
546 }655 }
547 }656 }
548 return ptep;
549}657}
550 658
551static void flush_cache_pages(struct vm_area_struct *vma, struct mm_struct *mm,659static inline unsigned long mm_total_size(struct mm_struct *mm)
552 unsigned long start, unsigned long end)
553{660{
554 unsigned long addr, pfn;661 struct vm_area_struct *vma;
555 pte_t *ptep;662 unsigned long usize = 0;
556 663
557 for (addr = start; addr < end; addr += PAGE_SIZE) {664 for (vma = mm->mmap; vma && usize < parisc_cache_flush_threshold; vma = vma->vm_next)
558 ptep = get_ptep(mm->pgd, addr);665 usize += vma->vm_end - vma->vm_start;
559 if (ptep) {666 return usize;
560 pfn = pte_pfn(*ptep);
561 flush_cache_page(vma, addr, pfn);
562 }
563 }
564}667}
565 668
566void flush_cache_mm(struct mm_struct *mm)669void flush_cache_mm(struct mm_struct *mm)
567{670{
568 struct vm_area_struct *vma;671 struct vm_area_struct *vma;
569 672
570 /* Flushing the whole cache on each cpu takes forever on673 /*
571 rp3440, etc. So, avoid it if the mm isn't too big. */674 * Flushing the whole cache on each cpu takes forever on
572 if ((!IS_ENABLED(CONFIG_SMP) || !arch_irqs_disabled()) &&675 * rp3440, etc. So, avoid it if the mm isn't too big.
573 mm_total_size(mm) >= parisc_cache_flush_threshold) {676 *
574 if (mm->context.space_id)677 * Note that we must flush the entire cache on machines
575 flush_tlb_all();678 * with aliasing caches to prevent random segmentation
679 * faults.
680 */
681 if (!parisc_requires_coherency()
682 || mm_total_size(mm) >= parisc_cache_flush_threshold) {
683 if (WARN_ON(IS_ENABLED(CONFIG_SMP) && arch_irqs_disabled()))
684 return;
685 flush_tlb_all();
576 flush_cache_all();686 flush_cache_all();
577 return;687 return;
578 }688 }
579 689
690 /* Flush mm */
580 for (vma = mm->mmap; vma; vma = vma->vm_next)691 for (vma = mm->mmap; vma; vma = vma->vm_next)
581 flush_cache_pages(vma, mm, vma->vm_start, vma->vm_end);692 flush_cache_pages(vma, vma->vm_start, vma->vm_end);
582}693}
583 694
584void flush_cache_range(struct vm_area_struct *vma,695void flush_cache_range(struct vm_area_struct *vma, unsigned long start, unsigned long end)
585 unsigned long start, unsigned long end)
586{696{
587 if ((!IS_ENABLED(CONFIG_SMP) || !arch_irqs_disabled()) &&697 if (!parisc_requires_coherency()
588 end - start >= parisc_cache_flush_threshold) {698 || end - start >= parisc_cache_flush_threshold) {
589 if (vma->vm_mm->context.space_id)699 if (WARN_ON(IS_ENABLED(CONFIG_SMP) && arch_irqs_disabled()))
590 flush_tlb_range(vma, start, end);700 return;
701 flush_tlb_range(vma, start, end);
591 flush_cache_all();702 flush_cache_all();
592 return;703 return;
593 }704 }
594 705
595 flush_cache_pages(vma, vma->vm_mm, start, end);706 flush_cache_pages(vma, start, end);
596}707}
597 708
598void709void flush_cache_page(struct vm_area_struct *vma, unsigned long vmaddr, unsigned long pfn)
599flush_cache_page(struct vm_area_struct *vma, unsigned long vmaddr, unsigned long pfn)
600{710{
601 if (pfn_valid(pfn)) {711 if (WARN_ON(!pfn_valid(pfn)))
602 if (likely(vma->vm_mm->context.space_id)) {712 return;
603 flush_tlb_page(vma, vmaddr);713 if (parisc_requires_coherency())
604 __flush_cache_page(vma, vmaddr, PFN_PHYS(pfn));714 flush_user_cache_page(vma, vmaddr);
605 } else {715 else
606 __purge_cache_page(vma, vmaddr, PFN_PHYS(pfn));716 __flush_cache_page(vma, vmaddr, PFN_PHYS(pfn));
607 }717}
718
719void flush_anon_page(struct vm_area_struct *vma, struct page *page, unsigned long vmaddr)
720{
721 if (!PageAnon(page))
722 return;
723
724 if (parisc_requires_coherency()) {
725 flush_user_cache_page(vma, vmaddr);
726 return;
608 }727 }
728
729 flush_tlb_page(vma, vmaddr);
730 preempt_disable();
731 flush_dcache_page_asm(page_to_phys(page), vmaddr);
732 preempt_enable();
609}733}
610 734
611void flush_kernel_vmap_range(void *vaddr, int size)735void flush_kernel_vmap_range(void *vaddr, int size)