aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/arm/include/asm/smp_plat.h16
-rw-r--r--arch/arm/kernel/smp.c7
-rw-r--r--arch/arm/mm/mmu.c37
3 files changed, 50 insertions, 10 deletions
diff --git a/arch/arm/include/asm/smp_plat.h b/arch/arm/include/asm/smp_plat.h
new file mode 100644
index 000000000000..59303e200845
--- /dev/null
+++ b/arch/arm/include/asm/smp_plat.h
@@ -0,0 +1,16 @@
1/*
2 * ARM specific SMP header, this contains our implementation
3 * details.
4 */
5#ifndef __ASMARM_SMP_PLAT_H
6#define __ASMARM_SMP_PLAT_H
7
8#include <asm/cputype.h>
9
10/* all SMP configurations have the extended CPUID registers */
11static inline int tlb_ops_need_broadcast(void)
12{
13 return ((read_cpuid_ext(CPUID_EXT_MMFR3) >> 12) & 0xf) < 2;
14}
15
16#endif
diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c
index e0d32770bb3d..9d015ee5747a 100644
--- a/arch/arm/kernel/smp.c
+++ b/arch/arm/kernel/smp.c
@@ -36,6 +36,7 @@
36#include <asm/tlbflush.h> 36#include <asm/tlbflush.h>
37#include <asm/ptrace.h> 37#include <asm/ptrace.h>
38#include <asm/localtimer.h> 38#include <asm/localtimer.h>
39#include <asm/smp_plat.h>
39 40
40/* 41/*
41 * as from 2.5, kernels no longer have an init_tasks structure 42 * as from 2.5, kernels no longer have an init_tasks structure
@@ -586,12 +587,6 @@ struct tlb_args {
586 unsigned long ta_end; 587 unsigned long ta_end;
587}; 588};
588 589
589/* all SMP configurations have the extended CPUID registers */
590static inline int tlb_ops_need_broadcast(void)
591{
592 return ((read_cpuid_ext(CPUID_EXT_MMFR3) >> 12) & 0xf) < 2;
593}
594
595static inline void ipi_flush_tlb_all(void *ignored) 590static inline void ipi_flush_tlb_all(void *ignored)
596{ 591{
597 local_flush_tlb_all(); 592 local_flush_tlb_all();
diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c
index ce551ec2cb23..02243eeccf50 100644
--- a/arch/arm/mm/mmu.c
+++ b/arch/arm/mm/mmu.c
@@ -21,6 +21,7 @@
21#include <asm/cachetype.h> 21#include <asm/cachetype.h>
22#include <asm/setup.h> 22#include <asm/setup.h>
23#include <asm/sizes.h> 23#include <asm/sizes.h>
24#include <asm/smp_plat.h>
24#include <asm/tlb.h> 25#include <asm/tlb.h>
25#include <asm/highmem.h> 26#include <asm/highmem.h>
26 27
@@ -709,10 +710,6 @@ static void __init sanity_check_meminfo(void)
709 if (meminfo.nr_banks >= NR_BANKS) { 710 if (meminfo.nr_banks >= NR_BANKS) {
710 printk(KERN_CRIT "NR_BANKS too low, " 711 printk(KERN_CRIT "NR_BANKS too low, "
711 "ignoring high memory\n"); 712 "ignoring high memory\n");
712 } else if (cache_is_vipt_aliasing()) {
713 printk(KERN_CRIT "HIGHMEM is not yet supported "
714 "with VIPT aliasing cache, "
715 "ignoring high memory\n");
716 } else { 713 } else {
717 memmove(bank + 1, bank, 714 memmove(bank + 1, bank,
718 (meminfo.nr_banks - i) * sizeof(*bank)); 715 (meminfo.nr_banks - i) * sizeof(*bank));
@@ -756,6 +753,38 @@ static void __init sanity_check_meminfo(void)
756#endif 753#endif
757 j++; 754 j++;
758 } 755 }
756#ifdef CONFIG_HIGHMEM
757 if (highmem) {
758 const char *reason = NULL;
759
760 if (cache_is_vipt_aliasing()) {
761 /*
762 * Interactions between kmap and other mappings
763 * make highmem support with aliasing VIPT caches
764 * rather difficult.
765 */
766 reason = "with VIPT aliasing cache";
767#ifdef CONFIG_SMP
768 } else if (tlb_ops_need_broadcast()) {
769 /*
770 * kmap_high needs to occasionally flush TLB entries,
771 * however, if the TLB entries need to be broadcast
772 * we may deadlock:
773 * kmap_high(irqs off)->flush_all_zero_pkmaps->
774 * flush_tlb_kernel_range->smp_call_function_many
775 * (must not be called with irqs off)
776 */
777 reason = "without hardware TLB ops broadcasting";
778#endif
779 }
780 if (reason) {
781 printk(KERN_CRIT "HIGHMEM is not supported %s, ignoring high memory\n",
782 reason);
783 while (j > 0 && meminfo.bank[j - 1].highmem)
784 j--;
785 }
786 }
787#endif
759 meminfo.nr_banks = j; 788 meminfo.nr_banks = j;
760} 789}
761 790