aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/kernel/smp.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/kernel/smp.c')
-rw-r--r--arch/arm/kernel/smp.c69
1 files changed, 43 insertions, 26 deletions
diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c
index 6014dfd22af..ece658e773a 100644
--- a/arch/arm/kernel/smp.c
+++ b/arch/arm/kernel/smp.c
@@ -32,6 +32,7 @@
32#include <asm/processor.h> 32#include <asm/processor.h>
33#include <asm/tlbflush.h> 33#include <asm/tlbflush.h>
34#include <asm/ptrace.h> 34#include <asm/ptrace.h>
35#include <asm/cputype.h>
35 36
36/* 37/*
37 * as from 2.5, kernels no longer have an init_tasks structure 38 * as from 2.5, kernels no longer have an init_tasks structure
@@ -545,6 +546,12 @@ struct tlb_args {
545 unsigned long ta_end; 546 unsigned long ta_end;
546}; 547};
547 548
549/* all SMP configurations have the extended CPUID registers */
550static inline int tlb_ops_need_broadcast(void)
551{
552 return ((read_cpuid_ext(CPUID_EXT_MMFR3) >> 12) & 0xf) < 2;
553}
554
548static inline void ipi_flush_tlb_all(void *ignored) 555static inline void ipi_flush_tlb_all(void *ignored)
549{ 556{
550 local_flush_tlb_all(); 557 local_flush_tlb_all();
@@ -587,51 +594,61 @@ static inline void ipi_flush_tlb_kernel_range(void *arg)
587 594
588void flush_tlb_all(void) 595void flush_tlb_all(void)
589{ 596{
590 on_each_cpu(ipi_flush_tlb_all, NULL, 1); 597 if (tlb_ops_need_broadcast())
598 on_each_cpu(ipi_flush_tlb_all, NULL, 1);
599 else
600 local_flush_tlb_all();
591} 601}
592 602
593void flush_tlb_mm(struct mm_struct *mm) 603void flush_tlb_mm(struct mm_struct *mm)
594{ 604{
595 on_each_cpu_mask(ipi_flush_tlb_mm, mm, 1, &mm->cpu_vm_mask); 605 if (tlb_ops_need_broadcast())
606 on_each_cpu_mask(ipi_flush_tlb_mm, mm, 1, &mm->cpu_vm_mask);
607 else
608 local_flush_tlb_mm(mm);
596} 609}
597 610
598void flush_tlb_page(struct vm_area_struct *vma, unsigned long uaddr) 611void flush_tlb_page(struct vm_area_struct *vma, unsigned long uaddr)
599{ 612{
600 struct tlb_args ta; 613 if (tlb_ops_need_broadcast()) {
601 614 struct tlb_args ta;
602 ta.ta_vma = vma; 615 ta.ta_vma = vma;
603 ta.ta_start = uaddr; 616 ta.ta_start = uaddr;
604 617 on_each_cpu_mask(ipi_flush_tlb_page, &ta, 1, &vma->vm_mm->cpu_vm_mask);
605 on_each_cpu_mask(ipi_flush_tlb_page, &ta, 1, &vma->vm_mm->cpu_vm_mask); 618 } else
619 local_flush_tlb_page(vma, uaddr);
606} 620}
607 621
608void flush_tlb_kernel_page(unsigned long kaddr) 622void flush_tlb_kernel_page(unsigned long kaddr)
609{ 623{
610 struct tlb_args ta; 624 if (tlb_ops_need_broadcast()) {
611 625 struct tlb_args ta;
612 ta.ta_start = kaddr; 626 ta.ta_start = kaddr;
613 627 on_each_cpu(ipi_flush_tlb_kernel_page, &ta, 1);
614 on_each_cpu(ipi_flush_tlb_kernel_page, &ta, 1); 628 } else
629 local_flush_tlb_kernel_page(kaddr);
615} 630}
616 631
617void flush_tlb_range(struct vm_area_struct *vma, 632void flush_tlb_range(struct vm_area_struct *vma,
618 unsigned long start, unsigned long end) 633 unsigned long start, unsigned long end)
619{ 634{
620 struct tlb_args ta; 635 if (tlb_ops_need_broadcast()) {
621 636 struct tlb_args ta;
622 ta.ta_vma = vma; 637 ta.ta_vma = vma;
623 ta.ta_start = start; 638 ta.ta_start = start;
624 ta.ta_end = end; 639 ta.ta_end = end;
625 640 on_each_cpu_mask(ipi_flush_tlb_range, &ta, 1, &vma->vm_mm->cpu_vm_mask);
626 on_each_cpu_mask(ipi_flush_tlb_range, &ta, 1, &vma->vm_mm->cpu_vm_mask); 641 } else
642 local_flush_tlb_range(vma, start, end);
627} 643}
628 644
629void flush_tlb_kernel_range(unsigned long start, unsigned long end) 645void flush_tlb_kernel_range(unsigned long start, unsigned long end)
630{ 646{
631 struct tlb_args ta; 647 if (tlb_ops_need_broadcast()) {
632 648 struct tlb_args ta;
633 ta.ta_start = start; 649 ta.ta_start = start;
634 ta.ta_end = end; 650 ta.ta_end = end;
635 651 on_each_cpu(ipi_flush_tlb_kernel_range, &ta, 1);
636 on_each_cpu(ipi_flush_tlb_kernel_range, &ta, 1); 652 } else
653 local_flush_tlb_kernel_range(start, end);
637} 654}