aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
Diffstat (limited to 'arch')
-rw-r--r--arch/arm/include/asm/cputype.h25
-rw-r--r--arch/arm/include/asm/tlbflush.h26
-rw-r--r--arch/arm/kernel/smp.c69
-rw-r--r--arch/arm/mm/proc-v7.S4
-rw-r--r--arch/arm/mm/tlb-v7.S17
5 files changed, 105 insertions, 36 deletions
diff --git a/arch/arm/include/asm/cputype.h b/arch/arm/include/asm/cputype.h
index 7b9d27e749b8..b3e656c6fb78 100644
--- a/arch/arm/include/asm/cputype.h
+++ b/arch/arm/include/asm/cputype.h
@@ -8,6 +8,21 @@
8#define CPUID_TCM 2 8#define CPUID_TCM 2
9#define CPUID_TLBTYPE 3 9#define CPUID_TLBTYPE 3
10 10
11#define CPUID_EXT_PFR0 "c1, 0"
12#define CPUID_EXT_PFR1 "c1, 1"
13#define CPUID_EXT_DFR0 "c1, 2"
14#define CPUID_EXT_AFR0 "c1, 3"
15#define CPUID_EXT_MMFR0 "c1, 4"
16#define CPUID_EXT_MMFR1 "c1, 5"
17#define CPUID_EXT_MMFR2 "c1, 6"
18#define CPUID_EXT_MMFR3 "c1, 7"
19#define CPUID_EXT_ISAR0 "c2, 0"
20#define CPUID_EXT_ISAR1 "c2, 1"
21#define CPUID_EXT_ISAR2 "c2, 2"
22#define CPUID_EXT_ISAR3 "c2, 3"
23#define CPUID_EXT_ISAR4 "c2, 4"
24#define CPUID_EXT_ISAR5 "c2, 5"
25
11#ifdef CONFIG_CPU_CP15 26#ifdef CONFIG_CPU_CP15
12#define read_cpuid(reg) \ 27#define read_cpuid(reg) \
13 ({ \ 28 ({ \
@@ -18,9 +33,19 @@
18 : "cc"); \ 33 : "cc"); \
19 __val; \ 34 __val; \
20 }) 35 })
36#define read_cpuid_ext(ext_reg) \
37 ({ \
38 unsigned int __val; \
39 asm("mrc p15, 0, %0, c0, " ext_reg \
40 : "=r" (__val) \
41 : \
42 : "cc"); \
43 __val; \
44 })
21#else 45#else
22extern unsigned int processor_id; 46extern unsigned int processor_id;
23#define read_cpuid(reg) (processor_id) 47#define read_cpuid(reg) (processor_id)
48#define read_cpuid_ext(reg) 0
24#endif 49#endif
25 50
26/* 51/*
diff --git a/arch/arm/include/asm/tlbflush.h b/arch/arm/include/asm/tlbflush.h
index a62218013c78..c964f3fc3bc5 100644
--- a/arch/arm/include/asm/tlbflush.h
+++ b/arch/arm/include/asm/tlbflush.h
@@ -40,6 +40,12 @@
40#define TLB_V6_I_ASID (1 << 18) 40#define TLB_V6_I_ASID (1 << 18)
41 41
42#define TLB_BTB (1 << 28) 42#define TLB_BTB (1 << 28)
43
44/* Unified Inner Shareable TLB operations (ARMv7 MP extensions) */
45#define TLB_V7_UIS_PAGE (1 << 19)
46#define TLB_V7_UIS_FULL (1 << 20)
47#define TLB_V7_UIS_ASID (1 << 21)
48
43#define TLB_L2CLEAN_FR (1 << 29) /* Feroceon */ 49#define TLB_L2CLEAN_FR (1 << 29) /* Feroceon */
44#define TLB_DCLEAN (1 << 30) 50#define TLB_DCLEAN (1 << 30)
45#define TLB_WB (1 << 31) 51#define TLB_WB (1 << 31)
@@ -176,9 +182,17 @@
176# define v6wbi_always_flags (-1UL) 182# define v6wbi_always_flags (-1UL)
177#endif 183#endif
178 184
185#ifdef CONFIG_SMP
186#define v7wbi_tlb_flags (TLB_WB | TLB_DCLEAN | TLB_BTB | \
187 TLB_V7_UIS_FULL | TLB_V7_UIS_PAGE | TLB_V7_UIS_ASID)
188#else
189#define v7wbi_tlb_flags (TLB_WB | TLB_DCLEAN | TLB_BTB | \
190 TLB_V6_U_FULL | TLB_V6_U_PAGE | TLB_V6_U_ASID)
191#endif
192
179#ifdef CONFIG_CPU_TLB_V7 193#ifdef CONFIG_CPU_TLB_V7
180# define v7wbi_possible_flags v6wbi_tlb_flags 194# define v7wbi_possible_flags v7wbi_tlb_flags
181# define v7wbi_always_flags v6wbi_tlb_flags 195# define v7wbi_always_flags v7wbi_tlb_flags
182# ifdef _TLB 196# ifdef _TLB
183# define MULTI_TLB 1 197# define MULTI_TLB 1
184# else 198# else
@@ -316,6 +330,8 @@ static inline void local_flush_tlb_all(void)
316 asm("mcr p15, 0, %0, c8, c6, 0" : : "r" (zero) : "cc"); 330 asm("mcr p15, 0, %0, c8, c6, 0" : : "r" (zero) : "cc");
317 if (tlb_flag(TLB_V4_I_FULL | TLB_V6_I_FULL)) 331 if (tlb_flag(TLB_V4_I_FULL | TLB_V6_I_FULL))
318 asm("mcr p15, 0, %0, c8, c5, 0" : : "r" (zero) : "cc"); 332 asm("mcr p15, 0, %0, c8, c5, 0" : : "r" (zero) : "cc");
333 if (tlb_flag(TLB_V7_UIS_FULL))
334 asm("mcr p15, 0, %0, c8, c3, 0" : : "r" (zero) : "cc");
319 335
320 if (tlb_flag(TLB_BTB)) { 336 if (tlb_flag(TLB_BTB)) {
321 /* flush the branch target cache */ 337 /* flush the branch target cache */
@@ -351,6 +367,8 @@ static inline void local_flush_tlb_mm(struct mm_struct *mm)
351 asm("mcr p15, 0, %0, c8, c6, 2" : : "r" (asid) : "cc"); 367 asm("mcr p15, 0, %0, c8, c6, 2" : : "r" (asid) : "cc");
352 if (tlb_flag(TLB_V6_I_ASID)) 368 if (tlb_flag(TLB_V6_I_ASID))
353 asm("mcr p15, 0, %0, c8, c5, 2" : : "r" (asid) : "cc"); 369 asm("mcr p15, 0, %0, c8, c5, 2" : : "r" (asid) : "cc");
370 if (tlb_flag(TLB_V7_UIS_ASID))
371 asm("mcr p15, 0, %0, c8, c3, 2" : : "r" (asid) : "cc");
354 372
355 if (tlb_flag(TLB_BTB)) { 373 if (tlb_flag(TLB_BTB)) {
356 /* flush the branch target cache */ 374 /* flush the branch target cache */
@@ -389,6 +407,8 @@ local_flush_tlb_page(struct vm_area_struct *vma, unsigned long uaddr)
389 asm("mcr p15, 0, %0, c8, c6, 1" : : "r" (uaddr) : "cc"); 407 asm("mcr p15, 0, %0, c8, c6, 1" : : "r" (uaddr) : "cc");
390 if (tlb_flag(TLB_V6_I_PAGE)) 408 if (tlb_flag(TLB_V6_I_PAGE))
391 asm("mcr p15, 0, %0, c8, c5, 1" : : "r" (uaddr) : "cc"); 409 asm("mcr p15, 0, %0, c8, c5, 1" : : "r" (uaddr) : "cc");
410 if (tlb_flag(TLB_V7_UIS_PAGE))
411 asm("mcr p15, 0, %0, c8, c3, 1" : : "r" (uaddr) : "cc");
392 412
393 if (tlb_flag(TLB_BTB)) { 413 if (tlb_flag(TLB_BTB)) {
394 /* flush the branch target cache */ 414 /* flush the branch target cache */
@@ -424,6 +444,8 @@ static inline void local_flush_tlb_kernel_page(unsigned long kaddr)
424 asm("mcr p15, 0, %0, c8, c6, 1" : : "r" (kaddr) : "cc"); 444 asm("mcr p15, 0, %0, c8, c6, 1" : : "r" (kaddr) : "cc");
425 if (tlb_flag(TLB_V6_I_PAGE)) 445 if (tlb_flag(TLB_V6_I_PAGE))
426 asm("mcr p15, 0, %0, c8, c5, 1" : : "r" (kaddr) : "cc"); 446 asm("mcr p15, 0, %0, c8, c5, 1" : : "r" (kaddr) : "cc");
447 if (tlb_flag(TLB_V7_UIS_PAGE))
448 asm("mcr p15, 0, %0, c8, c3, 1" : : "r" (kaddr) : "cc");
427 449
428 if (tlb_flag(TLB_BTB)) { 450 if (tlb_flag(TLB_BTB)) {
429 /* flush the branch target cache */ 451 /* flush the branch target cache */
diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c
index 6014dfd22af4..ece658e773a6 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}
diff --git a/arch/arm/mm/proc-v7.S b/arch/arm/mm/proc-v7.S
index 3397f1e64d76..c3f737516836 100644
--- a/arch/arm/mm/proc-v7.S
+++ b/arch/arm/mm/proc-v7.S
@@ -176,8 +176,8 @@ cpu_v7_name:
176 */ 176 */
177__v7_setup: 177__v7_setup:
178#ifdef CONFIG_SMP 178#ifdef CONFIG_SMP
179 mrc p15, 0, r0, c1, c0, 1 @ Enable SMP/nAMP mode 179 mrc p15, 0, r0, c1, c0, 1 @ Enable SMP/nAMP mode and
180 orr r0, r0, #(0x1 << 6) 180 orr r0, r0, #(1 << 6) | (1 << 0) @ TLB ops broadcasting
181 mcr p15, 0, r0, c1, c0, 1 181 mcr p15, 0, r0, c1, c0, 1
182#endif 182#endif
183 adr r12, __v7_setup_stack @ the local stack 183 adr r12, __v7_setup_stack @ the local stack
diff --git a/arch/arm/mm/tlb-v7.S b/arch/arm/mm/tlb-v7.S
index b637e7380ab7..a26a605b73bd 100644
--- a/arch/arm/mm/tlb-v7.S
+++ b/arch/arm/mm/tlb-v7.S
@@ -42,9 +42,11 @@ ENTRY(v7wbi_flush_user_tlb_range)
42 mov r1, r1, lsl #PAGE_SHIFT 42 mov r1, r1, lsl #PAGE_SHIFT
43 vma_vm_flags r2, r2 @ get vma->vm_flags 43 vma_vm_flags r2, r2 @ get vma->vm_flags
441: 441:
45 mcr p15, 0, r0, c8, c6, 1 @ TLB invalidate D MVA (was 1) 45#ifdef CONFIG_SMP
46 tst r2, #VM_EXEC @ Executable area ? 46 mcr p15, 0, r0, c8, c3, 1 @ TLB invalidate U MVA (shareable)
47 mcrne p15, 0, r0, c8, c5, 1 @ TLB invalidate I MVA (was 1) 47#else
48 mcr p15, 0, r0, c8, c7, 1 @ TLB invalidate U MVA
49#endif
48 add r0, r0, #PAGE_SZ 50 add r0, r0, #PAGE_SZ
49 cmp r0, r1 51 cmp r0, r1
50 blo 1b 52 blo 1b
@@ -69,8 +71,11 @@ ENTRY(v7wbi_flush_kern_tlb_range)
69 mov r0, r0, lsl #PAGE_SHIFT 71 mov r0, r0, lsl #PAGE_SHIFT
70 mov r1, r1, lsl #PAGE_SHIFT 72 mov r1, r1, lsl #PAGE_SHIFT
711: 731:
72 mcr p15, 0, r0, c8, c6, 1 @ TLB invalidate D MVA 74#ifdef CONFIG_SMP
73 mcr p15, 0, r0, c8, c5, 1 @ TLB invalidate I MVA 75 mcr p15, 0, r0, c8, c3, 1 @ TLB invalidate U MVA (shareable)
76#else
77 mcr p15, 0, r0, c8, c7, 1 @ TLB invalidate U MVA
78#endif
74 add r0, r0, #PAGE_SZ 79 add r0, r0, #PAGE_SZ
75 cmp r0, r1 80 cmp r0, r1
76 blo 1b 81 blo 1b
@@ -87,5 +92,5 @@ ENDPROC(v7wbi_flush_kern_tlb_range)
87ENTRY(v7wbi_tlb_fns) 92ENTRY(v7wbi_tlb_fns)
88 .long v7wbi_flush_user_tlb_range 93 .long v7wbi_flush_user_tlb_range
89 .long v7wbi_flush_kern_tlb_range 94 .long v7wbi_flush_kern_tlb_range
90 .long v6wbi_tlb_flags 95 .long v7wbi_tlb_flags
91 .size v7wbi_tlb_fns, . - v7wbi_tlb_fns 96 .size v7wbi_tlb_fns, . - v7wbi_tlb_fns