aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips/kernel
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>2005-06-15 09:00:12 -0400
committerRalf Baechle <ralf@linux-mips.org>2005-10-29 14:31:23 -0400
commit02416dcf5a94af34bcd28b4baf25bbbf399d8136 (patch)
tree1906c4266d4e28ef0b13d0579a145603dcbcff1b /arch/mips/kernel
parentaac8aa7717a23a9bf8740dbfb59755b1d62f04bf (diff)
Redo RM9000 workaround which along with other DSP ASE changes was
causing some headache for debuggers knowing about signal frames. Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Diffstat (limited to 'arch/mips/kernel')
-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
4 files changed, 84 insertions, 57 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);