aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2013-11-11 04:19:06 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2013-11-11 04:19:06 -0500
commitedae583a6d4d1ad2eb73981787790993fef1bbad (patch)
treec1680187bad65be2e1c4d72b25642d42d2efd394
parent0a759b2466d19c619257fec36f988f93424cf3ae (diff)
parent737d5b980be82f722153d8104f7949e4204c5911 (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 ...
-rw-r--r--arch/arc/Kconfig16
-rw-r--r--arch/arc/configs/fpga_defconfig3
-rw-r--r--arch/arc/include/asm/cache.h8
-rw-r--r--arch/arc/include/asm/irq.h4
-rw-r--r--arch/arc/include/asm/irqflags.h22
-rw-r--r--arch/arc/include/asm/mmu.h2
-rw-r--r--arch/arc/include/asm/mmu_context.h61
-rw-r--r--arch/arc/include/asm/setup.h2
-rw-r--r--arch/arc/include/asm/smp.h2
-rw-r--r--arch/arc/include/asm/tlbflush.h11
-rw-r--r--arch/arc/include/asm/unaligned.h3
-rw-r--r--arch/arc/kernel/ctx_sw.c13
-rw-r--r--arch/arc/kernel/ctx_sw_asm.S11
-rw-r--r--arch/arc/kernel/entry.S24
-rw-r--r--arch/arc/kernel/head.S2
-rw-r--r--arch/arc/kernel/irq.c12
-rw-r--r--arch/arc/kernel/kgdb.c12
-rw-r--r--arch/arc/kernel/kprobes.c6
-rw-r--r--arch/arc/kernel/reset.c1
-rw-r--r--arch/arc/kernel/setup.c11
-rw-r--r--arch/arc/kernel/smp.c10
-rw-r--r--arch/arc/kernel/stacktrace.c5
-rw-r--r--arch/arc/kernel/time.c11
-rw-r--r--arch/arc/kernel/traps.c3
-rw-r--r--arch/arc/mm/cache_arc700.c155
-rw-r--r--arch/arc/mm/fault.c2
-rw-r--r--arch/arc/mm/tlb.c91
-rw-r--r--arch/arc/mm/tlbex.S4
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
38config TRACE_IRQFLAGS_SUPPORT
39 def_bool y
40
41config LOCKDEP_SUPPORT
42 def_bool y
43
38config SCHED_OMIT_FRAME_POINTER 44config SCHED_OMIT_FRAME_POINTER
39 def_bool y 45 def_bool y
40 46
@@ -130,17 +136,14 @@ if SMP
130config ARC_HAS_COH_CACHES 136config ARC_HAS_COH_CACHES
131 def_bool n 137 def_bool n
132 138
133config ARC_HAS_COH_RTSC
134 def_bool n
135
136config ARC_HAS_REENTRANT_IRQ_LV2 139config ARC_HAS_REENTRANT_IRQ_LV2
137 def_bool n 140 def_bool n
138 141
139endif 142endif
140 143
141config NR_CPUS 144config 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
332endmenu # "ARC CPU Configuration" 334endmenu # "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
3CONFIG_DEFAULT_HOSTNAME="ARCLinux" 3CONFIG_DEFAULT_HOSTNAME="ARCLinux"
4# CONFIG_SWAP is not set 4# CONFIG_SWAP is not set
5CONFIG_SYSVIPC=y
6CONFIG_POSIX_MQUEUE=y
5CONFIG_HIGH_RES_TIMERS=y 7CONFIG_HIGH_RES_TIMERS=y
6CONFIG_IKCONFIG=y 8CONFIG_IKCONFIG=y
7CONFIG_IKCONFIG_PROC=y 9CONFIG_IKCONFIG_PROC=y
@@ -62,4 +64,5 @@ CONFIG_TMPFS=y
62CONFIG_NFS_FS=y 64CONFIG_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
65CONFIG_XZ_DEC=y 68CONFIG_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
21extern void __init arc_init_IRQ(void); 21extern void arc_init_IRQ(void);
22extern int __init get_hw_config_num_irq(void); 22extern int get_hw_config_num_irq(void);
23 23
24void arc_local_timer_setup(unsigned int cpu); 24void 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
50typedef struct { 50typedef 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
52extern unsigned int asid_cache; 53DECLARE_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 */
58static inline void get_new_mmu_context(struct mm_struct *mm) 60static 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
94set_hw: 97set_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:
104static inline int 107static inline int
105init_new_context(struct task_struct *tsk, struct mm_struct *mm) 108init_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
118static 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*/
114static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, 131static 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
134static 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 {
31extern int root_mountflags, end_mem; 31extern int root_mountflags, end_mem;
32extern int running_on_hw; 32extern int running_on_hw;
33 33
34void __init setup_processor(void); 34void setup_processor(void);
35void __init setup_arch_memory(void); 35void __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 */
32extern void __init smp_init_cpus(void); 32extern void __init smp_init_cpus(void);
33extern void __init first_lines_of_secondary(void); 33extern void first_lines_of_secondary(void);
34extern const char *arc_platform_smp_cpuinfo(void); 34extern 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);
18void local_flush_tlb_range(struct vm_area_struct *vma, 18void 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
28extern void flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
29 unsigned long end);
30extern void flush_tlb_page(struct vm_area_struct *vma, unsigned long page);
31extern void flush_tlb_kernel_range(unsigned long start, unsigned long end);
32extern void flush_tlb_all(void);
33extern 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
22misaligned_fixup(unsigned long address, struct pt_regs *regs, 22misaligned_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
20struct task_struct *__sched 22struct 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 ============
3664: 3754:
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
641restore_regs : 645restore_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
149int __init get_hw_config_num_irq(void) 153int 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
199static void kgdb_call_nmi_hook(void *ignored)
200{
201 kgdb_nmicallback(raw_smp_processor_id(), NULL);
202}
203
204void 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
199struct kgdb_arch arch_kgdb_ops = { 211struct 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
88static void __kprobes restore_previous_kprobe(struct kprobe_ctlblk *kcb) 88static 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
94static inline void __kprobes set_current_kprobe(struct kprobe *p) 94static 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
99static void __kprobes resume_execution(struct kprobe *p, unsigned long addr, 99static 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
33void (*pm_power_off) (void) = NULL; 33void (*pm_power_off) (void) = NULL;
34EXPORT_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
38struct cpuinfo_arc cpuinfo_arc700[NR_CPUS]; 38struct cpuinfo_arc cpuinfo_arc700[NR_CPUS];
39 39
40 40static void read_arc_build_cfg_regs(void)
41void 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
109char *arc_cpu_mumbojumbo(int cpu_id, char *buf, int len) 108static 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
174char *arc_extn_mumbojumbo(int cpu_id, char *buf, int len) 173static 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
237void arc_chk_ccms(void) 236static 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 */
272void arc_chk_fpu(void) 271static 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 */
98void __attribute__((weak)) arc_platform_smp_wait_to_boot(int cpu) 98void __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
255void arch_send_call_function_single_ipi(int cpu) 255void 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
260void arch_send_call_function_ipi_mask(const struct cpumask *mask) 260void 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 */
238void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace) 238void 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
243void save_stack_trace(struct stack_trace *trace) 244void 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}
249EXPORT_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
64int arc_counter_setup(void) 64int 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
207static irqreturn_t timer_irq_handler(int irq, void *dev_id) 208static 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 */
226void __attribute__((weak)) arc_local_timer_setup(unsigned int cpu) 227void __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)
84DO_ERROR_INFO(SIGTRAP, "Breakpoint Set", trap_is_brkpt, TRAP_BRKPT) 84DO_ERROR_INFO(SIGTRAP, "Breakpoint Set", trap_is_brkpt, TRAP_BRKPT)
85DO_ERROR_INFO(SIGBUS, "Misaligned Access", do_misaligned_error, BUS_ADRALN) 85DO_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 */
91int do_misaligned_access(unsigned long address, struct pt_regs *regs, 90int 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 */
248static 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 */
298static 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
55void do_page_fault(struct pt_regs *regs, unsigned long address) 55void 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 */
103unsigned int asid_cache = MM_CTXT_FIRST_CYCLE; 103DEFINE_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)
274void local_flush_tlb_range(struct vm_area_struct *vma, unsigned long start, 274void 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
347void local_flush_tlb_page(struct vm_area_struct *vma, unsigned long page) 348void 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
368struct tlb_args {
369 struct vm_area_struct *ta_vma;
370 unsigned long ta_start;
371 unsigned long ta_end;
372};
373
374static 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
381static 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
388static 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
395void flush_tlb_all(void)
396{
397 on_each_cpu((smp_call_func_t)local_flush_tlb_all, NULL, 1);
398}
399
400void 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
406void 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
416void 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
428void 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