diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-11-11 04:19:06 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-11-11 04:19:06 -0500 |
commit | edae583a6d4d1ad2eb73981787790993fef1bbad (patch) | |
tree | c1680187bad65be2e1c4d72b25642d42d2efd394 | |
parent | 0a759b2466d19c619257fec36f988f93424cf3ae (diff) | |
parent | 737d5b980be82f722153d8104f7949e4204c5911 (diff) |
Merge tag 'arc-v3.13-rc1-part1' of git://git.kernel.org/pub/scm/linux/kernel/git/vgupta/arc
Pull ARC changes from Vineet Gupta:
- Towards a working SMP setup (ASID allocation, TLB Flush,...)
- Support for TRACE_IRQFLAGS, LOCKDEP
- cacheflush backend consolidation for I/D
- Lots of allmodconfig fixlets from Chen
- Other improvements/fixes
* tag 'arc-v3.13-rc1-part1' of git://git.kernel.org/pub/scm/linux/kernel/git/vgupta/arc: (25 commits)
ARC: [plat-arcfpga] defconfig update
smp, ARC: kill SMP single function call interrupt
ARC: [SMP] Disallow RTSC
ARC: [SMP] Fix build failures for large NR_CPUS
ARC: [SMP] enlarge possible NR_CPUS
ARC: [SMP] TLB flush
ARC: [SMP] ASID allocation
arc: export symbol for pm_power_off in reset.c
arc: export symbol for save_stack_trace() in stacktrace.c
arc: remove '__init' for get_hw_config_num_irq()
arc: remove '__init' for first_lines_of_secondary()
arc: remove '__init' for setup_processor() and arc_init_IRQ()
arc: kgdb: add default implementation for kgdb_roundup_cpus()
ARC: Fix bogus gcc warning and micro-optimise TLB iteration loop
ARC: Add support for irqflags tracing and lockdep
ARC: Reset the value of Interrupt Priority Register
ARC: Reduce #ifdef'ery for unaligned access emulation
ARC: Change calling convention of do_page_fault()
ARC: cacheflush optim - PTAG can be loop invariant if V-P is const
ARC: cacheflush refactor #3: Unify the {d,i}cache flush leaf helpers
...
28 files changed, 326 insertions, 181 deletions
diff --git a/arch/arc/Kconfig b/arch/arc/Kconfig index 91dbb2757afd..5ede5460c806 100644 --- a/arch/arc/Kconfig +++ b/arch/arc/Kconfig | |||
@@ -35,6 +35,12 @@ config ARC | |||
35 | select PERF_USE_VMALLOC | 35 | select PERF_USE_VMALLOC |
36 | select HAVE_DEBUG_STACKOVERFLOW | 36 | select HAVE_DEBUG_STACKOVERFLOW |
37 | 37 | ||
38 | config TRACE_IRQFLAGS_SUPPORT | ||
39 | def_bool y | ||
40 | |||
41 | config LOCKDEP_SUPPORT | ||
42 | def_bool y | ||
43 | |||
38 | config SCHED_OMIT_FRAME_POINTER | 44 | config SCHED_OMIT_FRAME_POINTER |
39 | def_bool y | 45 | def_bool y |
40 | 46 | ||
@@ -130,17 +136,14 @@ if SMP | |||
130 | config ARC_HAS_COH_CACHES | 136 | config ARC_HAS_COH_CACHES |
131 | def_bool n | 137 | def_bool n |
132 | 138 | ||
133 | config ARC_HAS_COH_RTSC | ||
134 | def_bool n | ||
135 | |||
136 | config ARC_HAS_REENTRANT_IRQ_LV2 | 139 | config ARC_HAS_REENTRANT_IRQ_LV2 |
137 | def_bool n | 140 | def_bool n |
138 | 141 | ||
139 | endif | 142 | endif |
140 | 143 | ||
141 | config NR_CPUS | 144 | config NR_CPUS |
142 | int "Maximum number of CPUs (2-32)" | 145 | int "Maximum number of CPUs (2-4096)" |
143 | range 2 32 | 146 | range 2 4096 |
144 | depends on SMP | 147 | depends on SMP |
145 | default "2" | 148 | default "2" |
146 | 149 | ||
@@ -326,8 +329,7 @@ config ARC_HAS_RTSC | |||
326 | bool "Insn: RTSC (64-bit r/o cycle counter)" | 329 | bool "Insn: RTSC (64-bit r/o cycle counter)" |
327 | default y | 330 | default y |
328 | depends on ARC_CPU_REL_4_10 | 331 | depends on ARC_CPU_REL_4_10 |
329 | # if SMP, enable RTSC only if counter is coherent across cores | 332 | depends on !SMP |
330 | depends on !SMP || ARC_HAS_COH_RTSC | ||
331 | 333 | ||
332 | endmenu # "ARC CPU Configuration" | 334 | endmenu # "ARC CPU Configuration" |
333 | 335 | ||
diff --git a/arch/arc/configs/fpga_defconfig b/arch/arc/configs/fpga_defconfig index 4ca50f1f8d05..e283aa586934 100644 --- a/arch/arc/configs/fpga_defconfig +++ b/arch/arc/configs/fpga_defconfig | |||
@@ -2,6 +2,8 @@ CONFIG_CROSS_COMPILE="arc-linux-uclibc-" | |||
2 | # CONFIG_LOCALVERSION_AUTO is not set | 2 | # CONFIG_LOCALVERSION_AUTO is not set |
3 | CONFIG_DEFAULT_HOSTNAME="ARCLinux" | 3 | CONFIG_DEFAULT_HOSTNAME="ARCLinux" |
4 | # CONFIG_SWAP is not set | 4 | # CONFIG_SWAP is not set |
5 | CONFIG_SYSVIPC=y | ||
6 | CONFIG_POSIX_MQUEUE=y | ||
5 | CONFIG_HIGH_RES_TIMERS=y | 7 | CONFIG_HIGH_RES_TIMERS=y |
6 | CONFIG_IKCONFIG=y | 8 | CONFIG_IKCONFIG=y |
7 | CONFIG_IKCONFIG_PROC=y | 9 | CONFIG_IKCONFIG_PROC=y |
@@ -62,4 +64,5 @@ CONFIG_TMPFS=y | |||
62 | CONFIG_NFS_FS=y | 64 | CONFIG_NFS_FS=y |
63 | # CONFIG_ENABLE_WARN_DEPRECATED is not set | 65 | # CONFIG_ENABLE_WARN_DEPRECATED is not set |
64 | # CONFIG_ENABLE_MUST_CHECK is not set | 66 | # CONFIG_ENABLE_MUST_CHECK is not set |
67 | # CONFIG_DEBUG_PREEMPT is not set | ||
65 | CONFIG_XZ_DEC=y | 68 | CONFIG_XZ_DEC=y |
diff --git a/arch/arc/include/asm/cache.h b/arch/arc/include/asm/cache.h index e4abdaac6f9f..2fd3162ec4df 100644 --- a/arch/arc/include/asm/cache.h +++ b/arch/arc/include/asm/cache.h | |||
@@ -17,13 +17,7 @@ | |||
17 | #endif | 17 | #endif |
18 | 18 | ||
19 | #define L1_CACHE_BYTES (1 << L1_CACHE_SHIFT) | 19 | #define L1_CACHE_BYTES (1 << L1_CACHE_SHIFT) |
20 | 20 | #define CACHE_LINE_MASK (~(L1_CACHE_BYTES - 1)) | |
21 | /* For a rare case where customers have differently config I/D */ | ||
22 | #define ARC_ICACHE_LINE_LEN L1_CACHE_BYTES | ||
23 | #define ARC_DCACHE_LINE_LEN L1_CACHE_BYTES | ||
24 | |||
25 | #define ICACHE_LINE_MASK (~(ARC_ICACHE_LINE_LEN - 1)) | ||
26 | #define DCACHE_LINE_MASK (~(ARC_DCACHE_LINE_LEN - 1)) | ||
27 | 21 | ||
28 | /* | 22 | /* |
29 | * ARC700 doesn't cache any access in top 256M. | 23 | * ARC700 doesn't cache any access in top 256M. |
diff --git a/arch/arc/include/asm/irq.h b/arch/arc/include/asm/irq.h index c0a72105ee0b..291a70db68b8 100644 --- a/arch/arc/include/asm/irq.h +++ b/arch/arc/include/asm/irq.h | |||
@@ -18,8 +18,8 @@ | |||
18 | 18 | ||
19 | #include <asm-generic/irq.h> | 19 | #include <asm-generic/irq.h> |
20 | 20 | ||
21 | extern void __init arc_init_IRQ(void); | 21 | extern void arc_init_IRQ(void); |
22 | extern int __init get_hw_config_num_irq(void); | 22 | extern int get_hw_config_num_irq(void); |
23 | 23 | ||
24 | void arc_local_timer_setup(unsigned int cpu); | 24 | void arc_local_timer_setup(unsigned int cpu); |
25 | 25 | ||
diff --git a/arch/arc/include/asm/irqflags.h b/arch/arc/include/asm/irqflags.h index b68b53f458d1..cb7efc29f16f 100644 --- a/arch/arc/include/asm/irqflags.h +++ b/arch/arc/include/asm/irqflags.h | |||
@@ -151,16 +151,38 @@ static inline void arch_unmask_irq(unsigned int irq) | |||
151 | 151 | ||
152 | #else | 152 | #else |
153 | 153 | ||
154 | #ifdef CONFIG_TRACE_IRQFLAGS | ||
155 | |||
156 | .macro TRACE_ASM_IRQ_DISABLE | ||
157 | bl trace_hardirqs_off | ||
158 | .endm | ||
159 | |||
160 | .macro TRACE_ASM_IRQ_ENABLE | ||
161 | bl trace_hardirqs_on | ||
162 | .endm | ||
163 | |||
164 | #else | ||
165 | |||
166 | .macro TRACE_ASM_IRQ_DISABLE | ||
167 | .endm | ||
168 | |||
169 | .macro TRACE_ASM_IRQ_ENABLE | ||
170 | .endm | ||
171 | |||
172 | #endif | ||
173 | |||
154 | .macro IRQ_DISABLE scratch | 174 | .macro IRQ_DISABLE scratch |
155 | lr \scratch, [status32] | 175 | lr \scratch, [status32] |
156 | bic \scratch, \scratch, (STATUS_E1_MASK | STATUS_E2_MASK) | 176 | bic \scratch, \scratch, (STATUS_E1_MASK | STATUS_E2_MASK) |
157 | flag \scratch | 177 | flag \scratch |
178 | TRACE_ASM_IRQ_DISABLE | ||
158 | .endm | 179 | .endm |
159 | 180 | ||
160 | .macro IRQ_ENABLE scratch | 181 | .macro IRQ_ENABLE scratch |
161 | lr \scratch, [status32] | 182 | lr \scratch, [status32] |
162 | or \scratch, \scratch, (STATUS_E1_MASK | STATUS_E2_MASK) | 183 | or \scratch, \scratch, (STATUS_E1_MASK | STATUS_E2_MASK) |
163 | flag \scratch | 184 | flag \scratch |
185 | TRACE_ASM_IRQ_ENABLE | ||
164 | .endm | 186 | .endm |
165 | 187 | ||
166 | #endif /* __ASSEMBLY__ */ | 188 | #endif /* __ASSEMBLY__ */ |
diff --git a/arch/arc/include/asm/mmu.h b/arch/arc/include/asm/mmu.h index c2663b32866b..8c84ae98c337 100644 --- a/arch/arc/include/asm/mmu.h +++ b/arch/arc/include/asm/mmu.h | |||
@@ -48,7 +48,7 @@ | |||
48 | #ifndef __ASSEMBLY__ | 48 | #ifndef __ASSEMBLY__ |
49 | 49 | ||
50 | typedef struct { | 50 | typedef struct { |
51 | unsigned long asid; /* 8 bit MMU PID + Generation cycle */ | 51 | unsigned long asid[NR_CPUS]; /* 8 bit MMU PID + Generation cycle */ |
52 | } mm_context_t; | 52 | } mm_context_t; |
53 | 53 | ||
54 | #ifdef CONFIG_ARC_DBG_TLB_PARANOIA | 54 | #ifdef CONFIG_ARC_DBG_TLB_PARANOIA |
diff --git a/arch/arc/include/asm/mmu_context.h b/arch/arc/include/asm/mmu_context.h index 43a1b51bb8cc..1fd467ef658f 100644 --- a/arch/arc/include/asm/mmu_context.h +++ b/arch/arc/include/asm/mmu_context.h | |||
@@ -30,13 +30,13 @@ | |||
30 | * "Fast Context Switch" i.e. no TLB flush on ctxt-switch | 30 | * "Fast Context Switch" i.e. no TLB flush on ctxt-switch |
31 | * | 31 | * |
32 | * Linux assigns each task a unique ASID. A simple round-robin allocation | 32 | * Linux assigns each task a unique ASID. A simple round-robin allocation |
33 | * of H/w ASID is done using software tracker @asid_cache. | 33 | * of H/w ASID is done using software tracker @asid_cpu. |
34 | * When it reaches max 255, the allocation cycle starts afresh by flushing | 34 | * When it reaches max 255, the allocation cycle starts afresh by flushing |
35 | * the entire TLB and wrapping ASID back to zero. | 35 | * the entire TLB and wrapping ASID back to zero. |
36 | * | 36 | * |
37 | * A new allocation cycle, post rollover, could potentially reassign an ASID | 37 | * A new allocation cycle, post rollover, could potentially reassign an ASID |
38 | * to a different task. Thus the rule is to refresh the ASID in a new cycle. | 38 | * to a different task. Thus the rule is to refresh the ASID in a new cycle. |
39 | * The 32 bit @asid_cache (and mm->asid) have 8 bits MMU PID and rest 24 bits | 39 | * The 32 bit @asid_cpu (and mm->asid) have 8 bits MMU PID and rest 24 bits |
40 | * serve as cycle/generation indicator and natural 32 bit unsigned math | 40 | * serve as cycle/generation indicator and natural 32 bit unsigned math |
41 | * automagically increments the generation when lower 8 bits rollover. | 41 | * automagically increments the generation when lower 8 bits rollover. |
42 | */ | 42 | */ |
@@ -47,9 +47,11 @@ | |||
47 | #define MM_CTXT_FIRST_CYCLE (MM_CTXT_ASID_MASK + 1) | 47 | #define MM_CTXT_FIRST_CYCLE (MM_CTXT_ASID_MASK + 1) |
48 | #define MM_CTXT_NO_ASID 0UL | 48 | #define MM_CTXT_NO_ASID 0UL |
49 | 49 | ||
50 | #define hw_pid(mm) (mm->context.asid & MM_CTXT_ASID_MASK) | 50 | #define asid_mm(mm, cpu) mm->context.asid[cpu] |
51 | #define hw_pid(mm, cpu) (asid_mm(mm, cpu) & MM_CTXT_ASID_MASK) | ||
51 | 52 | ||
52 | extern unsigned int asid_cache; | 53 | DECLARE_PER_CPU(unsigned int, asid_cache); |
54 | #define asid_cpu(cpu) per_cpu(asid_cache, cpu) | ||
53 | 55 | ||
54 | /* | 56 | /* |
55 | * Get a new ASID if task doesn't have a valid one (unalloc or from prev cycle) | 57 | * Get a new ASID if task doesn't have a valid one (unalloc or from prev cycle) |
@@ -57,6 +59,7 @@ extern unsigned int asid_cache; | |||
57 | */ | 59 | */ |
58 | static inline void get_new_mmu_context(struct mm_struct *mm) | 60 | static inline void get_new_mmu_context(struct mm_struct *mm) |
59 | { | 61 | { |
62 | const unsigned int cpu = smp_processor_id(); | ||
60 | unsigned long flags; | 63 | unsigned long flags; |
61 | 64 | ||
62 | local_irq_save(flags); | 65 | local_irq_save(flags); |
@@ -71,28 +74,28 @@ static inline void get_new_mmu_context(struct mm_struct *mm) | |||
71 | * first need to destroy the context, setting it to invalid | 74 | * first need to destroy the context, setting it to invalid |
72 | * value. | 75 | * value. |
73 | */ | 76 | */ |
74 | if (!((mm->context.asid ^ asid_cache) & MM_CTXT_CYCLE_MASK)) | 77 | if (!((asid_mm(mm, cpu) ^ asid_cpu(cpu)) & MM_CTXT_CYCLE_MASK)) |
75 | goto set_hw; | 78 | goto set_hw; |
76 | 79 | ||
77 | /* move to new ASID and handle rollover */ | 80 | /* move to new ASID and handle rollover */ |
78 | if (unlikely(!(++asid_cache & MM_CTXT_ASID_MASK))) { | 81 | if (unlikely(!(++asid_cpu(cpu) & MM_CTXT_ASID_MASK))) { |
79 | 82 | ||
80 | flush_tlb_all(); | 83 | local_flush_tlb_all(); |
81 | 84 | ||
82 | /* | 85 | /* |
83 | * Above checke for rollover of 8 bit ASID in 32 bit container. | 86 | * Above checke for rollover of 8 bit ASID in 32 bit container. |
84 | * If the container itself wrapped around, set it to a non zero | 87 | * If the container itself wrapped around, set it to a non zero |
85 | * "generation" to distinguish from no context | 88 | * "generation" to distinguish from no context |
86 | */ | 89 | */ |
87 | if (!asid_cache) | 90 | if (!asid_cpu(cpu)) |
88 | asid_cache = MM_CTXT_FIRST_CYCLE; | 91 | asid_cpu(cpu) = MM_CTXT_FIRST_CYCLE; |
89 | } | 92 | } |
90 | 93 | ||
91 | /* Assign new ASID to tsk */ | 94 | /* Assign new ASID to tsk */ |
92 | mm->context.asid = asid_cache; | 95 | asid_mm(mm, cpu) = asid_cpu(cpu); |
93 | 96 | ||
94 | set_hw: | 97 | set_hw: |
95 | write_aux_reg(ARC_REG_PID, hw_pid(mm) | MMU_ENABLE); | 98 | write_aux_reg(ARC_REG_PID, hw_pid(mm, cpu) | MMU_ENABLE); |
96 | 99 | ||
97 | local_irq_restore(flags); | 100 | local_irq_restore(flags); |
98 | } | 101 | } |
@@ -104,16 +107,45 @@ set_hw: | |||
104 | static inline int | 107 | static inline int |
105 | init_new_context(struct task_struct *tsk, struct mm_struct *mm) | 108 | init_new_context(struct task_struct *tsk, struct mm_struct *mm) |
106 | { | 109 | { |
107 | mm->context.asid = MM_CTXT_NO_ASID; | 110 | int i; |
111 | |||
112 | for_each_possible_cpu(i) | ||
113 | asid_mm(mm, i) = MM_CTXT_NO_ASID; | ||
114 | |||
108 | return 0; | 115 | return 0; |
109 | } | 116 | } |
110 | 117 | ||
118 | static inline void destroy_context(struct mm_struct *mm) | ||
119 | { | ||
120 | unsigned long flags; | ||
121 | |||
122 | /* Needed to elide CONFIG_DEBUG_PREEMPT warning */ | ||
123 | local_irq_save(flags); | ||
124 | asid_mm(mm, smp_processor_id()) = MM_CTXT_NO_ASID; | ||
125 | local_irq_restore(flags); | ||
126 | } | ||
127 | |||
111 | /* Prepare the MMU for task: setup PID reg with allocated ASID | 128 | /* Prepare the MMU for task: setup PID reg with allocated ASID |
112 | If task doesn't have an ASID (never alloc or stolen, get a new ASID) | 129 | If task doesn't have an ASID (never alloc or stolen, get a new ASID) |
113 | */ | 130 | */ |
114 | static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, | 131 | static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, |
115 | struct task_struct *tsk) | 132 | struct task_struct *tsk) |
116 | { | 133 | { |
134 | const int cpu = smp_processor_id(); | ||
135 | |||
136 | /* | ||
137 | * Note that the mm_cpumask is "aggregating" only, we don't clear it | ||
138 | * for the switched-out task, unlike some other arches. | ||
139 | * It is used to enlist cpus for sending TLB flush IPIs and not sending | ||
140 | * it to CPUs where a task once ran-on, could cause stale TLB entry | ||
141 | * re-use, specially for a multi-threaded task. | ||
142 | * e.g. T1 runs on C1, migrates to C3. T2 running on C2 munmaps. | ||
143 | * For a non-aggregating mm_cpumask, IPI not sent C1, and if T1 | ||
144 | * were to re-migrate to C1, it could access the unmapped region | ||
145 | * via any existing stale TLB entries. | ||
146 | */ | ||
147 | cpumask_set_cpu(cpu, mm_cpumask(next)); | ||
148 | |||
117 | #ifndef CONFIG_SMP | 149 | #ifndef CONFIG_SMP |
118 | /* PGD cached in MMU reg to avoid 3 mem lookups: task->mm->pgd */ | 150 | /* PGD cached in MMU reg to avoid 3 mem lookups: task->mm->pgd */ |
119 | write_aux_reg(ARC_REG_SCRATCH_DATA0, next->pgd); | 151 | write_aux_reg(ARC_REG_SCRATCH_DATA0, next->pgd); |
@@ -131,11 +163,6 @@ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, | |||
131 | */ | 163 | */ |
132 | #define activate_mm(prev, next) switch_mm(prev, next, NULL) | 164 | #define activate_mm(prev, next) switch_mm(prev, next, NULL) |
133 | 165 | ||
134 | static inline void destroy_context(struct mm_struct *mm) | ||
135 | { | ||
136 | mm->context.asid = MM_CTXT_NO_ASID; | ||
137 | } | ||
138 | |||
139 | /* it seemed that deactivate_mm( ) is a reasonable place to do book-keeping | 166 | /* it seemed that deactivate_mm( ) is a reasonable place to do book-keeping |
140 | * for retiring-mm. However destroy_context( ) still needs to do that because | 167 | * for retiring-mm. However destroy_context( ) still needs to do that because |
141 | * between mm_release( ) = >deactive_mm( ) and | 168 | * between mm_release( ) = >deactive_mm( ) and |
diff --git a/arch/arc/include/asm/setup.h b/arch/arc/include/asm/setup.h index 229e50681497..e10f8cef56a8 100644 --- a/arch/arc/include/asm/setup.h +++ b/arch/arc/include/asm/setup.h | |||
@@ -31,7 +31,7 @@ struct cpuinfo_data { | |||
31 | extern int root_mountflags, end_mem; | 31 | extern int root_mountflags, end_mem; |
32 | extern int running_on_hw; | 32 | extern int running_on_hw; |
33 | 33 | ||
34 | void __init setup_processor(void); | 34 | void setup_processor(void); |
35 | void __init setup_arch_memory(void); | 35 | void __init setup_arch_memory(void); |
36 | 36 | ||
37 | #endif /* __ASMARC_SETUP_H */ | 37 | #endif /* __ASMARC_SETUP_H */ |
diff --git a/arch/arc/include/asm/smp.h b/arch/arc/include/asm/smp.h index c4fb211dcd25..eefc29f08cdb 100644 --- a/arch/arc/include/asm/smp.h +++ b/arch/arc/include/asm/smp.h | |||
@@ -30,7 +30,7 @@ extern void arch_send_call_function_ipi_mask(const struct cpumask *mask); | |||
30 | * APIs provided by arch SMP code to rest of arch code | 30 | * APIs provided by arch SMP code to rest of arch code |
31 | */ | 31 | */ |
32 | extern void __init smp_init_cpus(void); | 32 | extern void __init smp_init_cpus(void); |
33 | extern void __init first_lines_of_secondary(void); | 33 | extern void first_lines_of_secondary(void); |
34 | extern const char *arc_platform_smp_cpuinfo(void); | 34 | extern const char *arc_platform_smp_cpuinfo(void); |
35 | 35 | ||
36 | /* | 36 | /* |
diff --git a/arch/arc/include/asm/tlbflush.h b/arch/arc/include/asm/tlbflush.h index b2f9bc7f68c8..71c7b2e4b874 100644 --- a/arch/arc/include/asm/tlbflush.h +++ b/arch/arc/include/asm/tlbflush.h | |||
@@ -18,11 +18,18 @@ void local_flush_tlb_kernel_range(unsigned long start, unsigned long end); | |||
18 | void local_flush_tlb_range(struct vm_area_struct *vma, | 18 | void local_flush_tlb_range(struct vm_area_struct *vma, |
19 | unsigned long start, unsigned long end); | 19 | unsigned long start, unsigned long end); |
20 | 20 | ||
21 | /* XXX: Revisit for SMP */ | 21 | #ifndef CONFIG_SMP |
22 | #define flush_tlb_range(vma, s, e) local_flush_tlb_range(vma, s, e) | 22 | #define flush_tlb_range(vma, s, e) local_flush_tlb_range(vma, s, e) |
23 | #define flush_tlb_page(vma, page) local_flush_tlb_page(vma, page) | 23 | #define flush_tlb_page(vma, page) local_flush_tlb_page(vma, page) |
24 | #define flush_tlb_kernel_range(s, e) local_flush_tlb_kernel_range(s, e) | 24 | #define flush_tlb_kernel_range(s, e) local_flush_tlb_kernel_range(s, e) |
25 | #define flush_tlb_all() local_flush_tlb_all() | 25 | #define flush_tlb_all() local_flush_tlb_all() |
26 | #define flush_tlb_mm(mm) local_flush_tlb_mm(mm) | 26 | #define flush_tlb_mm(mm) local_flush_tlb_mm(mm) |
27 | 27 | #else | |
28 | extern void flush_tlb_range(struct vm_area_struct *vma, unsigned long start, | ||
29 | unsigned long end); | ||
30 | extern void flush_tlb_page(struct vm_area_struct *vma, unsigned long page); | ||
31 | extern void flush_tlb_kernel_range(unsigned long start, unsigned long end); | ||
32 | extern void flush_tlb_all(void); | ||
33 | extern void flush_tlb_mm(struct mm_struct *mm); | ||
34 | #endif /* CONFIG_SMP */ | ||
28 | #endif | 35 | #endif |
diff --git a/arch/arc/include/asm/unaligned.h b/arch/arc/include/asm/unaligned.h index 60702f3751d2..3e5f071bc00c 100644 --- a/arch/arc/include/asm/unaligned.h +++ b/arch/arc/include/asm/unaligned.h | |||
@@ -22,7 +22,8 @@ static inline int | |||
22 | misaligned_fixup(unsigned long address, struct pt_regs *regs, | 22 | misaligned_fixup(unsigned long address, struct pt_regs *regs, |
23 | struct callee_regs *cregs) | 23 | struct callee_regs *cregs) |
24 | { | 24 | { |
25 | return 0; | 25 | /* Not fixed */ |
26 | return 1; | ||
26 | } | 27 | } |
27 | #endif | 28 | #endif |
28 | 29 | ||
diff --git a/arch/arc/kernel/ctx_sw.c b/arch/arc/kernel/ctx_sw.c index 34410eb1a308..c14a5bea0c76 100644 --- a/arch/arc/kernel/ctx_sw.c +++ b/arch/arc/kernel/ctx_sw.c | |||
@@ -17,6 +17,8 @@ | |||
17 | #include <asm/asm-offsets.h> | 17 | #include <asm/asm-offsets.h> |
18 | #include <linux/sched.h> | 18 | #include <linux/sched.h> |
19 | 19 | ||
20 | #define KSP_WORD_OFF ((TASK_THREAD + THREAD_KSP) / 4) | ||
21 | |||
20 | struct task_struct *__sched | 22 | struct task_struct *__sched |
21 | __switch_to(struct task_struct *prev_task, struct task_struct *next_task) | 23 | __switch_to(struct task_struct *prev_task, struct task_struct *next_task) |
22 | { | 24 | { |
@@ -45,7 +47,16 @@ __switch_to(struct task_struct *prev_task, struct task_struct *next_task) | |||
45 | #endif | 47 | #endif |
46 | 48 | ||
47 | /* set ksp of outgoing task in tsk->thread.ksp */ | 49 | /* set ksp of outgoing task in tsk->thread.ksp */ |
50 | #if KSP_WORD_OFF <= 255 | ||
48 | "st.as sp, [%3, %1] \n\t" | 51 | "st.as sp, [%3, %1] \n\t" |
52 | #else | ||
53 | /* | ||
54 | * Workaround for NR_CPUS=4k | ||
55 | * %1 is bigger than 255 (S9 offset for st.as) | ||
56 | */ | ||
57 | "add2 r24, %3, %1 \n\t" | ||
58 | "st sp, [r24] \n\t" | ||
59 | #endif | ||
49 | 60 | ||
50 | "sync \n\t" | 61 | "sync \n\t" |
51 | 62 | ||
@@ -97,7 +108,7 @@ __switch_to(struct task_struct *prev_task, struct task_struct *next_task) | |||
97 | /* FP/BLINK restore generated by gcc (standard func epilogue */ | 108 | /* FP/BLINK restore generated by gcc (standard func epilogue */ |
98 | 109 | ||
99 | : "=r"(tmp) | 110 | : "=r"(tmp) |
100 | : "n"((TASK_THREAD + THREAD_KSP) / 4), "r"(next), "r"(prev) | 111 | : "n"(KSP_WORD_OFF), "r"(next), "r"(prev) |
101 | : "blink" | 112 | : "blink" |
102 | ); | 113 | ); |
103 | 114 | ||
diff --git a/arch/arc/kernel/ctx_sw_asm.S b/arch/arc/kernel/ctx_sw_asm.S index d8972345e4c2..65690e7fcc8c 100644 --- a/arch/arc/kernel/ctx_sw_asm.S +++ b/arch/arc/kernel/ctx_sw_asm.S | |||
@@ -14,6 +14,8 @@ | |||
14 | #include <asm/asm-offsets.h> | 14 | #include <asm/asm-offsets.h> |
15 | #include <asm/linkage.h> | 15 | #include <asm/linkage.h> |
16 | 16 | ||
17 | #define KSP_WORD_OFF ((TASK_THREAD + THREAD_KSP) / 4) | ||
18 | |||
17 | ;################### Low Level Context Switch ########################## | 19 | ;################### Low Level Context Switch ########################## |
18 | 20 | ||
19 | .section .sched.text,"ax",@progbits | 21 | .section .sched.text,"ax",@progbits |
@@ -28,8 +30,13 @@ __switch_to: | |||
28 | SAVE_CALLEE_SAVED_KERNEL | 30 | SAVE_CALLEE_SAVED_KERNEL |
29 | 31 | ||
30 | /* Save the now KSP in task->thread.ksp */ | 32 | /* Save the now KSP in task->thread.ksp */ |
31 | st.as sp, [r0, (TASK_THREAD + THREAD_KSP)/4] | 33 | #if KSP_WORD_OFF <= 255 |
32 | 34 | st.as sp, [r0, KSP_WORD_OFF] | |
35 | #else | ||
36 | /* Workaround for NR_CPUS=4k as ST.as can only take s9 offset */ | ||
37 | add2 r24, r0, KSP_WORD_OFF | ||
38 | st sp, [r24] | ||
39 | #endif | ||
33 | /* | 40 | /* |
34 | * Return last task in r0 (return reg) | 41 | * Return last task in r0 (return reg) |
35 | * On ARC, Return reg = First Arg reg = r0. | 42 | * On ARC, Return reg = First Arg reg = r0. |
diff --git a/arch/arc/kernel/entry.S b/arch/arc/kernel/entry.S index b908dde8a331..47d09d07f093 100644 --- a/arch/arc/kernel/entry.S +++ b/arch/arc/kernel/entry.S | |||
@@ -250,6 +250,14 @@ ARC_ENTRY handle_interrupt_level1 | |||
250 | lr r0, [icause1] | 250 | lr r0, [icause1] |
251 | and r0, r0, 0x1f | 251 | and r0, r0, 0x1f |
252 | 252 | ||
253 | #ifdef CONFIG_TRACE_IRQFLAGS | ||
254 | ; icause1 needs to be read early, before calling tracing, which | ||
255 | ; can clobber scratch regs, hence use of stack to stash it | ||
256 | push r0 | ||
257 | TRACE_ASM_IRQ_DISABLE | ||
258 | pop r0 | ||
259 | #endif | ||
260 | |||
253 | bl.d @arch_do_IRQ | 261 | bl.d @arch_do_IRQ |
254 | mov r1, sp | 262 | mov r1, sp |
255 | 263 | ||
@@ -337,9 +345,9 @@ ARC_ENTRY EV_TLBProtV | |||
337 | ; vineetg: Mar 6th: Random Seg Fault issue #1 | 345 | ; vineetg: Mar 6th: Random Seg Fault issue #1 |
338 | ; ecr and efa were not saved in case an Intr sneaks in | 346 | ; ecr and efa were not saved in case an Intr sneaks in |
339 | ; after fake rtie | 347 | ; after fake rtie |
340 | ; | 348 | |
341 | lr r2, [ecr] | 349 | lr r2, [ecr] |
342 | lr r1, [efa] ; Faulting Data address | 350 | lr r0, [efa] ; Faulting Data address |
343 | 351 | ||
344 | ; --------(4) Return from CPU Exception Mode --------- | 352 | ; --------(4) Return from CPU Exception Mode --------- |
345 | ; Fake a rtie, but rtie to next label | 353 | ; Fake a rtie, but rtie to next label |
@@ -348,6 +356,8 @@ ARC_ENTRY EV_TLBProtV | |||
348 | 356 | ||
349 | FAKE_RET_FROM_EXCPN r9 | 357 | FAKE_RET_FROM_EXCPN r9 |
350 | 358 | ||
359 | mov r1, sp | ||
360 | |||
351 | ;------ (5) Type of Protection Violation? ---------- | 361 | ;------ (5) Type of Protection Violation? ---------- |
352 | ; | 362 | ; |
353 | ; ProtV Hardware Exception is triggered for Access Faults of 2 types | 363 | ; ProtV Hardware Exception is triggered for Access Faults of 2 types |
@@ -358,16 +368,12 @@ ARC_ENTRY EV_TLBProtV | |||
358 | bbit1 r2, ECR_C_BIT_PROTV_MISALIG_DATA, 4f | 368 | bbit1 r2, ECR_C_BIT_PROTV_MISALIG_DATA, 4f |
359 | 369 | ||
360 | ;========= (6a) Access Violation Processing ======== | 370 | ;========= (6a) Access Violation Processing ======== |
361 | mov r0, sp ; pt_regs | ||
362 | bl do_page_fault | 371 | bl do_page_fault |
363 | b ret_from_exception | 372 | b ret_from_exception |
364 | 373 | ||
365 | ;========== (6b) Non aligned access ============ | 374 | ;========== (6b) Non aligned access ============ |
366 | 4: | 375 | 4: |
367 | mov r0, r1 | ||
368 | mov r1, sp ; pt_regs | ||
369 | 376 | ||
370 | #ifdef CONFIG_ARC_MISALIGN_ACCESS | ||
371 | SAVE_CALLEE_SAVED_USER | 377 | SAVE_CALLEE_SAVED_USER |
372 | mov r2, sp ; callee_regs | 378 | mov r2, sp ; callee_regs |
373 | 379 | ||
@@ -376,9 +382,6 @@ ARC_ENTRY EV_TLBProtV | |||
376 | ; TBD: optimize - do this only if a callee reg was involved | 382 | ; TBD: optimize - do this only if a callee reg was involved |
377 | ; either a dst of emulated LD/ST or src with address-writeback | 383 | ; either a dst of emulated LD/ST or src with address-writeback |
378 | RESTORE_CALLEE_SAVED_USER | 384 | RESTORE_CALLEE_SAVED_USER |
379 | #else | ||
380 | bl do_misaligned_error | ||
381 | #endif | ||
382 | 385 | ||
383 | b ret_from_exception | 386 | b ret_from_exception |
384 | 387 | ||
@@ -575,6 +578,7 @@ resume_user_mode_begin: | |||
575 | ; --- (Slow Path #2) pending signal --- | 578 | ; --- (Slow Path #2) pending signal --- |
576 | mov r0, sp ; pt_regs for arg to do_signal()/do_notify_resume() | 579 | mov r0, sp ; pt_regs for arg to do_signal()/do_notify_resume() |
577 | 580 | ||
581 | GET_CURR_THR_INFO_FLAGS r9 | ||
578 | bbit0 r9, TIF_SIGPENDING, .Lchk_notify_resume | 582 | bbit0 r9, TIF_SIGPENDING, .Lchk_notify_resume |
579 | 583 | ||
580 | ; Normal Trap/IRQ entry only saves Scratch (caller-saved) regs | 584 | ; Normal Trap/IRQ entry only saves Scratch (caller-saved) regs |
@@ -640,6 +644,8 @@ resume_kernel_mode: | |||
640 | 644 | ||
641 | restore_regs : | 645 | restore_regs : |
642 | 646 | ||
647 | TRACE_ASM_IRQ_ENABLE | ||
648 | |||
643 | lr r10, [status32] | 649 | lr r10, [status32] |
644 | 650 | ||
645 | ; Restore REG File. In case multiple Events outstanding, | 651 | ; Restore REG File. In case multiple Events outstanding, |
diff --git a/arch/arc/kernel/head.S b/arch/arc/kernel/head.S index 0f944f024513..2c878e964a64 100644 --- a/arch/arc/kernel/head.S +++ b/arch/arc/kernel/head.S | |||
@@ -95,7 +95,7 @@ stext: | |||
95 | ;---------------------------------------------------------------- | 95 | ;---------------------------------------------------------------- |
96 | ; First lines of code run by secondary before jumping to 'C' | 96 | ; First lines of code run by secondary before jumping to 'C' |
97 | ;---------------------------------------------------------------- | 97 | ;---------------------------------------------------------------- |
98 | .section .init.text, "ax",@progbits | 98 | .section .text, "ax",@progbits |
99 | .type first_lines_of_secondary, @function | 99 | .type first_lines_of_secondary, @function |
100 | .globl first_lines_of_secondary | 100 | .globl first_lines_of_secondary |
101 | 101 | ||
diff --git a/arch/arc/kernel/irq.c b/arch/arc/kernel/irq.c index 5fc92455da36..a4b141ee9a6a 100644 --- a/arch/arc/kernel/irq.c +++ b/arch/arc/kernel/irq.c | |||
@@ -39,10 +39,14 @@ void arc_init_IRQ(void) | |||
39 | level_mask |= IS_ENABLED(CONFIG_ARC_IRQ5_LV2) << 5; | 39 | level_mask |= IS_ENABLED(CONFIG_ARC_IRQ5_LV2) << 5; |
40 | level_mask |= IS_ENABLED(CONFIG_ARC_IRQ6_LV2) << 6; | 40 | level_mask |= IS_ENABLED(CONFIG_ARC_IRQ6_LV2) << 6; |
41 | 41 | ||
42 | if (level_mask) { | 42 | /* |
43 | * Write to register, even if no LV2 IRQs configured to reset it | ||
44 | * in case bootloader had mucked with it | ||
45 | */ | ||
46 | write_aux_reg(AUX_IRQ_LEV, level_mask); | ||
47 | |||
48 | if (level_mask) | ||
43 | pr_info("Level-2 interrupts bitset %x\n", level_mask); | 49 | pr_info("Level-2 interrupts bitset %x\n", level_mask); |
44 | write_aux_reg(AUX_IRQ_LEV, level_mask); | ||
45 | } | ||
46 | } | 50 | } |
47 | 51 | ||
48 | /* | 52 | /* |
@@ -146,7 +150,7 @@ void arch_do_IRQ(unsigned int irq, struct pt_regs *regs) | |||
146 | set_irq_regs(old_regs); | 150 | set_irq_regs(old_regs); |
147 | } | 151 | } |
148 | 152 | ||
149 | int __init get_hw_config_num_irq(void) | 153 | int get_hw_config_num_irq(void) |
150 | { | 154 | { |
151 | uint32_t val = read_aux_reg(ARC_REG_VECBASE_BCR); | 155 | uint32_t val = read_aux_reg(ARC_REG_VECBASE_BCR); |
152 | 156 | ||
diff --git a/arch/arc/kernel/kgdb.c b/arch/arc/kernel/kgdb.c index a7698fb14818..a2ff5c5d1450 100644 --- a/arch/arc/kernel/kgdb.c +++ b/arch/arc/kernel/kgdb.c | |||
@@ -196,6 +196,18 @@ void kgdb_arch_set_pc(struct pt_regs *regs, unsigned long ip) | |||
196 | instruction_pointer(regs) = ip; | 196 | instruction_pointer(regs) = ip; |
197 | } | 197 | } |
198 | 198 | ||
199 | static void kgdb_call_nmi_hook(void *ignored) | ||
200 | { | ||
201 | kgdb_nmicallback(raw_smp_processor_id(), NULL); | ||
202 | } | ||
203 | |||
204 | void kgdb_roundup_cpus(unsigned long flags) | ||
205 | { | ||
206 | local_irq_enable(); | ||
207 | smp_call_function(kgdb_call_nmi_hook, NULL, 0); | ||
208 | local_irq_disable(); | ||
209 | } | ||
210 | |||
199 | struct kgdb_arch arch_kgdb_ops = { | 211 | struct kgdb_arch arch_kgdb_ops = { |
200 | /* breakpoint instruction: TRAP_S 0x3 */ | 212 | /* breakpoint instruction: TRAP_S 0x3 */ |
201 | #ifdef CONFIG_CPU_BIG_ENDIAN | 213 | #ifdef CONFIG_CPU_BIG_ENDIAN |
diff --git a/arch/arc/kernel/kprobes.c b/arch/arc/kernel/kprobes.c index 72f97822784a..eb1c2ee5eaf0 100644 --- a/arch/arc/kernel/kprobes.c +++ b/arch/arc/kernel/kprobes.c | |||
@@ -87,13 +87,13 @@ static void __kprobes save_previous_kprobe(struct kprobe_ctlblk *kcb) | |||
87 | 87 | ||
88 | static void __kprobes restore_previous_kprobe(struct kprobe_ctlblk *kcb) | 88 | static void __kprobes restore_previous_kprobe(struct kprobe_ctlblk *kcb) |
89 | { | 89 | { |
90 | __get_cpu_var(current_kprobe) = kcb->prev_kprobe.kp; | 90 | __this_cpu_write(current_kprobe, kcb->prev_kprobe.kp); |
91 | kcb->kprobe_status = kcb->prev_kprobe.status; | 91 | kcb->kprobe_status = kcb->prev_kprobe.status; |
92 | } | 92 | } |
93 | 93 | ||
94 | static inline void __kprobes set_current_kprobe(struct kprobe *p) | 94 | static inline void __kprobes set_current_kprobe(struct kprobe *p) |
95 | { | 95 | { |
96 | __get_cpu_var(current_kprobe) = p; | 96 | __this_cpu_write(current_kprobe, p); |
97 | } | 97 | } |
98 | 98 | ||
99 | static void __kprobes resume_execution(struct kprobe *p, unsigned long addr, | 99 | static void __kprobes resume_execution(struct kprobe *p, unsigned long addr, |
@@ -237,7 +237,7 @@ int __kprobes arc_kprobe_handler(unsigned long addr, struct pt_regs *regs) | |||
237 | 237 | ||
238 | return 1; | 238 | return 1; |
239 | } else if (kprobe_running()) { | 239 | } else if (kprobe_running()) { |
240 | p = __get_cpu_var(current_kprobe); | 240 | p = __this_cpu_read(current_kprobe); |
241 | if (p->break_handler && p->break_handler(p, regs)) { | 241 | if (p->break_handler && p->break_handler(p, regs)) { |
242 | setup_singlestep(p, regs); | 242 | setup_singlestep(p, regs); |
243 | kcb->kprobe_status = KPROBE_HIT_SS; | 243 | kcb->kprobe_status = KPROBE_HIT_SS; |
diff --git a/arch/arc/kernel/reset.c b/arch/arc/kernel/reset.c index e227a2b1c943..2768fa1e39b9 100644 --- a/arch/arc/kernel/reset.c +++ b/arch/arc/kernel/reset.c | |||
@@ -31,3 +31,4 @@ void machine_power_off(void) | |||
31 | } | 31 | } |
32 | 32 | ||
33 | void (*pm_power_off) (void) = NULL; | 33 | void (*pm_power_off) (void) = NULL; |
34 | EXPORT_SYMBOL(pm_power_off); | ||
diff --git a/arch/arc/kernel/setup.c b/arch/arc/kernel/setup.c index 2c68bc7e6a78..d9e15f16633e 100644 --- a/arch/arc/kernel/setup.c +++ b/arch/arc/kernel/setup.c | |||
@@ -37,8 +37,7 @@ struct task_struct *_current_task[NR_CPUS]; /* For stack switching */ | |||
37 | 37 | ||
38 | struct cpuinfo_arc cpuinfo_arc700[NR_CPUS]; | 38 | struct cpuinfo_arc cpuinfo_arc700[NR_CPUS]; |
39 | 39 | ||
40 | 40 | static void read_arc_build_cfg_regs(void) | |
41 | void read_arc_build_cfg_regs(void) | ||
42 | { | 41 | { |
43 | struct bcr_perip uncached_space; | 42 | struct bcr_perip uncached_space; |
44 | struct cpuinfo_arc *cpu = &cpuinfo_arc700[smp_processor_id()]; | 43 | struct cpuinfo_arc *cpu = &cpuinfo_arc700[smp_processor_id()]; |
@@ -106,7 +105,7 @@ static const struct cpuinfo_data arc_cpu_tbl[] = { | |||
106 | { {0x00, NULL } } | 105 | { {0x00, NULL } } |
107 | }; | 106 | }; |
108 | 107 | ||
109 | char *arc_cpu_mumbojumbo(int cpu_id, char *buf, int len) | 108 | static char *arc_cpu_mumbojumbo(int cpu_id, char *buf, int len) |
110 | { | 109 | { |
111 | int n = 0; | 110 | int n = 0; |
112 | struct cpuinfo_arc *cpu = &cpuinfo_arc700[cpu_id]; | 111 | struct cpuinfo_arc *cpu = &cpuinfo_arc700[cpu_id]; |
@@ -171,7 +170,7 @@ static const struct id_to_str mac_mul_nm[] = { | |||
171 | {0x6, "Dual 16x16 and 32x16"} | 170 | {0x6, "Dual 16x16 and 32x16"} |
172 | }; | 171 | }; |
173 | 172 | ||
174 | char *arc_extn_mumbojumbo(int cpu_id, char *buf, int len) | 173 | static char *arc_extn_mumbojumbo(int cpu_id, char *buf, int len) |
175 | { | 174 | { |
176 | int n = 0; | 175 | int n = 0; |
177 | struct cpuinfo_arc *cpu = &cpuinfo_arc700[cpu_id]; | 176 | struct cpuinfo_arc *cpu = &cpuinfo_arc700[cpu_id]; |
@@ -234,7 +233,7 @@ char *arc_extn_mumbojumbo(int cpu_id, char *buf, int len) | |||
234 | return buf; | 233 | return buf; |
235 | } | 234 | } |
236 | 235 | ||
237 | void arc_chk_ccms(void) | 236 | static void arc_chk_ccms(void) |
238 | { | 237 | { |
239 | #if defined(CONFIG_ARC_HAS_DCCM) || defined(CONFIG_ARC_HAS_ICCM) | 238 | #if defined(CONFIG_ARC_HAS_DCCM) || defined(CONFIG_ARC_HAS_ICCM) |
240 | struct cpuinfo_arc *cpu = &cpuinfo_arc700[smp_processor_id()]; | 239 | struct cpuinfo_arc *cpu = &cpuinfo_arc700[smp_processor_id()]; |
@@ -269,7 +268,7 @@ void arc_chk_ccms(void) | |||
269 | * hardware has dedicated regs which need to be saved/restored on ctx-sw | 268 | * hardware has dedicated regs which need to be saved/restored on ctx-sw |
270 | * (Single Precision uses core regs), thus kernel is kind of oblivious to it | 269 | * (Single Precision uses core regs), thus kernel is kind of oblivious to it |
271 | */ | 270 | */ |
272 | void arc_chk_fpu(void) | 271 | static void arc_chk_fpu(void) |
273 | { | 272 | { |
274 | struct cpuinfo_arc *cpu = &cpuinfo_arc700[smp_processor_id()]; | 273 | struct cpuinfo_arc *cpu = &cpuinfo_arc700[smp_processor_id()]; |
275 | 274 | ||
diff --git a/arch/arc/kernel/smp.c b/arch/arc/kernel/smp.c index bca3052c956d..c2f9ebbc38f6 100644 --- a/arch/arc/kernel/smp.c +++ b/arch/arc/kernel/smp.c | |||
@@ -95,7 +95,7 @@ void __init smp_cpus_done(unsigned int max_cpus) | |||
95 | * If it turns out to be elaborate, it's better to code it in assembly | 95 | * If it turns out to be elaborate, it's better to code it in assembly |
96 | * | 96 | * |
97 | */ | 97 | */ |
98 | void __attribute__((weak)) arc_platform_smp_wait_to_boot(int cpu) | 98 | void __weak arc_platform_smp_wait_to_boot(int cpu) |
99 | { | 99 | { |
100 | /* | 100 | /* |
101 | * As a hack for debugging - since debugger will single-step over the | 101 | * As a hack for debugging - since debugger will single-step over the |
@@ -128,6 +128,7 @@ void start_kernel_secondary(void) | |||
128 | atomic_inc(&mm->mm_users); | 128 | atomic_inc(&mm->mm_users); |
129 | atomic_inc(&mm->mm_count); | 129 | atomic_inc(&mm->mm_count); |
130 | current->active_mm = mm; | 130 | current->active_mm = mm; |
131 | cpumask_set_cpu(cpu, mm_cpumask(mm)); | ||
131 | 132 | ||
132 | notify_cpu_starting(cpu); | 133 | notify_cpu_starting(cpu); |
133 | set_cpu_online(cpu, true); | 134 | set_cpu_online(cpu, true); |
@@ -210,7 +211,6 @@ enum ipi_msg_type { | |||
210 | IPI_NOP = 0, | 211 | IPI_NOP = 0, |
211 | IPI_RESCHEDULE = 1, | 212 | IPI_RESCHEDULE = 1, |
212 | IPI_CALL_FUNC, | 213 | IPI_CALL_FUNC, |
213 | IPI_CALL_FUNC_SINGLE, | ||
214 | IPI_CPU_STOP | 214 | IPI_CPU_STOP |
215 | }; | 215 | }; |
216 | 216 | ||
@@ -254,7 +254,7 @@ void smp_send_stop(void) | |||
254 | 254 | ||
255 | void arch_send_call_function_single_ipi(int cpu) | 255 | void arch_send_call_function_single_ipi(int cpu) |
256 | { | 256 | { |
257 | ipi_send_msg(cpumask_of(cpu), IPI_CALL_FUNC_SINGLE); | 257 | ipi_send_msg(cpumask_of(cpu), IPI_CALL_FUNC); |
258 | } | 258 | } |
259 | 259 | ||
260 | void arch_send_call_function_ipi_mask(const struct cpumask *mask) | 260 | void arch_send_call_function_ipi_mask(const struct cpumask *mask) |
@@ -286,10 +286,6 @@ static inline void __do_IPI(unsigned long *ops, struct ipi_data *ipi, int cpu) | |||
286 | generic_smp_call_function_interrupt(); | 286 | generic_smp_call_function_interrupt(); |
287 | break; | 287 | break; |
288 | 288 | ||
289 | case IPI_CALL_FUNC_SINGLE: | ||
290 | generic_smp_call_function_single_interrupt(); | ||
291 | break; | ||
292 | |||
293 | case IPI_CPU_STOP: | 289 | case IPI_CPU_STOP: |
294 | ipi_cpu_stop(cpu); | 290 | ipi_cpu_stop(cpu); |
295 | break; | 291 | break; |
diff --git a/arch/arc/kernel/stacktrace.c b/arch/arc/kernel/stacktrace.c index f8b7d880304d..9ce47cfe2303 100644 --- a/arch/arc/kernel/stacktrace.c +++ b/arch/arc/kernel/stacktrace.c | |||
@@ -237,11 +237,14 @@ unsigned int get_wchan(struct task_struct *tsk) | |||
237 | */ | 237 | */ |
238 | void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace) | 238 | void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace) |
239 | { | 239 | { |
240 | /* Assumes @tsk is sleeping so unwinds from __switch_to */ | ||
240 | arc_unwind_core(tsk, NULL, __collect_all_but_sched, trace); | 241 | arc_unwind_core(tsk, NULL, __collect_all_but_sched, trace); |
241 | } | 242 | } |
242 | 243 | ||
243 | void save_stack_trace(struct stack_trace *trace) | 244 | void save_stack_trace(struct stack_trace *trace) |
244 | { | 245 | { |
245 | arc_unwind_core(current, NULL, __collect_all, trace); | 246 | /* Pass NULL for task so it unwinds the current call frame */ |
247 | arc_unwind_core(NULL, NULL, __collect_all, trace); | ||
246 | } | 248 | } |
249 | EXPORT_SYMBOL_GPL(save_stack_trace); | ||
247 | #endif | 250 | #endif |
diff --git a/arch/arc/kernel/time.c b/arch/arc/kernel/time.c index 3fde7de3ea67..e5f3a837fb35 100644 --- a/arch/arc/kernel/time.c +++ b/arch/arc/kernel/time.c | |||
@@ -63,9 +63,10 @@ | |||
63 | 63 | ||
64 | int arc_counter_setup(void) | 64 | int arc_counter_setup(void) |
65 | { | 65 | { |
66 | /* RTSC insn taps into cpu clk, needs no setup */ | 66 | /* |
67 | 67 | * For SMP this needs to be 0. However Kconfig glue doesn't | |
68 | /* For SMP, only allowed if cross-core-sync, hence usable as cs */ | 68 | * enable this option for SMP configs |
69 | */ | ||
69 | return 1; | 70 | return 1; |
70 | } | 71 | } |
71 | 72 | ||
@@ -206,7 +207,7 @@ static DEFINE_PER_CPU(struct clock_event_device, arc_clockevent_device) = { | |||
206 | 207 | ||
207 | static irqreturn_t timer_irq_handler(int irq, void *dev_id) | 208 | static irqreturn_t timer_irq_handler(int irq, void *dev_id) |
208 | { | 209 | { |
209 | struct clock_event_device *clk = &__get_cpu_var(arc_clockevent_device); | 210 | struct clock_event_device *clk = this_cpu_ptr(&arc_clockevent_device); |
210 | 211 | ||
211 | arc_timer_event_ack(clk->mode == CLOCK_EVT_MODE_PERIODIC); | 212 | arc_timer_event_ack(clk->mode == CLOCK_EVT_MODE_PERIODIC); |
212 | clk->event_handler(clk); | 213 | clk->event_handler(clk); |
@@ -223,7 +224,7 @@ static struct irqaction arc_timer_irq = { | |||
223 | * Setup the local event timer for @cpu | 224 | * Setup the local event timer for @cpu |
224 | * N.B. weak so that some exotic ARC SoCs can completely override it | 225 | * N.B. weak so that some exotic ARC SoCs can completely override it |
225 | */ | 226 | */ |
226 | void __attribute__((weak)) arc_local_timer_setup(unsigned int cpu) | 227 | void __weak arc_local_timer_setup(unsigned int cpu) |
227 | { | 228 | { |
228 | struct clock_event_device *clk = &per_cpu(arc_clockevent_device, cpu); | 229 | struct clock_event_device *clk = &per_cpu(arc_clockevent_device, cpu); |
229 | 230 | ||
diff --git a/arch/arc/kernel/traps.c b/arch/arc/kernel/traps.c index e21692d2fdab..3eadfdabc322 100644 --- a/arch/arc/kernel/traps.c +++ b/arch/arc/kernel/traps.c | |||
@@ -84,19 +84,18 @@ DO_ERROR_INFO(SIGBUS, "Invalid Mem Access", do_memory_error, BUS_ADRERR) | |||
84 | DO_ERROR_INFO(SIGTRAP, "Breakpoint Set", trap_is_brkpt, TRAP_BRKPT) | 84 | DO_ERROR_INFO(SIGTRAP, "Breakpoint Set", trap_is_brkpt, TRAP_BRKPT) |
85 | DO_ERROR_INFO(SIGBUS, "Misaligned Access", do_misaligned_error, BUS_ADRALN) | 85 | DO_ERROR_INFO(SIGBUS, "Misaligned Access", do_misaligned_error, BUS_ADRALN) |
86 | 86 | ||
87 | #ifdef CONFIG_ARC_MISALIGN_ACCESS | ||
88 | /* | 87 | /* |
89 | * Entry Point for Misaligned Data access Exception, for emulating in software | 88 | * Entry Point for Misaligned Data access Exception, for emulating in software |
90 | */ | 89 | */ |
91 | int do_misaligned_access(unsigned long address, struct pt_regs *regs, | 90 | int do_misaligned_access(unsigned long address, struct pt_regs *regs, |
92 | struct callee_regs *cregs) | 91 | struct callee_regs *cregs) |
93 | { | 92 | { |
93 | /* If emulation not enabled, or failed, kill the task */ | ||
94 | if (misaligned_fixup(address, regs, cregs) != 0) | 94 | if (misaligned_fixup(address, regs, cregs) != 0) |
95 | return do_misaligned_error(address, regs); | 95 | return do_misaligned_error(address, regs); |
96 | 96 | ||
97 | return 0; | 97 | return 0; |
98 | } | 98 | } |
99 | #endif | ||
100 | 99 | ||
101 | /* | 100 | /* |
102 | * Entry point for miscll errors such as Nested Exceptions | 101 | * Entry point for miscll errors such as Nested Exceptions |
diff --git a/arch/arc/mm/cache_arc700.c b/arch/arc/mm/cache_arc700.c index 5a1259cd948c..6b58c1de7577 100644 --- a/arch/arc/mm/cache_arc700.c +++ b/arch/arc/mm/cache_arc700.c | |||
@@ -182,7 +182,7 @@ void arc_cache_init(void) | |||
182 | 182 | ||
183 | #ifdef CONFIG_ARC_HAS_ICACHE | 183 | #ifdef CONFIG_ARC_HAS_ICACHE |
184 | /* 1. Confirm some of I-cache params which Linux assumes */ | 184 | /* 1. Confirm some of I-cache params which Linux assumes */ |
185 | if (ic->line_len != ARC_ICACHE_LINE_LEN) | 185 | if (ic->line_len != L1_CACHE_BYTES) |
186 | panic("Cache H/W doesn't match kernel Config"); | 186 | panic("Cache H/W doesn't match kernel Config"); |
187 | 187 | ||
188 | if (ic->ver != CONFIG_ARC_MMU_VER) | 188 | if (ic->ver != CONFIG_ARC_MMU_VER) |
@@ -205,7 +205,7 @@ chk_dc: | |||
205 | return; | 205 | return; |
206 | 206 | ||
207 | #ifdef CONFIG_ARC_HAS_DCACHE | 207 | #ifdef CONFIG_ARC_HAS_DCACHE |
208 | if (dc->line_len != ARC_DCACHE_LINE_LEN) | 208 | if (dc->line_len != L1_CACHE_BYTES) |
209 | panic("Cache H/W doesn't match kernel Config"); | 209 | panic("Cache H/W doesn't match kernel Config"); |
210 | 210 | ||
211 | /* check for D-Cache aliasing */ | 211 | /* check for D-Cache aliasing */ |
@@ -240,6 +240,67 @@ chk_dc: | |||
240 | #define OP_INV 0x1 | 240 | #define OP_INV 0x1 |
241 | #define OP_FLUSH 0x2 | 241 | #define OP_FLUSH 0x2 |
242 | #define OP_FLUSH_N_INV 0x3 | 242 | #define OP_FLUSH_N_INV 0x3 |
243 | #define OP_INV_IC 0x4 | ||
244 | |||
245 | /* | ||
246 | * Common Helper for Line Operations on {I,D}-Cache | ||
247 | */ | ||
248 | static inline void __cache_line_loop(unsigned long paddr, unsigned long vaddr, | ||
249 | unsigned long sz, const int cacheop) | ||
250 | { | ||
251 | unsigned int aux_cmd, aux_tag; | ||
252 | int num_lines; | ||
253 | const int full_page_op = __builtin_constant_p(sz) && sz == PAGE_SIZE; | ||
254 | |||
255 | if (cacheop == OP_INV_IC) { | ||
256 | aux_cmd = ARC_REG_IC_IVIL; | ||
257 | aux_tag = ARC_REG_IC_PTAG; | ||
258 | } | ||
259 | else { | ||
260 | /* d$ cmd: INV (discard or wback-n-discard) OR FLUSH (wback) */ | ||
261 | aux_cmd = cacheop & OP_INV ? ARC_REG_DC_IVDL : ARC_REG_DC_FLDL; | ||
262 | aux_tag = ARC_REG_DC_PTAG; | ||
263 | } | ||
264 | |||
265 | /* Ensure we properly floor/ceil the non-line aligned/sized requests | ||
266 | * and have @paddr - aligned to cache line and integral @num_lines. | ||
267 | * This however can be avoided for page sized since: | ||
268 | * -@paddr will be cache-line aligned already (being page aligned) | ||
269 | * -@sz will be integral multiple of line size (being page sized). | ||
270 | */ | ||
271 | if (!full_page_op) { | ||
272 | sz += paddr & ~CACHE_LINE_MASK; | ||
273 | paddr &= CACHE_LINE_MASK; | ||
274 | vaddr &= CACHE_LINE_MASK; | ||
275 | } | ||
276 | |||
277 | num_lines = DIV_ROUND_UP(sz, L1_CACHE_BYTES); | ||
278 | |||
279 | #if (CONFIG_ARC_MMU_VER <= 2) | ||
280 | /* MMUv2 and before: paddr contains stuffed vaddrs bits */ | ||
281 | paddr |= (vaddr >> PAGE_SHIFT) & 0x1F; | ||
282 | #else | ||
283 | /* if V-P const for loop, PTAG can be written once outside loop */ | ||
284 | if (full_page_op) | ||
285 | write_aux_reg(ARC_REG_DC_PTAG, paddr); | ||
286 | #endif | ||
287 | |||
288 | while (num_lines-- > 0) { | ||
289 | #if (CONFIG_ARC_MMU_VER > 2) | ||
290 | /* MMUv3, cache ops require paddr seperately */ | ||
291 | if (!full_page_op) { | ||
292 | write_aux_reg(aux_tag, paddr); | ||
293 | paddr += L1_CACHE_BYTES; | ||
294 | } | ||
295 | |||
296 | write_aux_reg(aux_cmd, vaddr); | ||
297 | vaddr += L1_CACHE_BYTES; | ||
298 | #else | ||
299 | write_aux_reg(aux, paddr); | ||
300 | paddr += L1_CACHE_BYTES; | ||
301 | #endif | ||
302 | } | ||
303 | } | ||
243 | 304 | ||
244 | #ifdef CONFIG_ARC_HAS_DCACHE | 305 | #ifdef CONFIG_ARC_HAS_DCACHE |
245 | 306 | ||
@@ -289,53 +350,6 @@ static inline void __dc_entire_op(const int cacheop) | |||
289 | write_aux_reg(ARC_REG_DC_CTRL, tmp & ~DC_CTRL_INV_MODE_FLUSH); | 350 | write_aux_reg(ARC_REG_DC_CTRL, tmp & ~DC_CTRL_INV_MODE_FLUSH); |
290 | } | 351 | } |
291 | 352 | ||
292 | /* | ||
293 | * Per Line Operation on D-Cache | ||
294 | * Doesn't deal with type-of-op/IRQ-disabling/waiting-for-flush-to-complete | ||
295 | * It's sole purpose is to help gcc generate ZOL | ||
296 | * (aliasing VIPT dcache flushing needs both vaddr and paddr) | ||
297 | */ | ||
298 | static inline void __dc_line_loop(unsigned long paddr, unsigned long vaddr, | ||
299 | unsigned long sz, const int aux_reg) | ||
300 | { | ||
301 | int num_lines; | ||
302 | |||
303 | /* Ensure we properly floor/ceil the non-line aligned/sized requests | ||
304 | * and have @paddr - aligned to cache line and integral @num_lines. | ||
305 | * This however can be avoided for page sized since: | ||
306 | * -@paddr will be cache-line aligned already (being page aligned) | ||
307 | * -@sz will be integral multiple of line size (being page sized). | ||
308 | */ | ||
309 | if (!(__builtin_constant_p(sz) && sz == PAGE_SIZE)) { | ||
310 | sz += paddr & ~DCACHE_LINE_MASK; | ||
311 | paddr &= DCACHE_LINE_MASK; | ||
312 | vaddr &= DCACHE_LINE_MASK; | ||
313 | } | ||
314 | |||
315 | num_lines = DIV_ROUND_UP(sz, ARC_DCACHE_LINE_LEN); | ||
316 | |||
317 | #if (CONFIG_ARC_MMU_VER <= 2) | ||
318 | paddr |= (vaddr >> PAGE_SHIFT) & 0x1F; | ||
319 | #endif | ||
320 | |||
321 | while (num_lines-- > 0) { | ||
322 | #if (CONFIG_ARC_MMU_VER > 2) | ||
323 | /* | ||
324 | * Just as for I$, in MMU v3, D$ ops also require | ||
325 | * "tag" bits in DC_PTAG, "index" bits in FLDL,IVDL ops | ||
326 | */ | ||
327 | write_aux_reg(ARC_REG_DC_PTAG, paddr); | ||
328 | |||
329 | write_aux_reg(aux_reg, vaddr); | ||
330 | vaddr += ARC_DCACHE_LINE_LEN; | ||
331 | #else | ||
332 | /* paddr contains stuffed vaddrs bits */ | ||
333 | write_aux_reg(aux_reg, paddr); | ||
334 | #endif | ||
335 | paddr += ARC_DCACHE_LINE_LEN; | ||
336 | } | ||
337 | } | ||
338 | |||
339 | /* For kernel mappings cache operation: index is same as paddr */ | 353 | /* For kernel mappings cache operation: index is same as paddr */ |
340 | #define __dc_line_op_k(p, sz, op) __dc_line_op(p, p, sz, op) | 354 | #define __dc_line_op_k(p, sz, op) __dc_line_op(p, p, sz, op) |
341 | 355 | ||
@@ -346,7 +360,6 @@ static inline void __dc_line_op(unsigned long paddr, unsigned long vaddr, | |||
346 | unsigned long sz, const int cacheop) | 360 | unsigned long sz, const int cacheop) |
347 | { | 361 | { |
348 | unsigned long flags, tmp = tmp; | 362 | unsigned long flags, tmp = tmp; |
349 | int aux; | ||
350 | 363 | ||
351 | local_irq_save(flags); | 364 | local_irq_save(flags); |
352 | 365 | ||
@@ -361,12 +374,7 @@ static inline void __dc_line_op(unsigned long paddr, unsigned long vaddr, | |||
361 | write_aux_reg(ARC_REG_DC_CTRL, tmp | DC_CTRL_INV_MODE_FLUSH); | 374 | write_aux_reg(ARC_REG_DC_CTRL, tmp | DC_CTRL_INV_MODE_FLUSH); |
362 | } | 375 | } |
363 | 376 | ||
364 | if (cacheop & OP_INV) /* Inv / flush-n-inv use same cmd reg */ | 377 | __cache_line_loop(paddr, vaddr, sz, cacheop); |
365 | aux = ARC_REG_DC_IVDL; | ||
366 | else | ||
367 | aux = ARC_REG_DC_FLDL; | ||
368 | |||
369 | __dc_line_loop(paddr, vaddr, sz, aux); | ||
370 | 378 | ||
371 | if (cacheop & OP_FLUSH) /* flush / flush-n-inv both wait */ | 379 | if (cacheop & OP_FLUSH) /* flush / flush-n-inv both wait */ |
372 | wait_for_flush(); | 380 | wait_for_flush(); |
@@ -438,42 +446,9 @@ static void __ic_line_inv_vaddr(unsigned long paddr, unsigned long vaddr, | |||
438 | unsigned long sz) | 446 | unsigned long sz) |
439 | { | 447 | { |
440 | unsigned long flags; | 448 | unsigned long flags; |
441 | int num_lines; | ||
442 | |||
443 | /* | ||
444 | * Ensure we properly floor/ceil the non-line aligned/sized requests: | ||
445 | * However page sized flushes can be compile time optimised. | ||
446 | * -@paddr will be cache-line aligned already (being page aligned) | ||
447 | * -@sz will be integral multiple of line size (being page sized). | ||
448 | */ | ||
449 | if (!(__builtin_constant_p(sz) && sz == PAGE_SIZE)) { | ||
450 | sz += paddr & ~ICACHE_LINE_MASK; | ||
451 | paddr &= ICACHE_LINE_MASK; | ||
452 | vaddr &= ICACHE_LINE_MASK; | ||
453 | } | ||
454 | |||
455 | num_lines = DIV_ROUND_UP(sz, ARC_ICACHE_LINE_LEN); | ||
456 | |||
457 | #if (CONFIG_ARC_MMU_VER <= 2) | ||
458 | /* bits 17:13 of vaddr go as bits 4:0 of paddr */ | ||
459 | paddr |= (vaddr >> PAGE_SHIFT) & 0x1F; | ||
460 | #endif | ||
461 | 449 | ||
462 | local_irq_save(flags); | 450 | local_irq_save(flags); |
463 | while (num_lines-- > 0) { | 451 | __cache_line_loop(paddr, vaddr, sz, OP_INV_IC); |
464 | #if (CONFIG_ARC_MMU_VER > 2) | ||
465 | /* tag comes from phy addr */ | ||
466 | write_aux_reg(ARC_REG_IC_PTAG, paddr); | ||
467 | |||
468 | /* index bits come from vaddr */ | ||
469 | write_aux_reg(ARC_REG_IC_IVIL, vaddr); | ||
470 | vaddr += ARC_ICACHE_LINE_LEN; | ||
471 | #else | ||
472 | /* paddr contains stuffed vaddrs bits */ | ||
473 | write_aux_reg(ARC_REG_IC_IVIL, paddr); | ||
474 | #endif | ||
475 | paddr += ARC_ICACHE_LINE_LEN; | ||
476 | } | ||
477 | local_irq_restore(flags); | 452 | local_irq_restore(flags); |
478 | } | 453 | } |
479 | 454 | ||
diff --git a/arch/arc/mm/fault.c b/arch/arc/mm/fault.c index 0c14d8a52683..9c69552350c4 100644 --- a/arch/arc/mm/fault.c +++ b/arch/arc/mm/fault.c | |||
@@ -52,7 +52,7 @@ bad_area: | |||
52 | return 1; | 52 | return 1; |
53 | } | 53 | } |
54 | 54 | ||
55 | void do_page_fault(struct pt_regs *regs, unsigned long address) | 55 | void do_page_fault(unsigned long address, struct pt_regs *regs) |
56 | { | 56 | { |
57 | struct vm_area_struct *vma = NULL; | 57 | struct vm_area_struct *vma = NULL; |
58 | struct task_struct *tsk = current; | 58 | struct task_struct *tsk = current; |
diff --git a/arch/arc/mm/tlb.c b/arch/arc/mm/tlb.c index 71cb26df4255..e1acf0ce5647 100644 --- a/arch/arc/mm/tlb.c +++ b/arch/arc/mm/tlb.c | |||
@@ -100,7 +100,7 @@ | |||
100 | 100 | ||
101 | 101 | ||
102 | /* A copy of the ASID from the PID reg is kept in asid_cache */ | 102 | /* A copy of the ASID from the PID reg is kept in asid_cache */ |
103 | unsigned int asid_cache = MM_CTXT_FIRST_CYCLE; | 103 | DEFINE_PER_CPU(unsigned int, asid_cache) = MM_CTXT_FIRST_CYCLE; |
104 | 104 | ||
105 | /* | 105 | /* |
106 | * Utility Routine to erase a J-TLB entry | 106 | * Utility Routine to erase a J-TLB entry |
@@ -274,6 +274,7 @@ noinline void local_flush_tlb_mm(struct mm_struct *mm) | |||
274 | void local_flush_tlb_range(struct vm_area_struct *vma, unsigned long start, | 274 | void local_flush_tlb_range(struct vm_area_struct *vma, unsigned long start, |
275 | unsigned long end) | 275 | unsigned long end) |
276 | { | 276 | { |
277 | const unsigned int cpu = smp_processor_id(); | ||
277 | unsigned long flags; | 278 | unsigned long flags; |
278 | 279 | ||
279 | /* If range @start to @end is more than 32 TLB entries deep, | 280 | /* If range @start to @end is more than 32 TLB entries deep, |
@@ -297,9 +298,9 @@ void local_flush_tlb_range(struct vm_area_struct *vma, unsigned long start, | |||
297 | 298 | ||
298 | local_irq_save(flags); | 299 | local_irq_save(flags); |
299 | 300 | ||
300 | if (vma->vm_mm->context.asid != MM_CTXT_NO_ASID) { | 301 | if (asid_mm(vma->vm_mm, cpu) != MM_CTXT_NO_ASID) { |
301 | while (start < end) { | 302 | while (start < end) { |
302 | tlb_entry_erase(start | hw_pid(vma->vm_mm)); | 303 | tlb_entry_erase(start | hw_pid(vma->vm_mm, cpu)); |
303 | start += PAGE_SIZE; | 304 | start += PAGE_SIZE; |
304 | } | 305 | } |
305 | } | 306 | } |
@@ -346,6 +347,7 @@ void local_flush_tlb_kernel_range(unsigned long start, unsigned long end) | |||
346 | 347 | ||
347 | void local_flush_tlb_page(struct vm_area_struct *vma, unsigned long page) | 348 | void local_flush_tlb_page(struct vm_area_struct *vma, unsigned long page) |
348 | { | 349 | { |
350 | const unsigned int cpu = smp_processor_id(); | ||
349 | unsigned long flags; | 351 | unsigned long flags; |
350 | 352 | ||
351 | /* Note that it is critical that interrupts are DISABLED between | 353 | /* Note that it is critical that interrupts are DISABLED between |
@@ -353,14 +355,87 @@ void local_flush_tlb_page(struct vm_area_struct *vma, unsigned long page) | |||
353 | */ | 355 | */ |
354 | local_irq_save(flags); | 356 | local_irq_save(flags); |
355 | 357 | ||
356 | if (vma->vm_mm->context.asid != MM_CTXT_NO_ASID) { | 358 | if (asid_mm(vma->vm_mm, cpu) != MM_CTXT_NO_ASID) { |
357 | tlb_entry_erase((page & PAGE_MASK) | hw_pid(vma->vm_mm)); | 359 | tlb_entry_erase((page & PAGE_MASK) | hw_pid(vma->vm_mm, cpu)); |
358 | utlb_invalidate(); | 360 | utlb_invalidate(); |
359 | } | 361 | } |
360 | 362 | ||
361 | local_irq_restore(flags); | 363 | local_irq_restore(flags); |
362 | } | 364 | } |
363 | 365 | ||
366 | #ifdef CONFIG_SMP | ||
367 | |||
368 | struct tlb_args { | ||
369 | struct vm_area_struct *ta_vma; | ||
370 | unsigned long ta_start; | ||
371 | unsigned long ta_end; | ||
372 | }; | ||
373 | |||
374 | static inline void ipi_flush_tlb_page(void *arg) | ||
375 | { | ||
376 | struct tlb_args *ta = arg; | ||
377 | |||
378 | local_flush_tlb_page(ta->ta_vma, ta->ta_start); | ||
379 | } | ||
380 | |||
381 | static inline void ipi_flush_tlb_range(void *arg) | ||
382 | { | ||
383 | struct tlb_args *ta = arg; | ||
384 | |||
385 | local_flush_tlb_range(ta->ta_vma, ta->ta_start, ta->ta_end); | ||
386 | } | ||
387 | |||
388 | static inline void ipi_flush_tlb_kernel_range(void *arg) | ||
389 | { | ||
390 | struct tlb_args *ta = (struct tlb_args *)arg; | ||
391 | |||
392 | local_flush_tlb_kernel_range(ta->ta_start, ta->ta_end); | ||
393 | } | ||
394 | |||
395 | void flush_tlb_all(void) | ||
396 | { | ||
397 | on_each_cpu((smp_call_func_t)local_flush_tlb_all, NULL, 1); | ||
398 | } | ||
399 | |||
400 | void flush_tlb_mm(struct mm_struct *mm) | ||
401 | { | ||
402 | on_each_cpu_mask(mm_cpumask(mm), (smp_call_func_t)local_flush_tlb_mm, | ||
403 | mm, 1); | ||
404 | } | ||
405 | |||
406 | void flush_tlb_page(struct vm_area_struct *vma, unsigned long uaddr) | ||
407 | { | ||
408 | struct tlb_args ta = { | ||
409 | .ta_vma = vma, | ||
410 | .ta_start = uaddr | ||
411 | }; | ||
412 | |||
413 | on_each_cpu_mask(mm_cpumask(vma->vm_mm), ipi_flush_tlb_page, &ta, 1); | ||
414 | } | ||
415 | |||
416 | void flush_tlb_range(struct vm_area_struct *vma, unsigned long start, | ||
417 | unsigned long end) | ||
418 | { | ||
419 | struct tlb_args ta = { | ||
420 | .ta_vma = vma, | ||
421 | .ta_start = start, | ||
422 | .ta_end = end | ||
423 | }; | ||
424 | |||
425 | on_each_cpu_mask(mm_cpumask(vma->vm_mm), ipi_flush_tlb_range, &ta, 1); | ||
426 | } | ||
427 | |||
428 | void flush_tlb_kernel_range(unsigned long start, unsigned long end) | ||
429 | { | ||
430 | struct tlb_args ta = { | ||
431 | .ta_start = start, | ||
432 | .ta_end = end | ||
433 | }; | ||
434 | |||
435 | on_each_cpu(ipi_flush_tlb_kernel_range, &ta, 1); | ||
436 | } | ||
437 | #endif | ||
438 | |||
364 | /* | 439 | /* |
365 | * Routine to create a TLB entry | 440 | * Routine to create a TLB entry |
366 | */ | 441 | */ |
@@ -400,7 +475,7 @@ void create_tlb(struct vm_area_struct *vma, unsigned long address, pte_t *ptep) | |||
400 | 475 | ||
401 | local_irq_save(flags); | 476 | local_irq_save(flags); |
402 | 477 | ||
403 | tlb_paranoid_check(vma->vm_mm->context.asid, address); | 478 | tlb_paranoid_check(asid_mm(vma->vm_mm, smp_processor_id()), address); |
404 | 479 | ||
405 | address &= PAGE_MASK; | 480 | address &= PAGE_MASK; |
406 | 481 | ||
@@ -610,9 +685,9 @@ void do_tlb_overlap_fault(unsigned long cause, unsigned long address, | |||
610 | struct pt_regs *regs) | 685 | struct pt_regs *regs) |
611 | { | 686 | { |
612 | int set, way, n; | 687 | int set, way, n; |
613 | unsigned int pd0[4], pd1[4]; /* assume max 4 ways */ | ||
614 | unsigned long flags, is_valid; | 688 | unsigned long flags, is_valid; |
615 | struct cpuinfo_arc_mmu *mmu = &cpuinfo_arc700[smp_processor_id()].mmu; | 689 | struct cpuinfo_arc_mmu *mmu = &cpuinfo_arc700[smp_processor_id()].mmu; |
690 | unsigned int pd0[mmu->ways], pd1[mmu->ways]; | ||
616 | 691 | ||
617 | local_irq_save(flags); | 692 | local_irq_save(flags); |
618 | 693 | ||
@@ -637,7 +712,7 @@ void do_tlb_overlap_fault(unsigned long cause, unsigned long address, | |||
637 | continue; | 712 | continue; |
638 | 713 | ||
639 | /* Scan the set for duplicate ways: needs a nested loop */ | 714 | /* Scan the set for duplicate ways: needs a nested loop */ |
640 | for (way = 0; way < mmu->ways; way++) { | 715 | for (way = 0; way < mmu->ways - 1; way++) { |
641 | if (!pd0[way]) | 716 | if (!pd0[way]) |
642 | continue; | 717 | continue; |
643 | 718 | ||
diff --git a/arch/arc/mm/tlbex.S b/arch/arc/mm/tlbex.S index cf7d7d9ad695..3fcfdb38d242 100644 --- a/arch/arc/mm/tlbex.S +++ b/arch/arc/mm/tlbex.S | |||
@@ -369,8 +369,8 @@ do_slow_path_pf: | |||
369 | EXCEPTION_PROLOGUE | 369 | EXCEPTION_PROLOGUE |
370 | 370 | ||
371 | ; ------- setup args for Linux Page fault Hanlder --------- | 371 | ; ------- setup args for Linux Page fault Hanlder --------- |
372 | mov_s r0, sp | 372 | mov_s r1, sp |
373 | lr r1, [efa] | 373 | lr r0, [efa] |
374 | 374 | ||
375 | ; We don't want exceptions to be disabled while the fault is handled. | 375 | ; We don't want exceptions to be disabled while the fault is handled. |
376 | ; Now that we have saved the context we return from exception hence | 376 | ; Now that we have saved the context we return from exception hence |