aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips/kernel
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>2005-05-31 07:49:19 -0400
committerRalf Baechle <ralf@linux-mips.org>2005-10-29 14:31:17 -0400
commite50c0a8fa60da9ac0e0a70caa8a3a803815c1f2f (patch)
tree1928e8b0a4b7fb615e5a9f65dc934ba2e74cb9cd /arch/mips/kernel
parent10f650db1bcc193ea07d4f8c2f07315da38ea0c4 (diff)
Support the MIPS32 / MIPS64 DSP ASE.
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Diffstat (limited to 'arch/mips/kernel')
-rw-r--r--arch/mips/kernel/asm-offsets.c26
-rw-r--r--arch/mips/kernel/branch.c19
-rw-r--r--arch/mips/kernel/cpu-probe.c3
-rw-r--r--arch/mips/kernel/genex.S1
-rw-r--r--arch/mips/kernel/process.c58
-rw-r--r--arch/mips/kernel/ptrace.c38
-rw-r--r--arch/mips/kernel/ptrace32.c38
-rw-r--r--arch/mips/kernel/r4k_fpu.S5
-rw-r--r--arch/mips/kernel/scall32-o32.S2
-rw-r--r--arch/mips/kernel/setup.c9
-rw-r--r--arch/mips/kernel/signal-common.h56
-rw-r--r--arch/mips/kernel/signal.c52
-rw-r--r--arch/mips/kernel/signal32.c34
-rw-r--r--arch/mips/kernel/traps.c49
14 files changed, 308 insertions, 82 deletions
diff --git a/arch/mips/kernel/asm-offsets.c b/arch/mips/kernel/asm-offsets.c
index af69cdbdd50e..ca6b03c773be 100644
--- a/arch/mips/kernel/asm-offsets.c
+++ b/arch/mips/kernel/asm-offsets.c
@@ -95,7 +95,7 @@ void output_thread_info_defines(void)
95 offset("#define TI_PRE_COUNT ", struct thread_info, preempt_count); 95 offset("#define TI_PRE_COUNT ", struct thread_info, preempt_count);
96 offset("#define TI_ADDR_LIMIT ", struct thread_info, addr_limit); 96 offset("#define TI_ADDR_LIMIT ", struct thread_info, addr_limit);
97 offset("#define TI_RESTART_BLOCK ", struct thread_info, restart_block); 97 offset("#define TI_RESTART_BLOCK ", struct thread_info, restart_block);
98 offset("#define TI_TP_VALUE ", struct thread_info, tp_value); 98 offset("#define TI_TP_VALUE ", struct thread_info, tp_value);
99 constant("#define _THREAD_SIZE_ORDER ", THREAD_SIZE_ORDER); 99 constant("#define _THREAD_SIZE_ORDER ", THREAD_SIZE_ORDER);
100 constant("#define _THREAD_SIZE ", THREAD_SIZE); 100 constant("#define _THREAD_SIZE ", THREAD_SIZE);
101 constant("#define _THREAD_MASK ", THREAD_MASK); 101 constant("#define _THREAD_MASK ", THREAD_MASK);
@@ -241,6 +241,7 @@ void output_mm_defines(void)
241 linefeed; 241 linefeed;
242} 242}
243 243
244#ifdef CONFIG_32BIT
244void output_sc_defines(void) 245void output_sc_defines(void)
245{ 246{
246 text("/* Linux sigcontext offsets. */"); 247 text("/* Linux sigcontext offsets. */");
@@ -252,10 +253,29 @@ void output_sc_defines(void)
252 offset("#define SC_STATUS ", struct sigcontext, sc_status); 253 offset("#define SC_STATUS ", struct sigcontext, sc_status);
253 offset("#define SC_FPC_CSR ", struct sigcontext, sc_fpc_csr); 254 offset("#define SC_FPC_CSR ", struct sigcontext, sc_fpc_csr);
254 offset("#define SC_FPC_EIR ", struct sigcontext, sc_fpc_eir); 255 offset("#define SC_FPC_EIR ", struct sigcontext, sc_fpc_eir);
255 offset("#define SC_CAUSE ", struct sigcontext, sc_cause); 256 offset("#define SC_HI1 ", struct sigcontext, sc_hi1);
256 offset("#define SC_BADVADDR ", struct sigcontext, sc_badvaddr); 257 offset("#define SC_LO1 ", struct sigcontext, sc_lo1);
258 offset("#define SC_HI2 ", struct sigcontext, sc_hi2);
259 offset("#define SC_LO2 ", struct sigcontext, sc_lo2);
260 offset("#define SC_HI3 ", struct sigcontext, sc_hi3);
261 offset("#define SC_LO3 ", struct sigcontext, sc_lo3);
257 linefeed; 262 linefeed;
258} 263}
264#endif
265
266#ifdef CONFIG_64BIT
267void output_sc_defines(void)
268{
269 text("/* Linux sigcontext offsets. */");
270 offset("#define SC_REGS ", struct sigcontext, sc_regs);
271 offset("#define SC_FPREGS ", struct sigcontext, sc_fpregs);
272 offset("#define SC_MDHI ", struct sigcontext, sc_hi);
273 offset("#define SC_MDLO ", struct sigcontext, sc_lo);
274 offset("#define SC_PC ", struct sigcontext, sc_pc);
275 offset("#define SC_FPC_CSR ", struct sigcontext, sc_fpc_csr);
276 linefeed;
277}
278#endif
259 279
260#ifdef CONFIG_MIPS32_COMPAT 280#ifdef CONFIG_MIPS32_COMPAT
261void output_sc32_defines(void) 281void output_sc32_defines(void)
diff --git a/arch/mips/kernel/branch.c b/arch/mips/kernel/branch.c
index 56aea5f526a7..374de839558d 100644
--- a/arch/mips/kernel/branch.c
+++ b/arch/mips/kernel/branch.c
@@ -22,7 +22,7 @@
22 */ 22 */
23int __compute_return_epc(struct pt_regs *regs) 23int __compute_return_epc(struct pt_regs *regs)
24{ 24{
25 unsigned int *addr, bit, fcr31; 25 unsigned int *addr, bit, fcr31, dspcontrol;
26 long epc; 26 long epc;
27 union mips_instruction insn; 27 union mips_instruction insn;
28 28
@@ -99,6 +99,18 @@ int __compute_return_epc(struct pt_regs *regs)
99 epc += 8; 99 epc += 8;
100 regs->cp0_epc = epc; 100 regs->cp0_epc = epc;
101 break; 101 break;
102 case bposge32_op:
103 if (!cpu_has_dsp)
104 goto sigill;
105
106 dspcontrol = rddsp(0x01);
107
108 if (dspcontrol >= 32) {
109 epc = epc + 4 + (insn.i_format.simmediate << 2);
110 } else
111 epc += 8;
112 regs->cp0_epc = epc;
113 break;
102 } 114 }
103 break; 115 break;
104 116
@@ -200,4 +212,9 @@ unaligned:
200 printk("%s: unaligned epc - sending SIGBUS.\n", current->comm); 212 printk("%s: unaligned epc - sending SIGBUS.\n", current->comm);
201 force_sig(SIGBUS, current); 213 force_sig(SIGBUS, current);
202 return -EFAULT; 214 return -EFAULT;
215
216sigill:
217 printk("%s: DSP branch but not DSP ASE - sending SIGBUS.\n", current->comm);
218 force_sig(SIGBUS, current);
219 return -EFAULT;
203} 220}
diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c
index 552d2b6c191e..1ae7762fd084 100644
--- a/arch/mips/kernel/cpu-probe.c
+++ b/arch/mips/kernel/cpu-probe.c
@@ -482,6 +482,8 @@ static inline unsigned int decode_config3(struct cpuinfo_mips *c)
482 482
483 if (config3 & MIPS_CONF3_SM) 483 if (config3 & MIPS_CONF3_SM)
484 c->ases |= MIPS_ASE_SMARTMIPS; 484 c->ases |= MIPS_ASE_SMARTMIPS;
485 if (config3 & MIPS_CONF3_DSP)
486 c->ases |= MIPS_ASE_DSP;
485 487
486 return config3 & MIPS_CONF_M; 488 return config3 & MIPS_CONF_M;
487} 489}
@@ -529,6 +531,7 @@ static inline void cpu_probe_mips(struct cpuinfo_mips *c)
529 c->cputype = CPU_20KC; 531 c->cputype = CPU_20KC;
530 break; 532 break;
531 case PRID_IMP_24K: 533 case PRID_IMP_24K:
534 case PRID_IMP_24KE:
532 c->cputype = CPU_24K; 535 c->cputype = CPU_24K;
533 break; 536 break;
534 case PRID_IMP_25KF: 537 case PRID_IMP_25KF:
diff --git a/arch/mips/kernel/genex.S b/arch/mips/kernel/genex.S
index e5021c758ef0..349ec301168f 100644
--- a/arch/mips/kernel/genex.S
+++ b/arch/mips/kernel/genex.S
@@ -291,6 +291,7 @@ NESTED(nmi_handler, PT_SIZE, sp)
291 BUILD_HANDLER mdmx mdmx sti silent /* #22 */ 291 BUILD_HANDLER mdmx mdmx sti silent /* #22 */
292 BUILD_HANDLER watch watch sti verbose /* #23 */ 292 BUILD_HANDLER watch watch sti verbose /* #23 */
293 BUILD_HANDLER mcheck mcheck cli verbose /* #24 */ 293 BUILD_HANDLER mcheck mcheck cli verbose /* #24 */
294 BUILD_HANDLER dsp dsp sti silent /* #26 */
294 BUILD_HANDLER reserved reserved sti verbose /* others */ 295 BUILD_HANDLER reserved reserved sti verbose /* others */
295 296
296#ifdef CONFIG_64BIT 297#ifdef CONFIG_64BIT
diff --git a/arch/mips/kernel/process.c b/arch/mips/kernel/process.c
index 368526af5f5e..98432097a86a 100644
--- a/arch/mips/kernel/process.c
+++ b/arch/mips/kernel/process.c
@@ -25,8 +25,10 @@
25#include <linux/init.h> 25#include <linux/init.h>
26#include <linux/completion.h> 26#include <linux/completion.h>
27 27
28#include <asm/abi.h>
28#include <asm/bootinfo.h> 29#include <asm/bootinfo.h>
29#include <asm/cpu.h> 30#include <asm/cpu.h>
31#include <asm/dsp.h>
30#include <asm/fpu.h> 32#include <asm/fpu.h>
31#include <asm/pgtable.h> 33#include <asm/pgtable.h>
32#include <asm/system.h> 34#include <asm/system.h>
@@ -54,6 +56,54 @@ ATTRIB_NORET void cpu_idle(void)
54 } 56 }
55} 57}
56 58
59extern int do_signal(sigset_t *oldset, struct pt_regs *regs);
60extern int do_signal32(sigset_t *oldset, struct pt_regs *regs);
61
62/*
63 * Native o32 and N64 ABI without DSP ASE
64 */
65extern void setup_frame(struct k_sigaction * ka, struct pt_regs *regs,
66 int signr, sigset_t *set);
67extern void setup_rt_frame(struct k_sigaction * ka, struct pt_regs *regs,
68 int signr, sigset_t *set, siginfo_t *info);
69
70struct mips_abi mips_abi = {
71 .do_signal = do_signal,
72#ifdef CONFIG_TRAD_SIGNALS
73 .setup_frame = setup_frame,
74#endif
75 .setup_rt_frame = setup_rt_frame
76};
77
78#ifdef CONFIG_MIPS32_O32
79/*
80 * o32 compatibility on 64-bit kernels, without DSP ASE
81 */
82extern void setup_frame_32(struct k_sigaction * ka, struct pt_regs *regs,
83 int signr, sigset_t *set);
84extern void setup_rt_frame_32(struct k_sigaction * ka, struct pt_regs *regs,
85 int signr, sigset_t *set, siginfo_t *info);
86
87struct mips_abi mips_abi_32 = {
88 .do_signal = do_signal32,
89 .setup_frame = setup_frame_32,
90 .setup_rt_frame = setup_rt_frame_32
91};
92#endif /* CONFIG_MIPS32_O32 */
93
94#ifdef CONFIG_MIPS32_N32
95/*
96 * N32 on 64-bit kernels, without DSP ASE
97 */
98extern void setup_rt_frame_n32(struct k_sigaction * ka, struct pt_regs *regs,
99 int signr, sigset_t *set, siginfo_t *info);
100
101struct mips_abi mips_abi_n32 = {
102 .do_signal = do_signal,
103 .setup_rt_frame = setup_rt_frame_n32
104};
105#endif /* CONFIG_MIPS32_N32 */
106
57asmlinkage void ret_from_fork(void); 107asmlinkage void ret_from_fork(void);
58 108
59void start_thread(struct pt_regs * regs, unsigned long pc, unsigned long sp) 109void start_thread(struct pt_regs * regs, unsigned long pc, unsigned long sp)
@@ -70,6 +120,8 @@ void start_thread(struct pt_regs * regs, unsigned long pc, unsigned long sp)
70 regs->cp0_status = status; 120 regs->cp0_status = status;
71 clear_used_math(); 121 clear_used_math();
72 lose_fpu(); 122 lose_fpu();
123 if (cpu_has_dsp)
124 __init_dsp();
73 regs->cp0_epc = pc; 125 regs->cp0_epc = pc;
74 regs->regs[29] = sp; 126 regs->regs[29] = sp;
75 current_thread_info()->addr_limit = USER_DS; 127 current_thread_info()->addr_limit = USER_DS;
@@ -95,9 +147,11 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
95 147
96 preempt_disable(); 148 preempt_disable();
97 149
98 if (is_fpu_owner()) { 150 if (is_fpu_owner())
99 save_fp(p); 151 save_fp(p);
100 } 152
153 if (cpu_has_dsp)
154 save_dsp(p);
101 155
102 preempt_enable(); 156 preempt_enable();
103 157
diff --git a/arch/mips/kernel/ptrace.c b/arch/mips/kernel/ptrace.c
index 49821ee18984..2441e32ce820 100644
--- a/arch/mips/kernel/ptrace.c
+++ b/arch/mips/kernel/ptrace.c
@@ -30,6 +30,7 @@
30 30
31#include <asm/byteorder.h> 31#include <asm/byteorder.h>
32#include <asm/cpu.h> 32#include <asm/cpu.h>
33#include <asm/dsp.h>
33#include <asm/fpu.h> 34#include <asm/fpu.h>
34#include <asm/mipsregs.h> 35#include <asm/mipsregs.h>
35#include <asm/pgtable.h> 36#include <asm/pgtable.h>
@@ -176,6 +177,27 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
176 write_c0_status(flags); 177 write_c0_status(flags);
177 break; 178 break;
178 } 179 }
180 case DSP_BASE ... DSP_BASE + 5:
181 if (!cpu_has_dsp) {
182 tmp = 0;
183 ret = -EIO;
184 goto out_tsk;
185 }
186 if (child->thread.dsp.used_dsp) {
187 dspreg_t *dregs = __get_dsp_regs(child);
188 tmp = (unsigned long) (dregs[addr - DSP_BASE]);
189 } else {
190 tmp = -1; /* DSP registers yet used */
191 }
192 break;
193 case DSP_CONTROL:
194 if (!cpu_has_dsp) {
195 tmp = 0;
196 ret = -EIO;
197 goto out_tsk;
198 }
199 tmp = child->thread.dsp.dspcontrol;
200 break;
179 default: 201 default:
180 tmp = 0; 202 tmp = 0;
181 ret = -EIO; 203 ret = -EIO;
@@ -248,6 +270,22 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
248 else 270 else
249 child->thread.fpu.soft.fcr31 = data; 271 child->thread.fpu.soft.fcr31 = data;
250 break; 272 break;
273 case DSP_BASE ... DSP_BASE + 5:
274 if (!cpu_has_dsp) {
275 ret = -EIO;
276 break;
277 }
278
279 dspreg_t *dregs = __get_dsp_regs(child);
280 dregs[addr - DSP_BASE] = data;
281 break;
282 case DSP_CONTROL:
283 if (!cpu_has_dsp) {
284 ret = -EIO;
285 break;
286 }
287 child->thread.dsp.dspcontrol = data;
288 break;
251 default: 289 default:
252 /* The rest are not allowed. */ 290 /* The rest are not allowed. */
253 ret = -EIO; 291 ret = -EIO;
diff --git a/arch/mips/kernel/ptrace32.c b/arch/mips/kernel/ptrace32.c
index eb446e525908..5c45a5880226 100644
--- a/arch/mips/kernel/ptrace32.c
+++ b/arch/mips/kernel/ptrace32.c
@@ -26,6 +26,7 @@
26#include <linux/security.h> 26#include <linux/security.h>
27 27
28#include <asm/cpu.h> 28#include <asm/cpu.h>
29#include <asm/dsp.h>
29#include <asm/fpu.h> 30#include <asm/fpu.h>
30#include <asm/mipsregs.h> 31#include <asm/mipsregs.h>
31#include <asm/pgtable.h> 32#include <asm/pgtable.h>
@@ -161,6 +162,27 @@ asmlinkage int sys32_ptrace(int request, int pid, int addr, int data)
161 write_c0_status(flags); 162 write_c0_status(flags);
162 break; 163 break;
163 } 164 }
165 case DSP_BASE ... DSP_BASE + 5:
166 if (!cpu_has_dsp) {
167 tmp = 0;
168 ret = -EIO;
169 goto out_tsk;
170 }
171 if (child->thread.dsp.used_dsp) {
172 dspreg_t *dregs = __get_dsp_regs(child);
173 tmp = (unsigned long) (dregs[addr - DSP_BASE]);
174 } else {
175 tmp = -1; /* DSP registers yet used */
176 }
177 break;
178 case DSP_CONTROL:
179 if (!cpu_has_dsp) {
180 tmp = 0;
181 ret = -EIO;
182 goto out_tsk;
183 }
184 tmp = child->thread.dsp.dspcontrol;
185 break;
164 default: 186 default:
165 tmp = 0; 187 tmp = 0;
166 ret = -EIO; 188 ret = -EIO;
@@ -230,6 +252,22 @@ asmlinkage int sys32_ptrace(int request, int pid, int addr, int data)
230 else 252 else
231 child->thread.fpu.soft.fcr31 = data; 253 child->thread.fpu.soft.fcr31 = data;
232 break; 254 break;
255 case DSP_BASE ... DSP_BASE + 5:
256 if (!cpu_has_dsp) {
257 ret = -EIO;
258 break;
259 }
260
261 dspreg_t *dregs = __get_dsp_regs(child);
262 dregs[addr - DSP_BASE] = data;
263 break;
264 case DSP_CONTROL:
265 if (!cpu_has_dsp) {
266 ret = -EIO;
267 break;
268 }
269 child->thread.dsp.dspcontrol = data;
270 break;
233 default: 271 default:
234 /* The rest are not allowed. */ 272 /* The rest are not allowed. */
235 ret = -EIO; 273 ret = -EIO;
diff --git a/arch/mips/kernel/r4k_fpu.S b/arch/mips/kernel/r4k_fpu.S
index 1a14c6b18829..283a98508fc8 100644
--- a/arch/mips/kernel/r4k_fpu.S
+++ b/arch/mips/kernel/r4k_fpu.S
@@ -32,7 +32,7 @@
32 32
33 .set noreorder 33 .set noreorder
34 .set mips3 34 .set mips3
35 /* Save floating point context */ 35
36LEAF(_save_fp_context) 36LEAF(_save_fp_context)
37 cfc1 t1, fcr31 37 cfc1 t1, fcr31
38 38
@@ -74,9 +74,6 @@ LEAF(_save_fp_context)
74 EX sdc1 $f28, SC_FPREGS+224(a0) 74 EX sdc1 $f28, SC_FPREGS+224(a0)
75 EX sdc1 $f30, SC_FPREGS+240(a0) 75 EX sdc1 $f30, SC_FPREGS+240(a0)
76 EX sw t1, SC_FPC_CSR(a0) 76 EX sw t1, SC_FPC_CSR(a0)
77 cfc1 t0, $0 # implementation/version
78 EX sw t0, SC_FPC_EIR(a0)
79
80 jr ra 77 jr ra
81 li v0, 0 # success 78 li v0, 0 # success
82 END(_save_fp_context) 79 END(_save_fp_context)
diff --git a/arch/mips/kernel/scall32-o32.S b/arch/mips/kernel/scall32-o32.S
index 6fa1112512c8..c389dbaa279e 100644
--- a/arch/mips/kernel/scall32-o32.S
+++ b/arch/mips/kernel/scall32-o32.S
@@ -620,7 +620,7 @@ einval: li v0, -EINVAL
620 sys sys_ni_syscall 0 /* sys_vserver */ 620 sys sys_ni_syscall 0 /* sys_vserver */
621 sys sys_waitid 5 621 sys sys_waitid 5
622 sys sys_ni_syscall 0 /* available, was setaltroot */ 622 sys sys_ni_syscall 0 /* available, was setaltroot */
623 sys sys_add_key 5 623 sys sys_add_key 5 /* 4280 */
624 sys sys_request_key 4 624 sys sys_request_key 4
625 sys sys_keyctl 5 625 sys sys_keyctl 5
626 sys sys_set_thread_area 1 626 sys sys_set_thread_area 1
diff --git a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c
index 6fc51b298304..9253dccefd07 100644
--- a/arch/mips/kernel/setup.c
+++ b/arch/mips/kernel/setup.c
@@ -549,3 +549,12 @@ int __init fpu_disable(char *s)
549} 549}
550 550
551__setup("nofpu", fpu_disable); 551__setup("nofpu", fpu_disable);
552
553int __init dsp_disable(char *s)
554{
555 cpu_data[0].ases &= ~MIPS_ASE_DSP;
556
557 return 1;
558}
559
560__setup("nodsp", dsp_disable);
diff --git a/arch/mips/kernel/signal-common.h b/arch/mips/kernel/signal-common.h
index f9234df53253..3208ff528cd2 100644
--- a/arch/mips/kernel/signal-common.h
+++ b/arch/mips/kernel/signal-common.h
@@ -8,13 +8,14 @@
8 * Copyright (C) 1999, 2000 Silicon Graphics, Inc. 8 * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
9 */ 9 */
10 10
11#include <linux/config.h>
12
11static inline int 13static inline int
12setup_sigcontext(struct pt_regs *regs, struct sigcontext *sc) 14setup_sigcontext(struct pt_regs *regs, struct sigcontext *sc)
13{ 15{
14 int err = 0; 16 int err = 0;
15 17
16 err |= __put_user(regs->cp0_epc, &sc->sc_pc); 18 err |= __put_user(regs->cp0_epc, &sc->sc_pc);
17 err |= __put_user(regs->cp0_status, &sc->sc_status);
18 19
19#define save_gp_reg(i) do { \ 20#define save_gp_reg(i) do { \
20 err |= __put_user(regs->regs[i], &sc->sc_regs[i]); \ 21 err |= __put_user(regs->regs[i], &sc->sc_regs[i]); \
@@ -30,10 +31,32 @@ setup_sigcontext(struct pt_regs *regs, struct sigcontext *sc)
30 save_gp_reg(31); 31 save_gp_reg(31);
31#undef save_gp_reg 32#undef save_gp_reg
32 33
34#ifdef CONFIG_32BIT
33 err |= __put_user(regs->hi, &sc->sc_mdhi); 35 err |= __put_user(regs->hi, &sc->sc_mdhi);
34 err |= __put_user(regs->lo, &sc->sc_mdlo); 36 err |= __put_user(regs->lo, &sc->sc_mdlo);
35 err |= __put_user(regs->cp0_cause, &sc->sc_cause); 37 if (cpu_has_dsp) {
36 err |= __put_user(regs->cp0_badvaddr, &sc->sc_badvaddr); 38 err |= __put_user(mfhi1(), &sc->sc_hi1);
39 err |= __put_user(mflo1(), &sc->sc_lo1);
40 err |= __put_user(mfhi2(), &sc->sc_hi2);
41 err |= __put_user(mflo2(), &sc->sc_lo2);
42 err |= __put_user(mfhi3(), &sc->sc_hi3);
43 err |= __put_user(mflo3(), &sc->sc_lo3);
44 err |= __put_user(rddsp(DSP_MASK), &sc->sc_dsp);
45 }
46#endif
47#ifdef CONFIG_64BIT
48 err |= __put_user(regs->hi, &sc->sc_hi[0]);
49 err |= __put_user(regs->lo, &sc->sc_lo[0]);
50 if (cpu_has_dsp) {
51 err |= __put_user(mfhi1(), &sc->sc_hi[1]);
52 err |= __put_user(mflo1(), &sc->sc_lo[1]);
53 err |= __put_user(mfhi2(), &sc->sc_hi[2]);
54 err |= __put_user(mflo2(), &sc->sc_lo[2]);
55 err |= __put_user(mfhi3(), &sc->sc_hi[3]);
56 err |= __put_user(mflo3(), &sc->sc_lo[3]);
57 err |= __put_user(rddsp(DSP_MASK), &sc->sc_dsp);
58 }
59#endif
37 60
38 err |= __put_user(!!used_math(), &sc->sc_used_math); 61 err |= __put_user(!!used_math(), &sc->sc_used_math);
39 62
@@ -61,15 +84,40 @@ out:
61static inline int 84static inline int
62restore_sigcontext(struct pt_regs *regs, struct sigcontext *sc) 85restore_sigcontext(struct pt_regs *regs, struct sigcontext *sc)
63{ 86{
64 int err = 0;
65 unsigned int used_math; 87 unsigned int used_math;
88 unsigned long treg;
89 int err = 0;
66 90
67 /* Always make any pending restarted system calls return -EINTR */ 91 /* Always make any pending restarted system calls return -EINTR */
68 current_thread_info()->restart_block.fn = do_no_restart_syscall; 92 current_thread_info()->restart_block.fn = do_no_restart_syscall;
69 93
70 err |= __get_user(regs->cp0_epc, &sc->sc_pc); 94 err |= __get_user(regs->cp0_epc, &sc->sc_pc);
95#ifdef CONFIG_32BIT
71 err |= __get_user(regs->hi, &sc->sc_mdhi); 96 err |= __get_user(regs->hi, &sc->sc_mdhi);
72 err |= __get_user(regs->lo, &sc->sc_mdlo); 97 err |= __get_user(regs->lo, &sc->sc_mdlo);
98 if (cpu_has_dsp) {
99 err |= __get_user(treg, &sc->sc_hi1); mthi1(treg);
100 err |= __get_user(treg, &sc->sc_lo1); mtlo1(treg);
101 err |= __get_user(treg, &sc->sc_hi2); mthi2(treg);
102 err |= __get_user(treg, &sc->sc_lo2); mtlo2(treg);
103 err |= __get_user(treg, &sc->sc_hi3); mthi3(treg);
104 err |= __get_user(treg, &sc->sc_lo3); mtlo3(treg);
105 err |= __get_user(treg, &sc->sc_dsp); wrdsp(treg, DSP_MASK);
106 }
107#endif
108#ifdef CONFIG_64BIT
109 err |= __get_user(regs->hi, &sc->sc_hi[0]);
110 err |= __get_user(regs->lo, &sc->sc_lo[0]);
111 if (cpu_has_dsp) {
112 err |= __get_user(treg, &sc->sc_hi[1]); mthi1(treg);
113 err |= __get_user(treg, &sc->sc_lo[1]); mthi1(treg);
114 err |= __get_user(treg, &sc->sc_hi[2]); mthi2(treg);
115 err |= __get_user(treg, &sc->sc_lo[2]); mthi2(treg);
116 err |= __get_user(treg, &sc->sc_hi[3]); mthi3(treg);
117 err |= __get_user(treg, &sc->sc_lo[3]); mthi3(treg);
118 err |= __get_user(treg, &sc->sc_dsp); wrdsp(treg, DSP_MASK);
119 }
120#endif
73 121
74#define restore_gp_reg(i) do { \ 122#define restore_gp_reg(i) do { \
75 err |= __get_user(regs->regs[i], &sc->sc_regs[i]); \ 123 err |= __get_user(regs->regs[i], &sc->sc_regs[i]); \
diff --git a/arch/mips/kernel/signal.c b/arch/mips/kernel/signal.c
index eb127230cc9a..8504febf8b22 100644
--- a/arch/mips/kernel/signal.c
+++ b/arch/mips/kernel/signal.c
@@ -21,6 +21,7 @@
21#include <linux/unistd.h> 21#include <linux/unistd.h>
22#include <linux/compiler.h> 22#include <linux/compiler.h>
23 23
24#include <asm/abi.h>
24#include <asm/asm.h> 25#include <asm/asm.h>
25#include <linux/bitops.h> 26#include <linux/bitops.h>
26#include <asm/cacheflush.h> 27#include <asm/cacheflush.h>
@@ -36,7 +37,7 @@
36 37
37#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) 38#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
38 39
39static int do_signal(sigset_t *oldset, struct pt_regs *regs); 40int do_signal(sigset_t *oldset, struct pt_regs *regs);
40 41
41/* 42/*
42 * Atomically swap in the new signal mask, and wait for a signal. 43 * Atomically swap in the new signal mask, and wait for a signal.
@@ -216,7 +217,7 @@ _sys_sigreturn(nabi_no_regargs struct pt_regs regs)
216badframe: 217badframe:
217 force_sig(SIGSEGV, current); 218 force_sig(SIGSEGV, current);
218} 219}
219#endif 220#endif /* CONFIG_TRAD_SIGNALS */
220 221
221save_static_function(sys_rt_sigreturn); 222save_static_function(sys_rt_sigreturn);
222__attribute_used__ noinline static void 223__attribute_used__ noinline static void
@@ -262,7 +263,7 @@ badframe:
262} 263}
263 264
264#ifdef CONFIG_TRAD_SIGNALS 265#ifdef CONFIG_TRAD_SIGNALS
265static void inline setup_frame(struct k_sigaction * ka, struct pt_regs *regs, 266void setup_frame(struct k_sigaction * ka, struct pt_regs *regs,
266 int signr, sigset_t *set) 267 int signr, sigset_t *set)
267{ 268{
268 struct sigframe *frame; 269 struct sigframe *frame;
@@ -318,7 +319,7 @@ give_sigsegv:
318} 319}
319#endif 320#endif
320 321
321static void inline setup_rt_frame(struct k_sigaction * ka, struct pt_regs *regs, 322void setup_rt_frame(struct k_sigaction * ka, struct pt_regs *regs,
322 int signr, sigset_t *set, siginfo_t *info) 323 int signr, sigset_t *set, siginfo_t *info)
323{ 324{
324 struct rt_sigframe *frame; 325 struct rt_sigframe *frame;
@@ -410,22 +411,10 @@ static inline void handle_signal(unsigned long sig, siginfo_t *info,
410 411
411 regs->regs[0] = 0; /* Don't deal with this again. */ 412 regs->regs[0] = 0; /* Don't deal with this again. */
412 413
413#ifdef CONFIG_TRAD_SIGNALS 414 if (sig_uses_siginfo(ka))
414 if (ka->sa.sa_flags & SA_SIGINFO) { 415 current->thread.abi->setup_rt_frame(ka, regs, sig, oldset, info);
415#else
416 if (1) {
417#endif
418#ifdef CONFIG_MIPS32_N32
419 if ((current->thread.mflags & MF_ABI_MASK) == MF_N32)
420 setup_rt_frame_n32 (ka, regs, sig, oldset, info);
421 else
422#endif
423 setup_rt_frame(ka, regs, sig, oldset, info);
424 }
425#ifdef CONFIG_TRAD_SIGNALS
426 else 416 else
427 setup_frame(ka, regs, sig, oldset); 417 current->thread.abi->setup_frame(ka, regs, sig, oldset);
428#endif
429 418
430 spin_lock_irq(&current->sighand->siglock); 419 spin_lock_irq(&current->sighand->siglock);
431 sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask); 420 sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
@@ -435,21 +424,12 @@ static inline void handle_signal(unsigned long sig, siginfo_t *info,
435 spin_unlock_irq(&current->sighand->siglock); 424 spin_unlock_irq(&current->sighand->siglock);
436} 425}
437 426
438extern int do_signal32(sigset_t *oldset, struct pt_regs *regs); 427int do_signal(sigset_t *oldset, struct pt_regs *regs)
439extern int do_irix_signal(sigset_t *oldset, struct pt_regs *regs);
440
441static int do_signal(sigset_t *oldset, struct pt_regs *regs)
442{ 428{
443 struct k_sigaction ka; 429 struct k_sigaction ka;
444 siginfo_t info; 430 siginfo_t info;
445 int signr; 431 int signr;
446 432
447#ifdef CONFIG_BINFMT_ELF32
448 if ((current->thread.mflags & MF_ABI_MASK) == MF_O32) {
449 return do_signal32(oldset, regs);
450 }
451#endif
452
453 /* 433 /*
454 * We want the common case to go fast, which is why we may in certain 434 * We want the common case to go fast, which is why we may in certain
455 * cases get here from kernel mode. Just return without doing anything 435 * cases get here from kernel mode. Just return without doing anything
@@ -501,18 +481,6 @@ asmlinkage void do_notify_resume(struct pt_regs *regs, sigset_t *oldset,
501{ 481{
502 /* deal with pending signal delivery */ 482 /* deal with pending signal delivery */
503 if (thread_info_flags & _TIF_SIGPENDING) { 483 if (thread_info_flags & _TIF_SIGPENDING) {
504#ifdef CONFIG_BINFMT_ELF32 484 current->thread.abi->do_signal(oldset, regs);
505 if (likely((current->thread.mflags & MF_ABI_MASK) == MF_O32)) {
506 do_signal32(oldset, regs);
507 return;
508 }
509#endif
510#ifdef CONFIG_BINFMT_IRIX
511 if (unlikely(current->personality != PER_LINUX)) {
512 do_irix_signal(oldset, regs);
513 return;
514 }
515#endif
516 do_signal(oldset, regs);
517 } 485 }
518} 486}
diff --git a/arch/mips/kernel/signal32.c b/arch/mips/kernel/signal32.c
index 5e7d0fa02672..8639e24732a5 100644
--- a/arch/mips/kernel/signal32.c
+++ b/arch/mips/kernel/signal32.c
@@ -21,6 +21,7 @@
21#include <linux/suspend.h> 21#include <linux/suspend.h>
22#include <linux/compiler.h> 22#include <linux/compiler.h>
23 23
24#include <asm/abi.h>
24#include <asm/asm.h> 25#include <asm/asm.h>
25#include <linux/bitops.h> 26#include <linux/bitops.h>
26#include <asm/cacheflush.h> 27#include <asm/cacheflush.h>
@@ -334,8 +335,9 @@ asmlinkage int sys32_sigaltstack(nabi_no_regargs struct pt_regs regs)
334 335
335static int restore_sigcontext32(struct pt_regs *regs, struct sigcontext32 *sc) 336static int restore_sigcontext32(struct pt_regs *regs, struct sigcontext32 *sc)
336{ 337{
338 u32 used_math;
337 int err = 0; 339 int err = 0;
338 __u32 used_math; 340 s32 treg;
339 341
340 /* Always make any pending restarted system calls return -EINTR */ 342 /* Always make any pending restarted system calls return -EINTR */
341 current_thread_info()->restart_block.fn = do_no_restart_syscall; 343 current_thread_info()->restart_block.fn = do_no_restart_syscall;
@@ -343,6 +345,15 @@ static int restore_sigcontext32(struct pt_regs *regs, struct sigcontext32 *sc)
343 err |= __get_user(regs->cp0_epc, &sc->sc_pc); 345 err |= __get_user(regs->cp0_epc, &sc->sc_pc);
344 err |= __get_user(regs->hi, &sc->sc_mdhi); 346 err |= __get_user(regs->hi, &sc->sc_mdhi);
345 err |= __get_user(regs->lo, &sc->sc_mdlo); 347 err |= __get_user(regs->lo, &sc->sc_mdlo);
348 if (cpu_has_dsp) {
349 err |= __get_user(treg, &sc->sc_hi1); mthi1(treg);
350 err |= __get_user(treg, &sc->sc_lo1); mtlo1(treg);
351 err |= __get_user(treg, &sc->sc_hi2); mthi2(treg);
352 err |= __get_user(treg, &sc->sc_lo2); mtlo2(treg);
353 err |= __get_user(treg, &sc->sc_hi3); mthi3(treg);
354 err |= __get_user(treg, &sc->sc_lo3); mtlo3(treg);
355 err |= __get_user(treg, &sc->sc_dsp); wrdsp(treg, DSP_MASK);
356 }
346 357
347#define restore_gp_reg(i) do { \ 358#define restore_gp_reg(i) do { \
348 err |= __get_user(regs->regs[i], &sc->sc_regs[i]); \ 359 err |= __get_user(regs->regs[i], &sc->sc_regs[i]); \
@@ -562,8 +573,15 @@ static inline int setup_sigcontext32(struct pt_regs *regs,
562 573
563 err |= __put_user(regs->hi, &sc->sc_mdhi); 574 err |= __put_user(regs->hi, &sc->sc_mdhi);
564 err |= __put_user(regs->lo, &sc->sc_mdlo); 575 err |= __put_user(regs->lo, &sc->sc_mdlo);
565 err |= __put_user(regs->cp0_cause, &sc->sc_cause); 576 if (cpu_has_dsp) {
566 err |= __put_user(regs->cp0_badvaddr, &sc->sc_badvaddr); 577 err |= __put_user(rddsp(DSP_MASK), &sc->sc_hi1);
578 err |= __put_user(mfhi1(), &sc->sc_hi1);
579 err |= __put_user(mflo1(), &sc->sc_lo1);
580 err |= __put_user(mfhi2(), &sc->sc_hi2);
581 err |= __put_user(mflo2(), &sc->sc_lo2);
582 err |= __put_user(mfhi3(), &sc->sc_hi3);
583 err |= __put_user(mflo3(), &sc->sc_lo3);
584 }
567 585
568 err |= __put_user(!!used_math(), &sc->sc_used_math); 586 err |= __put_user(!!used_math(), &sc->sc_used_math);
569 587
@@ -613,7 +631,7 @@ static inline void *get_sigframe(struct k_sigaction *ka, struct pt_regs *regs,
613 return (void *)((sp - frame_size) & ALMASK); 631 return (void *)((sp - frame_size) & ALMASK);
614} 632}
615 633
616static inline void setup_frame(struct k_sigaction * ka, struct pt_regs *regs, 634void setup_frame_32(struct k_sigaction * ka, struct pt_regs *regs,
617 int signr, sigset_t *set) 635 int signr, sigset_t *set)
618{ 636{
619 struct sigframe *frame; 637 struct sigframe *frame;
@@ -666,9 +684,7 @@ give_sigsegv:
666 force_sigsegv(signr, current); 684 force_sigsegv(signr, current);
667} 685}
668 686
669static inline void setup_rt_frame(struct k_sigaction * ka, 687void setup_rt_frame_32(struct k_sigaction * ka, struct pt_regs *regs, int signr, sigset_t *set, siginfo_t *info)
670 struct pt_regs *regs, int signr,
671 sigset_t *set, siginfo_t *info)
672{ 688{
673 struct rt_sigframe32 *frame; 689 struct rt_sigframe32 *frame;
674 int err = 0; 690 int err = 0;
@@ -759,9 +775,9 @@ static inline void handle_signal(unsigned long sig, siginfo_t *info,
759 regs->regs[0] = 0; /* Don't deal with this again. */ 775 regs->regs[0] = 0; /* Don't deal with this again. */
760 776
761 if (ka->sa.sa_flags & SA_SIGINFO) 777 if (ka->sa.sa_flags & SA_SIGINFO)
762 setup_rt_frame(ka, regs, sig, oldset, info); 778 current->thread.abi->setup_rt_frame(ka, regs, sig, oldset, info);
763 else 779 else
764 setup_frame(ka, regs, sig, oldset); 780 current->thread.abi->setup_frame(ka, regs, sig, oldset);
765 781
766 spin_lock_irq(&current->sighand->siglock); 782 spin_lock_irq(&current->sighand->siglock);
767 sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask); 783 sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c
index b3ecd02757cb..9419a3542c24 100644
--- a/arch/mips/kernel/traps.c
+++ b/arch/mips/kernel/traps.c
@@ -25,6 +25,7 @@
25#include <asm/branch.h> 25#include <asm/branch.h>
26#include <asm/break.h> 26#include <asm/break.h>
27#include <asm/cpu.h> 27#include <asm/cpu.h>
28#include <asm/dsp.h>
28#include <asm/fpu.h> 29#include <asm/fpu.h>
29#include <asm/module.h> 30#include <asm/module.h>
30#include <asm/pgtable.h> 31#include <asm/pgtable.h>
@@ -54,6 +55,7 @@ extern asmlinkage void handle_tr(void);
54extern asmlinkage void handle_fpe(void); 55extern asmlinkage void handle_fpe(void);
55extern asmlinkage void handle_mdmx(void); 56extern asmlinkage void handle_mdmx(void);
56extern asmlinkage void handle_watch(void); 57extern asmlinkage void handle_watch(void);
58extern asmlinkage void handle_dsp(void);
57extern asmlinkage void handle_mcheck(void); 59extern asmlinkage void handle_mcheck(void);
58extern asmlinkage void handle_reserved(void); 60extern asmlinkage void handle_reserved(void);
59 61
@@ -775,6 +777,14 @@ asmlinkage void do_mcheck(struct pt_regs *regs)
775 (regs->cp0_status & ST0_TS) ? "" : "not "); 777 (regs->cp0_status & ST0_TS) ? "" : "not ");
776} 778}
777 779
780asmlinkage void do_dsp(struct pt_regs *regs)
781{
782 if (cpu_has_dsp)
783 panic("Unexpected DSP exception\n");
784
785 force_sig(SIGILL, current);
786}
787
778asmlinkage void do_reserved(struct pt_regs *regs) 788asmlinkage void do_reserved(struct pt_regs *regs)
779{ 789{
780 /* 790 /*
@@ -984,9 +994,12 @@ void __init per_cpu_trap_init(void)
984#endif 994#endif
985 if (current_cpu_data.isa_level == MIPS_CPU_ISA_IV) 995 if (current_cpu_data.isa_level == MIPS_CPU_ISA_IV)
986 status_set |= ST0_XX; 996 status_set |= ST0_XX;
987 change_c0_status(ST0_CU|ST0_FR|ST0_BEV|ST0_TS|ST0_KX|ST0_SX|ST0_UX, 997 change_c0_status(ST0_CU|ST0_MX|ST0_FR|ST0_BEV|ST0_TS|ST0_KX|ST0_SX|ST0_UX,
988 status_set); 998 status_set);
989 999
1000 if (cpu_has_dsp)
1001 set_c0_status(ST0_MX);
1002
990 /* 1003 /*
991 * Some MIPS CPUs have a dedicated interrupt vector which reduces the 1004 * Some MIPS CPUs have a dedicated interrupt vector which reduces the
992 * interrupt processing overhead. Use it where available. 1005 * interrupt processing overhead. Use it where available.
@@ -1078,21 +1091,6 @@ void __init trap_init(void)
1078 set_except_vector(11, handle_cpu); 1091 set_except_vector(11, handle_cpu);
1079 set_except_vector(12, handle_ov); 1092 set_except_vector(12, handle_ov);
1080 set_except_vector(13, handle_tr); 1093 set_except_vector(13, handle_tr);
1081 set_except_vector(22, handle_mdmx);
1082
1083 if (cpu_has_fpu && !cpu_has_nofpuex)
1084 set_except_vector(15, handle_fpe);
1085
1086 if (cpu_has_mcheck)
1087 set_except_vector(24, handle_mcheck);
1088
1089 if (cpu_has_vce)
1090 /* Special exception: R4[04]00 uses also the divec space. */
1091 memcpy((void *)(CAC_BASE + 0x180), &except_vec3_r4000, 0x100);
1092 else if (cpu_has_4kex)
1093 memcpy((void *)(CAC_BASE + 0x180), &except_vec3_generic, 0x80);
1094 else
1095 memcpy((void *)(CAC_BASE + 0x080), &except_vec3_generic, 0x80);
1096 1094
1097 if (current_cpu_data.cputype == CPU_R6000 || 1095 if (current_cpu_data.cputype == CPU_R6000 ||
1098 current_cpu_data.cputype == CPU_R6000A) { 1096 current_cpu_data.cputype == CPU_R6000A) {
@@ -1108,6 +1106,25 @@ void __init trap_init(void)
1108 //set_except_vector(15, handle_ndc); 1106 //set_except_vector(15, handle_ndc);
1109 } 1107 }
1110 1108
1109 if (cpu_has_fpu && !cpu_has_nofpuex)
1110 set_except_vector(15, handle_fpe);
1111
1112 set_except_vector(22, handle_mdmx);
1113
1114 if (cpu_has_mcheck)
1115 set_except_vector(24, handle_mcheck);
1116
1117 if (cpu_has_dsp)
1118 set_except_vector(26, handle_dsp);
1119
1120 if (cpu_has_vce)
1121 /* Special exception: R4[04]00 uses also the divec space. */
1122 memcpy((void *)(CAC_BASE + 0x180), &except_vec3_r4000, 0x100);
1123 else if (cpu_has_4kex)
1124 memcpy((void *)(CAC_BASE + 0x180), &except_vec3_generic, 0x80);
1125 else
1126 memcpy((void *)(CAC_BASE + 0x080), &except_vec3_generic, 0x80);
1127
1111 signal_init(); 1128 signal_init();
1112#ifdef CONFIG_MIPS32_COMPAT 1129#ifdef CONFIG_MIPS32_COMPAT
1113 signal32_init(); 1130 signal32_init();