aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/mips/kernel/signal-common.h34
-rw-r--r--arch/mips/kernel/signal.c59
-rw-r--r--arch/mips/kernel/signal32.c16
-rw-r--r--arch/mips/kernel/signal_n32.c32
-rw-r--r--include/asm-mips/cpu-features.h11
-rw-r--r--include/asm-mips/mach-ja/cpu-feature-overrides.h6
-rw-r--r--include/asm-mips/mach-ocelot3/cpu-feature-overrides.h6
-rw-r--r--include/asm-mips/mach-yosemite/cpu-feature-overrides.h6
-rw-r--r--include/asm-mips/war.h14
9 files changed, 98 insertions, 86 deletions
diff --git a/arch/mips/kernel/signal-common.h b/arch/mips/kernel/signal-common.h
index 3208ff528cd2..0f66ae5838b9 100644
--- a/arch/mips/kernel/signal-common.h
+++ b/arch/mips/kernel/signal-common.h
@@ -160,7 +160,7 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext *sc)
160static inline void * 160static inline void *
161get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size) 161get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size)
162{ 162{
163 unsigned long sp, almask; 163 unsigned long sp;
164 164
165 /* Default to using normal stack */ 165 /* Default to using normal stack */
166 sp = regs->regs[29]; 166 sp = regs->regs[29];
@@ -176,10 +176,32 @@ get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size)
176 if ((ka->sa.sa_flags & SA_ONSTACK) && (sas_ss_flags (sp) == 0)) 176 if ((ka->sa.sa_flags & SA_ONSTACK) && (sas_ss_flags (sp) == 0))
177 sp = current->sas_ss_sp + current->sas_ss_size; 177 sp = current->sas_ss_sp + current->sas_ss_size;
178 178
179 if (PLAT_TRAMPOLINE_STUFF_LINE) 179 return (void *)((sp - frame_size) & (ICACHE_REFILLS_WORKAROUND_WAR ? 32 : ALMASK));
180 almask = ~(PLAT_TRAMPOLINE_STUFF_LINE - 1); 180}
181 else 181
182 almask = ALMASK; 182static inline int install_sigtramp(unsigned int __user *tramp,
183 unsigned int syscall)
184{
185 int err;
183 186
184 return (void *)((sp - frame_size) & almask); 187 /*
188 * Set up the return code ...
189 *
190 * li v0, __NR__foo_sigreturn
191 * syscall
192 */
193
194 err = __put_user(0x24020000 + syscall, tramp + 0);
195 err |= __put_user(0x0000000c , tramp + 1);
196 if (ICACHE_REFILLS_WORKAROUND_WAR) {
197 err |= __put_user(0, tramp + 2);
198 err |= __put_user(0, tramp + 3);
199 err |= __put_user(0, tramp + 4);
200 err |= __put_user(0, tramp + 5);
201 err |= __put_user(0, tramp + 6);
202 err |= __put_user(0, tramp + 7);
203 }
204 flush_cache_sigtramp((unsigned long) tramp);
205
206 return err;
185} 207}
diff --git a/arch/mips/kernel/signal.c b/arch/mips/kernel/signal.c
index 8504febf8b22..8679ccff870e 100644
--- a/arch/mips/kernel/signal.c
+++ b/arch/mips/kernel/signal.c
@@ -8,6 +8,7 @@
8 * Copyright (C) 1999, 2000 Silicon Graphics, Inc. 8 * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
9 */ 9 */
10#include <linux/config.h> 10#include <linux/config.h>
11#include <linux/cache.h>
11#include <linux/sched.h> 12#include <linux/sched.h>
12#include <linux/mm.h> 13#include <linux/mm.h>
13#include <linux/personality.h> 14#include <linux/personality.h>
@@ -30,6 +31,7 @@
30#include <asm/uaccess.h> 31#include <asm/uaccess.h>
31#include <asm/ucontext.h> 32#include <asm/ucontext.h>
32#include <asm/cpu-features.h> 33#include <asm/cpu-features.h>
34#include <asm/war.h>
33 35
34#include "signal-common.h" 36#include "signal-common.h"
35 37
@@ -157,26 +159,39 @@ asmlinkage int sys_sigaltstack(nabi_no_regargs struct pt_regs regs)
157 return do_sigaltstack(uss, uoss, usp); 159 return do_sigaltstack(uss, uoss, usp);
158} 160}
159 161
160#if PLAT_TRAMPOLINE_STUFF_LINE 162/*
161#define __tramp __attribute__((aligned(PLAT_TRAMPOLINE_STUFF_LINE))) 163 * Horribly complicated - with the bloody RM9000 workarounds enabled
162#else 164 * the signal trampolines is moving to the end of the structure so we can
163#define __tramp 165 * increase the alignment without breaking software compatibility.
164#endif 166 */
165
166#ifdef CONFIG_TRAD_SIGNALS 167#ifdef CONFIG_TRAD_SIGNALS
167struct sigframe { 168struct sigframe {
168 u32 sf_ass[4]; /* argument save space for o32 */ 169 u32 sf_ass[4]; /* argument save space for o32 */
169 u32 sf_code[2] __tramp; /* signal trampoline */ 170#if ICACHE_REFILLS_WORKAROUND_WAR
170 struct sigcontext sf_sc __tramp; 171 u32 sf_pad[2];
172#else
173 u32 sf_code[2]; /* signal trampoline */
174#endif
175 struct sigcontext sf_sc;
171 sigset_t sf_mask; 176 sigset_t sf_mask;
177#if ICACHE_REFILLS_WORKAROUND_WAR
178 u32 sf_code[8] ____cacheline_aligned; /* signal trampoline */
179#endif
172}; 180};
173#endif 181#endif
174 182
175struct rt_sigframe { 183struct rt_sigframe {
176 u32 rs_ass[4]; /* argument save space for o32 */ 184 u32 rs_ass[4]; /* argument save space for o32 */
177 u32 rs_code[2] __tramp; /* signal trampoline */ 185#if ICACHE_REFILLS_WORKAROUND_WAR
178 struct siginfo rs_info __tramp; 186 u32 rs_pad[2];
187#else
188 u32 rs_code[2]; /* signal trampoline */
189#endif
190 struct siginfo rs_info;
179 struct ucontext rs_uc; 191 struct ucontext rs_uc;
192#if ICACHE_REFILLS_WORKAROUND_WAR
193 u32 rs_code[8] ____cacheline_aligned; /* signal trampoline */
194#endif
180}; 195};
181 196
182#ifdef CONFIG_TRAD_SIGNALS 197#ifdef CONFIG_TRAD_SIGNALS
@@ -273,17 +288,7 @@ void setup_frame(struct k_sigaction * ka, struct pt_regs *regs,
273 if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame))) 288 if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame)))
274 goto give_sigsegv; 289 goto give_sigsegv;
275 290
276 /* 291 install_sigtramp(frame->sf_code, __NR_sigreturn);
277 * Set up the return code ...
278 *
279 * li v0, __NR_sigreturn
280 * syscall
281 */
282 if (PLAT_TRAMPOLINE_STUFF_LINE)
283 __clear_user(frame->sf_code, PLAT_TRAMPOLINE_STUFF_LINE);
284 err |= __put_user(0x24020000 + __NR_sigreturn, frame->sf_code + 0);
285 err |= __put_user(0x0000000c , frame->sf_code + 1);
286 flush_cache_sigtramp((unsigned long) frame->sf_code);
287 292
288 err |= setup_sigcontext(regs, &frame->sf_sc); 293 err |= setup_sigcontext(regs, &frame->sf_sc);
289 err |= __copy_to_user(&frame->sf_mask, set, sizeof(*set)); 294 err |= __copy_to_user(&frame->sf_mask, set, sizeof(*set));
@@ -329,17 +334,7 @@ void setup_rt_frame(struct k_sigaction * ka, struct pt_regs *regs,
329 if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame))) 334 if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame)))
330 goto give_sigsegv; 335 goto give_sigsegv;
331 336
332 /* 337 install_sigtramp(frame->rs_code, __NR_rt_sigreturn);
333 * Set up the return code ...
334 *
335 * li v0, __NR_rt_sigreturn
336 * syscall
337 */
338 if (PLAT_TRAMPOLINE_STUFF_LINE)
339 __clear_user(frame->rs_code, PLAT_TRAMPOLINE_STUFF_LINE);
340 err |= __put_user(0x24020000 + __NR_rt_sigreturn, frame->rs_code + 0);
341 err |= __put_user(0x0000000c , frame->rs_code + 1);
342 flush_cache_sigtramp((unsigned long) frame->rs_code);
343 338
344 /* Create siginfo. */ 339 /* Create siginfo. */
345 err |= copy_siginfo_to_user(&frame->rs_info, info); 340 err |= copy_siginfo_to_user(&frame->rs_info, info);
diff --git a/arch/mips/kernel/signal32.c b/arch/mips/kernel/signal32.c
index 8639e24732a5..806ed073e54d 100644
--- a/arch/mips/kernel/signal32.c
+++ b/arch/mips/kernel/signal32.c
@@ -7,6 +7,7 @@
7 * Copyright (C) 1994 - 2000 Ralf Baechle 7 * Copyright (C) 1994 - 2000 Ralf Baechle
8 * Copyright (C) 1999, 2000 Silicon Graphics, Inc. 8 * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
9 */ 9 */
10#include <linux/cache.h>
10#include <linux/sched.h> 11#include <linux/sched.h>
11#include <linux/mm.h> 12#include <linux/mm.h>
12#include <linux/smp.h> 13#include <linux/smp.h>
@@ -30,6 +31,7 @@
30#include <asm/ucontext.h> 31#include <asm/ucontext.h>
31#include <asm/system.h> 32#include <asm/system.h>
32#include <asm/fpu.h> 33#include <asm/fpu.h>
34#include <asm/war.h>
33 35
34#define SI_PAD_SIZE32 ((SI_MAX_SIZE/sizeof(int)) - 3) 36#define SI_PAD_SIZE32 ((SI_MAX_SIZE/sizeof(int)) - 3)
35 37
@@ -392,16 +394,30 @@ static int restore_sigcontext32(struct pt_regs *regs, struct sigcontext32 *sc)
392 394
393struct sigframe { 395struct sigframe {
394 u32 sf_ass[4]; /* argument save space for o32 */ 396 u32 sf_ass[4]; /* argument save space for o32 */
397#if ICACHE_REFILLS_WORKAROUND_WAR
398 u32 sf_pad[2];
399#else
395 u32 sf_code[2]; /* signal trampoline */ 400 u32 sf_code[2]; /* signal trampoline */
401#endif
396 struct sigcontext32 sf_sc; 402 struct sigcontext32 sf_sc;
397 sigset_t sf_mask; 403 sigset_t sf_mask;
404#if ICACHE_REFILLS_WORKAROUND_WAR
405 u32 sf_code[8] ____cacheline_aligned; /* signal trampoline */
406#endif
398}; 407};
399 408
400struct rt_sigframe32 { 409struct rt_sigframe32 {
401 u32 rs_ass[4]; /* argument save space for o32 */ 410 u32 rs_ass[4]; /* argument save space for o32 */
411#if ICACHE_REFILLS_WORKAROUND_WAR
412 u32 rs_pad[2];
413#else
402 u32 rs_code[2]; /* signal trampoline */ 414 u32 rs_code[2]; /* signal trampoline */
415#endif
403 compat_siginfo_t rs_info; 416 compat_siginfo_t rs_info;
404 struct ucontext32 rs_uc; 417 struct ucontext32 rs_uc;
418#if ICACHE_REFILLS_WORKAROUND_WAR
419 u32 rs_code[8] __attribute__((aligned(32))); /* signal trampoline */
420#endif
405}; 421};
406 422
407int copy_siginfo_to_user32(compat_siginfo_t *to, siginfo_t *from) 423int copy_siginfo_to_user32(compat_siginfo_t *to, siginfo_t *from)
diff --git a/arch/mips/kernel/signal_n32.c b/arch/mips/kernel/signal_n32.c
index 3544208d4b4b..f47c3aaaec8a 100644
--- a/arch/mips/kernel/signal_n32.c
+++ b/arch/mips/kernel/signal_n32.c
@@ -15,6 +15,8 @@
15 * along with this program; if not, write to the Free Software 15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17 */ 17 */
18#include <linux/cache.h>
19#include <linux/sched.h>
18#include <linux/sched.h> 20#include <linux/sched.h>
19#include <linux/mm.h> 21#include <linux/mm.h>
20#include <linux/smp.h> 22#include <linux/smp.h>
@@ -36,6 +38,7 @@
36#include <asm/system.h> 38#include <asm/system.h>
37#include <asm/fpu.h> 39#include <asm/fpu.h>
38#include <asm/cpu-features.h> 40#include <asm/cpu-features.h>
41#include <asm/war.h>
39 42
40#include "signal-common.h" 43#include "signal-common.h"
41 44
@@ -62,17 +65,18 @@ struct ucontextn32 {
62 sigset_t uc_sigmask; /* mask last for extensibility */ 65 sigset_t uc_sigmask; /* mask last for extensibility */
63}; 66};
64 67
65#if PLAT_TRAMPOLINE_STUFF_LINE
66#define __tramp __attribute__((aligned(PLAT_TRAMPOLINE_STUFF_LINE)))
67#else
68#define __tramp
69#endif
70
71struct rt_sigframe_n32 { 68struct rt_sigframe_n32 {
72 u32 rs_ass[4]; /* argument save space for o32 */ 69 u32 rs_ass[4]; /* argument save space for o32 */
73 u32 rs_code[2] __tramp; /* signal trampoline */ 70#if ICACHE_REFILLS_WORKAROUND_WAR
74 struct siginfo rs_info __tramp; 71 u32 rs_pad[2];
72#else
73 u32 rs_code[2]; /* signal trampoline */
74#endif
75 struct siginfo rs_info;
75 struct ucontextn32 rs_uc; 76 struct ucontextn32 rs_uc;
77#if ICACHE_REFILLS_WORKAROUND_WAR
78 u32 rs_code[8] ____cacheline_aligned; /* signal trampoline */
79#endif
76}; 80};
77 81
78save_static_function(sysn32_rt_sigreturn); 82save_static_function(sysn32_rt_sigreturn);
@@ -137,17 +141,7 @@ void setup_rt_frame_n32(struct k_sigaction * ka,
137 if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame))) 141 if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame)))
138 goto give_sigsegv; 142 goto give_sigsegv;
139 143
140 /* 144 install_sigtramp(frame->rs_code, __NR_N32_rt_sigreturn);
141 * Set up the return code ...
142 *
143 * li v0, __NR_rt_sigreturn
144 * syscall
145 */
146 if (PLAT_TRAMPOLINE_STUFF_LINE)
147 __clear_user(frame->rs_code, PLAT_TRAMPOLINE_STUFF_LINE);
148 err |= __put_user(0x24020000 + __NR_N32_rt_sigreturn, frame->rs_code + 0);
149 err |= __put_user(0x0000000c , frame->rs_code + 1);
150 flush_cache_sigtramp((unsigned long) frame->rs_code);
151 145
152 /* Create siginfo. */ 146 /* Create siginfo. */
153 err |= copy_siginfo_to_user(&frame->rs_info, info); 147 err |= copy_siginfo_to_user(&frame->rs_info, info);
diff --git a/include/asm-mips/cpu-features.h b/include/asm-mips/cpu-features.h
index 4930824a43aa..bb2212cf460a 100644
--- a/include/asm-mips/cpu-features.h
+++ b/include/asm-mips/cpu-features.h
@@ -109,17 +109,6 @@
109#define cpu_has_dsp (cpu_data[0].ases & MIPS_ASE_DSP) 109#define cpu_has_dsp (cpu_data[0].ases & MIPS_ASE_DSP)
110#endif 110#endif
111 111
112/*
113 * Certain CPUs may throw bizarre exceptions if not the whole cacheline
114 * contains valid instructions. For these we ensure proper alignment of
115 * signal trampolines and pad them to the size of a full cache lines with
116 * nops. This is also used in structure definitions so can't be a test macro
117 * like the others.
118 */
119#ifndef PLAT_TRAMPOLINE_STUFF_LINE
120#define PLAT_TRAMPOLINE_STUFF_LINE 0UL
121#endif
122
123#ifdef CONFIG_32BIT 112#ifdef CONFIG_32BIT
124# ifndef cpu_has_nofpuex 113# ifndef cpu_has_nofpuex
125# define cpu_has_nofpuex (cpu_data[0].options & MIPS_CPU_NOFPUEX) 114# define cpu_has_nofpuex (cpu_data[0].options & MIPS_CPU_NOFPUEX)
diff --git a/include/asm-mips/mach-ja/cpu-feature-overrides.h b/include/asm-mips/mach-ja/cpu-feature-overrides.h
index 310609c0f4ad..a0fde405d4c4 100644
--- a/include/asm-mips/mach-ja/cpu-feature-overrides.h
+++ b/include/asm-mips/mach-ja/cpu-feature-overrides.h
@@ -37,10 +37,4 @@
37#define cpu_icache_line_size() 32 37#define cpu_icache_line_size() 32
38#define cpu_scache_line_size() 32 38#define cpu_scache_line_size() 32
39 39
40/*
41 * On the RM9000 we need to ensure that I-cache lines being fetches only
42 * contain valid instructions are funny things will happen.
43 */
44#define PLAT_TRAMPOLINE_STUFF_LINE 32UL
45
46#endif /* __ASM_MACH_JA_CPU_FEATURE_OVERRIDES_H */ 40#endif /* __ASM_MACH_JA_CPU_FEATURE_OVERRIDES_H */
diff --git a/include/asm-mips/mach-ocelot3/cpu-feature-overrides.h b/include/asm-mips/mach-ocelot3/cpu-feature-overrides.h
index 1812fc0408d3..825c5f674dfc 100644
--- a/include/asm-mips/mach-ocelot3/cpu-feature-overrides.h
+++ b/include/asm-mips/mach-ocelot3/cpu-feature-overrides.h
@@ -40,10 +40,4 @@
40#define cpu_icache_line_size() 32 40#define cpu_icache_line_size() 32
41#define cpu_scache_line_size() 32 41#define cpu_scache_line_size() 32
42 42
43/*
44 * On the RM9000 we need to ensure that I-cache lines being fetches only
45 * contain valid instructions are funny things will happen.
46 */
47#define PLAT_TRAMPOLINE_STUFF_LINE 32UL
48
49#endif /* __ASM_MACH_JA_CPU_FEATURE_OVERRIDES_H */ 43#endif /* __ASM_MACH_JA_CPU_FEATURE_OVERRIDES_H */
diff --git a/include/asm-mips/mach-yosemite/cpu-feature-overrides.h b/include/asm-mips/mach-yosemite/cpu-feature-overrides.h
index 63e94342e087..463d051f4683 100644
--- a/include/asm-mips/mach-yosemite/cpu-feature-overrides.h
+++ b/include/asm-mips/mach-yosemite/cpu-feature-overrides.h
@@ -37,10 +37,4 @@
37#define cpu_icache_line_size() 32 37#define cpu_icache_line_size() 32
38#define cpu_scache_line_size() 32 38#define cpu_scache_line_size() 32
39 39
40/*
41 * On the RM9000 we need to ensure that I-cache lines being fetches only
42 * contain valid instructions are funny things will happen.
43 */
44#define PLAT_TRAMPOLINE_STUFF_LINE 32UL
45
46#endif /* __ASM_MACH_YOSEMITE_CPU_FEATURE_OVERRIDES_H */ 40#endif /* __ASM_MACH_YOSEMITE_CPU_FEATURE_OVERRIDES_H */
diff --git a/include/asm-mips/war.h b/include/asm-mips/war.h
index 04ee53b34c2e..ad374bd3f130 100644
--- a/include/asm-mips/war.h
+++ b/include/asm-mips/war.h
@@ -177,6 +177,17 @@
177#endif 177#endif
178 178
179/* 179/*
180 * The RM9000 has a bug (though PMC-Sierra opposes it being called that)
181 * where invalid instructions in the same I-cache line worth of instructions
182 * being fetched may case spurious exceptions.
183 */
184#if defined(CONFIG_MOMENCO_JAGUAR_ATX) || defined(CONFIG_MOMENCO_OCELOT_3) || \
185 defined(CONFIG_PMC_YOSEMITE)
186#define ICACHE_REFILLS_WORKAROUND_WAR 1
187#endif
188
189
190/*
180 * ON the R10000 upto version 2.6 (not sure about 2.7) there is a bug that 191 * ON the R10000 upto version 2.6 (not sure about 2.7) there is a bug that
181 * may cause ll / sc and lld / scd sequences to execute non-atomically. 192 * may cause ll / sc and lld / scd sequences to execute non-atomically.
182 */ 193 */
@@ -187,6 +198,9 @@
187/* 198/*
188 * Workarounds default to off 199 * Workarounds default to off
189 */ 200 */
201#ifndef ICACHE_REFILLS_WORKAROUND_WAR
202#define ICACHE_REFILLS_WORKAROUND_WAR 0
203#endif
190#ifndef R4600_V1_INDEX_ICACHEOP_WAR 204#ifndef R4600_V1_INDEX_ICACHEOP_WAR
191#define R4600_V1_INDEX_ICACHEOP_WAR 0 205#define R4600_V1_INDEX_ICACHEOP_WAR 0
192#endif 206#endif