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
5959 flush_kernel_icache_range_asm(s,e); \
6060 } while (0)
6161
62−#define copy_to_user_page(vma, page, vaddr, dst, src, len) \
63−do { \
64− flush_cache_page(vma, vaddr, page_to_pfn(page)); \
65− memcpy(dst, src, len); \
66− flush_kernel_dcache_range_asm((unsigned long)dst, (unsigned long)dst + len); \
67−} while (0)
68−
69−#define copy_from_user_page(vma, page, vaddr, dst, src, len) \
70−do { \
71− flush_cache_page(vma, vaddr, page_to_pfn(page)); \
72− memcpy(dst, src, len); \
73−} while (0)
74−
75−void flush_cache_page(struct vm_area_struct *vma, unsigned long vmaddr, unsigned long pfn);
62+void copy_to_user_page(struct vm_area_struct *vma, struct page *page,
63+ unsigned long user_vaddr, void *dst, void *src, int len);
64+void copy_from_user_page(struct vm_area_struct *vma, struct page *page,
65+ unsigned long user_vaddr, void *dst, void *src, int len);
66+void flush_cache_page(struct vm_area_struct *vma, unsigned long vmaddr,
67+ unsigned long pfn);
7668 void flush_cache_range(struct vm_area_struct *vma,
7769 unsigned long start, unsigned long end);
7870
@@ -80,16 +72,7 @@ void flush_cache_range(struct vm_area_struct *vma, · 1 unmodified line
8072 void flush_dcache_page_asm(unsigned long phys_addr, unsigned long vaddr);
8173
8274 #define ARCH_HAS_FLUSH_ANON_PAGE
83−static inline void
84−flush_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−}
75+void flush_anon_page(struct vm_area_struct *vma, struct page *page, unsigned long vmaddr);
9376
9477 #define ARCH_HAS_FLUSH_ON_KUNMAP
9578 static inline void kunmap_flush_on_unmap(void *addr)
arch/parisc/include/asm/page.h+4−2
@@ -26,12 +26,14 @@ · 25 unmodified lines
2626 #define copy_page(to, from) copy_page_asm((void *)(to), (void *)(from))
2727
2828 struct page;
29+struct vm_area_struct;
2930
3031 void clear_page_asm(void *page);
3132 void copy_page_asm(void *to, void *from);
3233 #define clear_user_page(vto, vaddr, page) clear_page_asm(vto)
33−void copy_user_page(void *vto, void *vfrom, unsigned long vaddr,
34− struct page *pg);
34+void copy_user_highpage(struct page *to, struct page *from, unsigned long vaddr,
35+ struct vm_area_struct *vma);
36+#define __HAVE_ARCH_COPY_USER_HIGHPAGE
3537
3638 /*
3739 * These are used to make use of C type-checking..
arch/parisc/kernel/cache.c+225−101
@@ -27,6 +27,7 @@ · 26 unmodified lines
2727 #include <asm/processor.h>
2828 #include <asm/sections.h>
2929 #include <asm/shmparam.h>
30+#include <asm/mmu_context.h>
3031
3132 int split_tlb __ro_after_init;
3233 int dcache_stride __ro_after_init;
@@ -91,7 +92,7 @@ static inline void flush_data_cache(void) · 58 unmodified lines
9192 }
9293
9394
94−/* Virtual address of pfn. */
95+/* Kernel virtual address of pfn. */
9596 #define pfn_va(pfn) __va(PFN_PHYS(pfn))
9697
9798 void
@@ -124,11 +125,13 @@ show_cache_info(struct seq_file *m) · 26 unmodified lines
124125 cache_info.ic_size/1024 );
125126 if (cache_info.dc_loop != 1)
126127 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",
128129 cache_info.dc_size/1024,
129130 (cache_info.dc_conf.cc_wt ? "WT":"WB"),
130131 (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+ );
132135 seq_printf(m, "ITLB entries\t: %ld\n" "DTLB entries\t: %ld%s\n",
133136 cache_info.it_size,
134137 cache_info.dt_size,
@@ -324,25 +327,81 @@ __flush_cache_page(struct vm_area_struct *vma, unsigned long vmaddr, · 189 unmodified lines
324327 preempt_enable();
325328 }
326329
327−static inline void
328−__purge_cache_page(struct vm_area_struct *vma, unsigned long vmaddr,
329− unsigned long physaddr)
330+static void flush_user_cache_page(struct vm_area_struct *vma, unsigned long vmaddr)
330331 {
331− if (!static_branch_likely(&parisc_has_cache))
332− return;
332+ unsigned long flags, space, pgd, prot;
333+#ifdef CONFIG_TLB_PTLOCK
334+ unsigned long pgd_lock;
335+#endif
336+
337+ vmaddr &= PAGE_MASK;
338+
333339 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);
335353 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+
337367 preempt_enable();
338368 }
339369
370+static 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+
392+static 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+
340398 void flush_dcache_page(struct page *page)
341399 {
342400 struct address_space *mapping = page_mapping_file(page);
343401 struct vm_area_struct *mpnt;
344402 unsigned long offset;
345403 unsigned long addr, old_addr = 0;
404+ unsigned long count = 0;
346405 pgoff_t pgoff;
347406
348407 if (mapping && !mapping_mapped(mapping)) {
@@ -357,33 +416,52 @@ void flush_dcache_page(struct page *page) · 8 unmodified lines
357416
358417 pgoff = page->index;
359418
360− /* We have carefully arranged in arch_get_unmapped_area() that
419+ /*
420+ * We have carefully arranged in arch_get_unmapped_area() that
361421 * *any* mappings of a file are always congruently mapped (whether
362422 * declared as MAP_PRIVATE or MAP_SHARED), so we only need
363− * to flush one address here for them all to become coherent */
364−
423+ * to flush one address here for them all to become coherent
424+ * on machines that support equivalent aliasing
425+ */
365426 flush_dcache_mmap_lock(mapping);
366427 vma_interval_tree_foreach(mpnt, &mapping->i_mmap, pgoff, pgoff) {
367428 offset = (pgoff - mpnt->vm_pgoff) << PAGE_SHIFT;
368429 addr = mpnt->vm_start + offset;
430+ if (parisc_requires_coherency()) {
431+ pte_t *ptep;
369432
370− /* The TLB is the engine of coherence on parisc: The
371− * CPU is entitled to speculate any page with a TLB
372− * mapping, so here we kill the mapping then flush the
373− * page along a special flush only alias mapping.
374− * This guarantees that the page is no-longer in the
375− * cache for any process and nor may it be
376− * speculatively read in (until the user or kernel
377− * specifically accesses it, of course) */
378−
379− flush_tlb_page(mpnt, addr);
380− if (old_addr == 0 || (old_addr & (SHM_COLOUR - 1))
381− != (addr & (SHM_COLOUR - 1))) {
382− __flush_cache_page(mpnt, addr, page_to_phys(page));
383− if (parisc_requires_coherency() && old_addr)
384− printk(KERN_ERR "INEQUIVALENT ALIASES 0x%lx and 0x%lx in file %pD\n", old_addr, addr, mpnt->vm_file);
385− old_addr = addr;
433+ ptep = get_ptep(mpnt->vm_mm, addr);
434+ if (ptep && pte_needs_flush(*ptep))
435+ flush_user_cache_page(mpnt, addr);
436+ } else {
437+ /*
438+ * The TLB is the engine of coherence on parisc:
439+ * The CPU is entitled to speculate any page
440+ * with a TLB mapping, so here we kill the
441+ * mapping then flush the page along a special
442+ * flush only alias mapping. This guarantees that
443+ * the page is no-longer in the cache for any
444+ * process and nor may it be speculatively read
445+ * in (until the user or kernel specifically
446+ * accesses it, of course)
447+ */
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+ }
386463 }
464+ WARN_ON(++count == 4096);
387465 }
388466 flush_dcache_mmap_unlock(mapping);
389467 }
@@ -403,7 +481,7 @@ void __init parisc_setup_cache_timing(void) · 13 unmodified lines
403481 {
404482 unsigned long rangetime, alltime;
405483 unsigned long size;
406− unsigned long threshold;
484+ unsigned long threshold, threshold2;
407485
408486 alltime = mfctl(16);
409487 flush_data_cache();
@@ -417,11 +495,16 @@ void __init parisc_setup_cache_timing(void) · 7 unmodified lines
417495 printk(KERN_DEBUG "Whole cache flush %lu cycles, flushing %lu bytes %lu cycles\n",
418496 alltime, size, rangetime);
419497
420− threshold = L1_CACHE_ALIGN(size * alltime / rangetime);
421− if (threshold > cache_info.dc_size)
422− threshold = cache_info.dc_size;
423− if (threshold)
424− parisc_cache_flush_threshold = threshold;
498+ threshold = L1_CACHE_ALIGN((unsigned long)((uint64_t)size * alltime / rangetime));
499+ pr_info("Calculated flush threshold is %lu KiB\n",
500+ threshold/1024);
501+
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;
425508 printk(KERN_INFO "Cache flush threshold set to %lu KiB\n",
426509 parisc_cache_flush_threshold/1024);
427510
@@ -477,19 +560,47 @@ void flush_kernel_dcache_page_addr(void *addr) · 49 unmodified lines
477560 }
478561 EXPORT_SYMBOL(flush_kernel_dcache_page_addr);
479562
480−void copy_user_page(void *vto, void *vfrom, unsigned long vaddr,
481− struct page *pg)
563+static void flush_cache_page_if_present(struct vm_area_struct *vma,
564+ unsigned long vmaddr, unsigned long pfn)
482565 {
483− /* Copy using kernel mapping. No coherency is needed (all in
484− kunmap) for the `to' page. However, the `from' page needs to
485− be flushed through a mapping equivalent to the user mapping
486− before it can be accessed through the kernel mapping. */
487− preempt_disable();
488− flush_dcache_page_asm(__pa(vfrom), vaddr);
489− copy_page_asm(vto, vfrom);
490− preempt_enable();
566+ pte_t *ptep = get_ptep(vma->vm_mm, vmaddr);
567+
568+ /*
569+ * The pte check is racy and sometimes the flush will trigger
570+ * a non-access TLB miss. Hopefully, the page has already been
571+ * flushed.
572+ */
573+ if (ptep && pte_needs_flush(*ptep))
574+ flush_cache_page(vma, vmaddr, pfn);
575+}
576+
577+void 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+
590+void 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+
598+void 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);
491603 }
492−EXPORT_SYMBOL(copy_user_page);
493604
494605 /* __flush_tlb_range()
495606 *
@@ -520,92 +631,105 @@ int __flush_tlb_range(unsigned long sid, unsigned long start, · 24 unmodified lines
520631 return 0;
521632 }
522633
523−static inline unsigned long mm_total_size(struct mm_struct *mm)
634+static void flush_cache_pages(struct vm_area_struct *vma, unsigned long start, unsigned long end)
524635 {
525− struct vm_area_struct *vma;
526− unsigned long usize = 0;
527−
528− for (vma = mm->mmap; vma; vma = vma->vm_next)
529− usize += vma->vm_end - vma->vm_start;
530− return usize;
531−}
532−
533−static inline pte_t *get_ptep(pgd_t *pgd, unsigned long addr)
534−{
535− pte_t *ptep = NULL;
636+ unsigned long addr, pfn;
637+ pte_t *ptep;
536638
537− if (!pgd_none(*pgd)) {
538− p4d_t *p4d = p4d_offset(pgd, addr);
539− if (!p4d_none(*p4d)) {
540− pud_t *pud = pud_offset(p4d, addr);
541− if (!pud_none(*pud)) {
542− pmd_t *pmd = pmd_offset(pud, addr);
543− if (!pmd_none(*pmd))
544− ptep = pte_offset_map(pmd, addr);
639+ for (addr = start; addr < end; addr += PAGE_SIZE) {
640+ /*
641+ * The vma can contain pages that aren't present. Although
642+ * the pte search is expensive, we need the pte to find the
643+ * page pfn and to check whether the page should be flushed.
644+ */
645+ ptep = get_ptep(vma->vm_mm, 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));
545654 }
546655 }
547656 }
548− return ptep;
549657 }
550658
551−static void flush_cache_pages(struct vm_area_struct *vma, struct mm_struct *mm,
552− unsigned long start, unsigned long end)
659+static inline unsigned long mm_total_size(struct mm_struct *mm)
553660 {
554− unsigned long addr, pfn;
555− pte_t *ptep;
661+ struct vm_area_struct *vma;
662+ unsigned long usize = 0;
556663
557− for (addr = start; addr < end; addr += PAGE_SIZE) {
558− ptep = get_ptep(mm->pgd, addr);
559− if (ptep) {
560− pfn = pte_pfn(*ptep);
561− flush_cache_page(vma, addr, pfn);
562− }
563− }
664+ for (vma = mm->mmap; vma && usize < parisc_cache_flush_threshold; vma = vma->vm_next)
665+ usize += vma->vm_end - vma->vm_start;
666+ return usize;
564667 }
565668
566669 void flush_cache_mm(struct mm_struct *mm)
567670 {
568671 struct vm_area_struct *vma;
569672
570− /* Flushing the whole cache on each cpu takes forever on
571− rp3440, etc. So, avoid it if the mm isn't too big. */
572− if ((!IS_ENABLED(CONFIG_SMP) || !arch_irqs_disabled()) &&
573− mm_total_size(mm) >= parisc_cache_flush_threshold) {
574− if (mm->context.space_id)
575− flush_tlb_all();
673+ /*
674+ * Flushing the whole cache on each cpu takes forever on
675+ * rp3440, etc. So, avoid it if the mm isn't too big.
676+ *
677+ * Note that we must flush the entire cache on machines
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();
576686 flush_cache_all();
577687 return;
578688 }
579689
690+ /* Flush mm */
580691 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);
582693 }
583694
584−void flush_cache_range(struct vm_area_struct *vma,
585− unsigned long start, unsigned long end)
695+void flush_cache_range(struct vm_area_struct *vma, unsigned long start, unsigned long end)
586696 {
587− if ((!IS_ENABLED(CONFIG_SMP) || !arch_irqs_disabled()) &&
588− end - start >= parisc_cache_flush_threshold) {
589− if (vma->vm_mm->context.space_id)
590− flush_tlb_range(vma, start, end);
697+ if (!parisc_requires_coherency()
698+ || end - start >= parisc_cache_flush_threshold) {
699+ if (WARN_ON(IS_ENABLED(CONFIG_SMP) && arch_irqs_disabled()))
700+ return;
701+ flush_tlb_range(vma, start, end);
591702 flush_cache_all();
592703 return;
593704 }
594705
595− flush_cache_pages(vma, vma->vm_mm, start, end);
706+ flush_cache_pages(vma, start, end);
596707 }
597708
598−void
599−flush_cache_page(struct vm_area_struct *vma, unsigned long vmaddr, unsigned long pfn)
709+void flush_cache_page(struct vm_area_struct *vma, unsigned long vmaddr, unsigned long pfn)
600710 {
601− if (pfn_valid(pfn)) {
602− if (likely(vma->vm_mm->context.space_id)) {
603− flush_tlb_page(vma, vmaddr);
604− __flush_cache_page(vma, vmaddr, PFN_PHYS(pfn));
605− } else {
606− __purge_cache_page(vma, vmaddr, PFN_PHYS(pfn));
607− }
711+ if (WARN_ON(!pfn_valid(pfn)))
712+ return;
713+ if (parisc_requires_coherency())
714+ flush_user_cache_page(vma, vmaddr);
715+ else
716+ __flush_cache_page(vma, vmaddr, PFN_PHYS(pfn));
717+}
718+
719+void 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;
608727 }
728+
729+ flush_tlb_page(vma, vmaddr);
730+ preempt_disable();
731+ flush_dcache_page_asm(page_to_phys(page), vmaddr);
732+ preempt_enable();
609733 }
610734
611735 void flush_kernel_vmap_range(void *vaddr, int size)