aboutsummaryrefslogtreecommitdiffstats
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
parent10f650db1bcc193ea07d4f8c2f07315da38ea0c4 (diff)
Support the MIPS32 / MIPS64 DSP ASE.
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
-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
-rw-r--r--include/asm-mips/abi.h25
-rw-r--r--include/asm-mips/cpu-features.h4
-rw-r--r--include/asm-mips/cpu.h2
-rw-r--r--include/asm-mips/dsp.h83
-rw-r--r--include/asm-mips/elf.h81
-rw-r--r--include/asm-mips/inst.h8
-rw-r--r--include/asm-mips/mach-ip22/cpu-feature-overrides.h2
-rw-r--r--include/asm-mips/mach-ip27/cpu-feature-overrides.h1
-rw-r--r--include/asm-mips/mach-ip32/cpu-feature-overrides.h1
-rw-r--r--include/asm-mips/mach-ja/cpu-feature-overrides.h1
-rw-r--r--include/asm-mips/mach-ocelot3/cpu-feature-overrides.h1
-rw-r--r--include/asm-mips/mach-rm200/cpu-feature-overrides.h1
-rw-r--r--include/asm-mips/mach-sibyte/cpu-feature-overrides.h1
-rw-r--r--include/asm-mips/mach-yosemite/cpu-feature-overrides.h1
-rw-r--r--include/asm-mips/mipsregs.h287
-rw-r--r--include/asm-mips/processor.h22
-rw-r--r--include/asm-mips/ptrace.h4
-rw-r--r--include/asm-mips/sigcontext.h60
-rw-r--r--include/asm-mips/signal.h29
-rw-r--r--include/asm-mips/system.h11
34 files changed, 876 insertions, 139 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();
diff --git a/include/asm-mips/abi.h b/include/asm-mips/abi.h
new file mode 100644
index 000000000000..2e7e651c3e3f
--- /dev/null
+++ b/include/asm-mips/abi.h
@@ -0,0 +1,25 @@
1/*
2 * This file is subject to the terms and conditions of the GNU General Public
3 * License. See the file "COPYING" in the main directory of this archive
4 * for more details.
5 *
6 * Copyright (C) 2005 by Ralf Baechle
7 * Copyright (C) 2005 MIPS Technologies, Inc.
8 */
9#ifndef _ASM_ABI_H
10#define _ASM_ABI_H
11
12#include <asm/signal.h>
13#include <asm/siginfo.h>
14
15struct mips_abi {
16 int (* const do_signal)(sigset_t *oldset, struct pt_regs *regs);
17 int (* const setup_frame)(struct k_sigaction * ka,
18 struct pt_regs *regs, int signr,
19 sigset_t *set);
20 int (* const setup_rt_frame)(struct k_sigaction * ka,
21 struct pt_regs *regs, int signr,
22 sigset_t *set, siginfo_t *info);
23};
24
25#endif /* _ASM_ABI_H */
diff --git a/include/asm-mips/cpu-features.h b/include/asm-mips/cpu-features.h
index 012deda63e68..4930824a43aa 100644
--- a/include/asm-mips/cpu-features.h
+++ b/include/asm-mips/cpu-features.h
@@ -105,6 +105,10 @@
105#endif 105#endif
106#endif 106#endif
107 107
108#ifndef cpu_has_dsp
109#define cpu_has_dsp (cpu_data[0].ases & MIPS_ASE_DSP)
110#endif
111
108/* 112/*
109 * Certain CPUs may throw bizarre exceptions if not the whole cacheline 113 * Certain CPUs may throw bizarre exceptions if not the whole cacheline
110 * contains valid instructions. For these we ensure proper alignment of 114 * contains valid instructions. For these we ensure proper alignment of
diff --git a/include/asm-mips/cpu.h b/include/asm-mips/cpu.h
index a4f85a279c52..2a109a5e0932 100644
--- a/include/asm-mips/cpu.h
+++ b/include/asm-mips/cpu.h
@@ -77,6 +77,7 @@
77#define PRID_IMP_4KEMPR2 0x9100 77#define PRID_IMP_4KEMPR2 0x9100
78#define PRID_IMP_4KSD 0x9200 78#define PRID_IMP_4KSD 0x9200
79#define PRID_IMP_24K 0x9300 79#define PRID_IMP_24K 0x9300
80#define PRID_IMP_24KE 0x9600
80 81
81#define PRID_IMP_UNKNOWN 0xff00 82#define PRID_IMP_UNKNOWN 0xff00
82 83
@@ -232,5 +233,6 @@
232#define MIPS_ASE_MDMX 0x00000002 /* MIPS digital media extension */ 233#define MIPS_ASE_MDMX 0x00000002 /* MIPS digital media extension */
233#define MIPS_ASE_MIPS3D 0x00000004 /* MIPS-3D */ 234#define MIPS_ASE_MIPS3D 0x00000004 /* MIPS-3D */
234#define MIPS_ASE_SMARTMIPS 0x00000008 /* SmartMIPS */ 235#define MIPS_ASE_SMARTMIPS 0x00000008 /* SmartMIPS */
236#define MIPS_ASE_DSP 0x00000010 /* Signal Processing ASE */
235 237
236#endif /* _ASM_CPU_H */ 238#endif /* _ASM_CPU_H */
diff --git a/include/asm-mips/dsp.h b/include/asm-mips/dsp.h
new file mode 100644
index 000000000000..50f556bb4978
--- /dev/null
+++ b/include/asm-mips/dsp.h
@@ -0,0 +1,83 @@
1/*
2 * Copyright (C) 2005 Mips Technologies
3 * Author: Chris Dearman, chris@mips.com derived from fpu.h
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version.
9 */
10#ifndef _ASM_DSP_H
11#define _ASM_DSP_H
12
13#include <asm/cpu.h>
14#include <asm/cpu-features.h>
15#include <asm/hazards.h>
16#include <asm/mipsregs.h>
17
18#define DSP_DEFAULT 0x00000000
19#define DSP_MASK 0x1f
20
21#define __enable_dsp_hazard() \
22do { \
23 asm("_ehb"); \
24} while (0)
25
26static inline void __init_dsp(void)
27{
28 mthi1(0);
29 mtlo1(0);
30 mthi2(0);
31 mtlo2(0);
32 mthi3(0);
33 mtlo3(0);
34 wrdsp(DSP_DEFAULT, DSP_MASK);
35}
36
37static inline void init_dsp(void)
38{
39 if (cpu_has_dsp)
40 __init_dsp();
41}
42
43#define __save_dsp(tsk) \
44do { \
45 tsk->thread.dsp.dspr[0] = mfhi1(); \
46 tsk->thread.dsp.dspr[1] = mflo1(); \
47 tsk->thread.dsp.dspr[2] = mfhi2(); \
48 tsk->thread.dsp.dspr[3] = mflo2(); \
49 tsk->thread.dsp.dspr[4] = mfhi3(); \
50 tsk->thread.dsp.dspr[5] = mflo3(); \
51} while (0)
52
53#define save_dsp(tsk) \
54do { \
55 if (cpu_has_dsp) \
56 __save_dsp(tsk); \
57} while (0)
58
59#define __restore_dsp(tsk) \
60do { \
61 mthi1(tsk->thread.dsp.dspr[0]); \
62 mtlo1(tsk->thread.dsp.dspr[1]); \
63 mthi2(tsk->thread.dsp.dspr[2]); \
64 mtlo2(tsk->thread.dsp.dspr[3]); \
65 mthi3(tsk->thread.dsp.dspr[4]); \
66 mtlo3(tsk->thread.dsp.dspr[5]); \
67} while (0)
68
69#define restore_dsp(tsk) \
70do { \
71 if (cpu_has_dsp) \
72 __restore_dsp(tsk); \
73} while (0)
74
75#define __get_dsp_regs(tsk) \
76({ \
77 if (tsk == current) \
78 __save_dsp(current); \
79 \
80 tsk->thread.dsp.dspr; \
81})
82
83#endif /* _ASM_DSP_H */
diff --git a/include/asm-mips/elf.h b/include/asm-mips/elf.h
index bb031f3cd4db..a4db9ec95665 100644
--- a/include/asm-mips/elf.h
+++ b/include/asm-mips/elf.h
@@ -193,33 +193,76 @@ typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG];
193 193
194#ifdef __KERNEL__ 194#ifdef __KERNEL__
195 195
196struct mips_abi;
197
198extern struct mips_abi mips_abi;
199extern struct mips_abi mips_abi_32;
200extern struct mips_abi mips_abi_n32;
201
196#ifdef CONFIG_32BIT 202#ifdef CONFIG_32BIT
197 203
198#define SET_PERSONALITY(ex, ibcs2) \ 204#define SET_PERSONALITY(ex, ibcs2) \
199do { \ 205do { \
200 if (ibcs2) \ 206 if (ibcs2) \
201 set_personality(PER_SVR4); \ 207 set_personality(PER_SVR4); \
202 set_personality(PER_LINUX); \ 208 set_personality(PER_LINUX); \
209 \
210 current->thread.abi = &mips_abi; \
203} while (0) 211} while (0)
204 212
205#endif /* CONFIG_32BIT */ 213#endif /* CONFIG_32BIT */
206 214
207#ifdef CONFIG_64BIT 215#ifdef CONFIG_64BIT
208 216
209#define SET_PERSONALITY(ex, ibcs2) \ 217#ifdef CONFIG_MIPS32_N32
210do { current->thread.mflags &= ~MF_ABI_MASK; \ 218#define __SET_PERSONALITY32_N32() \
211 if ((ex).e_ident[EI_CLASS] == ELFCLASS32) { \ 219 do { \
212 if ((((ex).e_flags & EF_MIPS_ABI2) != 0) && \ 220 current->thread.mflags |= MF_N32; \
213 ((ex).e_flags & EF_MIPS_ABI) == 0) \ 221 current->thread.abi = &mips_abi_n32; \
214 current->thread.mflags |= MF_N32; \ 222 } while (0)
215 else \ 223#else
216 current->thread.mflags |= MF_O32; \ 224#define __SET_PERSONALITY32_N32() \
217 } else \ 225 do { } while (0)
218 current->thread.mflags |= MF_N64; \ 226#endif
219 if (ibcs2) \ 227
220 set_personality(PER_SVR4); \ 228#ifdef CONFIG_MIPS32_O32
221 else if (current->personality != PER_LINUX32) \ 229#define __SET_PERSONALITY32_O32() \
222 set_personality(PER_LINUX); \ 230 do { \
231 current->thread.mflags |= MF_O32; \
232 current->thread.abi = &mips_abi_32; \
233 } while (0)
234#else
235#define __SET_PERSONALITY32_O32() \
236 do { } while (0)
237#endif
238
239#ifdef CONFIG_MIPS32_COMPAT
240#define __SET_PERSONALITY32(ex) \
241do { \
242 if ((((ex).e_flags & EF_MIPS_ABI2) != 0) && \
243 ((ex).e_flags & EF_MIPS_ABI) == 0) \
244 __SET_PERSONALITY32_N32(); \
245 else \
246 __SET_PERSONALITY32_O32(); \
247} while (0)
248#else
249#define __SET_PERSONALITY32(ex) do { } while (0)
250#endif
251
252#define SET_PERSONALITY(ex, ibcs2) \
253do { \
254 current->thread.mflags &= ~MF_ABI_MASK; \
255 if ((ex).e_ident[EI_CLASS] == ELFCLASS32) \
256 __SET_PERSONALITY32(ex); \
257 else { \
258 current->thread.mflags |= MF_N64; \
259 current->thread.abi = &mips_abi; \
260 } \
261 \
262 if (ibcs2) \
263 set_personality(PER_SVR4); \
264 else if (current->personality != PER_LINUX32) \
265 set_personality(PER_LINUX); \
223} while (0) 266} while (0)
224 267
225#endif /* CONFIG_64BIT */ 268#endif /* CONFIG_64BIT */
diff --git a/include/asm-mips/inst.h b/include/asm-mips/inst.h
index df912c2b381f..e0745f4ff624 100644
--- a/include/asm-mips/inst.h
+++ b/include/asm-mips/inst.h
@@ -62,10 +62,10 @@ enum rt_op {
62 spimi_op, unused_rt_op_0x05, unused_rt_op_0x06, unused_rt_op_0x07, 62 spimi_op, unused_rt_op_0x05, unused_rt_op_0x06, unused_rt_op_0x07,
63 tgei_op, tgeiu_op, tlti_op, tltiu_op, 63 tgei_op, tgeiu_op, tlti_op, tltiu_op,
64 teqi_op, unused_0x0d_rt_op, tnei_op, unused_0x0f_rt_op, 64 teqi_op, unused_0x0d_rt_op, tnei_op, unused_0x0f_rt_op,
65 bltzal_op, bgezal_op, bltzall_op, bgezall_op 65 bltzal_op, bgezal_op, bltzall_op, bgezall_op,
66 /* 66 rt_op_0x14, rt_op_0x15, rt_op_0x16, rt_op_0x17,
67 * The others (0x14 - 0x1f) are unused. 67 rt_op_0x18, rt_op_0x19, rt_op_0x1a, rt_op_0x1b,
68 */ 68 bposge32_op, rt_op_0x1d, rt_op_0x1e, rt_op_0x1f
69}; 69};
70 70
71/* 71/*
diff --git a/include/asm-mips/mach-ip22/cpu-feature-overrides.h b/include/asm-mips/mach-ip22/cpu-feature-overrides.h
index 3c8896d9b133..a115940bd684 100644
--- a/include/asm-mips/mach-ip22/cpu-feature-overrides.h
+++ b/include/asm-mips/mach-ip22/cpu-feature-overrides.h
@@ -23,6 +23,8 @@
23#define cpu_has_dc_aliases (PAGE_SIZE < 0x4000) 23#define cpu_has_dc_aliases (PAGE_SIZE < 0x4000)
24#define cpu_has_ic_fills_f_dc 0 24#define cpu_has_ic_fills_f_dc 0
25 25
26#define cpu_has_dsp 0
27
26#define cpu_has_nofpuex 0 28#define cpu_has_nofpuex 0
27#define cpu_has_64bits 1 29#define cpu_has_64bits 1
28 30
diff --git a/include/asm-mips/mach-ip27/cpu-feature-overrides.h b/include/asm-mips/mach-ip27/cpu-feature-overrides.h
index fe96d7358517..4c8a90051fd0 100644
--- a/include/asm-mips/mach-ip27/cpu-feature-overrides.h
+++ b/include/asm-mips/mach-ip27/cpu-feature-overrides.h
@@ -25,6 +25,7 @@
25#define cpu_has_vtag_icache 0 25#define cpu_has_vtag_icache 0
26#define cpu_has_dc_aliases 0 26#define cpu_has_dc_aliases 0
27#define cpu_has_ic_fills_f_dc 0 27#define cpu_has_ic_fills_f_dc 0
28#define cpu_has_dsp 0
28#define cpu_icache_snoops_remote_store 1 29#define cpu_icache_snoops_remote_store 1
29 30
30#define cpu_has_nofpuex 0 31#define cpu_has_nofpuex 0
diff --git a/include/asm-mips/mach-ip32/cpu-feature-overrides.h b/include/asm-mips/mach-ip32/cpu-feature-overrides.h
index 04713973c6c3..ab37fc1842ba 100644
--- a/include/asm-mips/mach-ip32/cpu-feature-overrides.h
+++ b/include/asm-mips/mach-ip32/cpu-feature-overrides.h
@@ -37,5 +37,6 @@
37#define cpu_has_ejtag 0 37#define cpu_has_ejtag 0
38#define cpu_has_vtag_icache 0 38#define cpu_has_vtag_icache 0
39#define cpu_has_ic_fills_f_dc 0 39#define cpu_has_ic_fills_f_dc 0
40#define cpu_has_dsp 0
40 41
41#endif /* __ASM_MACH_IP32_CPU_FEATURE_OVERRIDES_H */ 42#endif /* __ASM_MACH_IP32_CPU_FEATURE_OVERRIDES_H */
diff --git a/include/asm-mips/mach-ja/cpu-feature-overrides.h b/include/asm-mips/mach-ja/cpu-feature-overrides.h
index ca57e7db98bb..310609c0f4ad 100644
--- a/include/asm-mips/mach-ja/cpu-feature-overrides.h
+++ b/include/asm-mips/mach-ja/cpu-feature-overrides.h
@@ -25,6 +25,7 @@
25#define cpu_has_vtag_icache 0 25#define cpu_has_vtag_icache 0
26#define cpu_has_dc_aliases 0 26#define cpu_has_dc_aliases 0
27#define cpu_has_ic_fills_f_dc 0 27#define cpu_has_ic_fills_f_dc 0
28#define cpu_has_dsp 0
28#define cpu_icache_snoops_remote_store 0 29#define cpu_icache_snoops_remote_store 0
29 30
30#define cpu_has_nofpuex 0 31#define cpu_has_nofpuex 0
diff --git a/include/asm-mips/mach-ocelot3/cpu-feature-overrides.h b/include/asm-mips/mach-ocelot3/cpu-feature-overrides.h
index 7473512384bc..1812fc0408d3 100644
--- a/include/asm-mips/mach-ocelot3/cpu-feature-overrides.h
+++ b/include/asm-mips/mach-ocelot3/cpu-feature-overrides.h
@@ -28,6 +28,7 @@
28#define cpu_has_vtag_icache 0 28#define cpu_has_vtag_icache 0
29#define cpu_has_dc_aliases 0 29#define cpu_has_dc_aliases 0
30#define cpu_has_ic_fills_f_dc 0 30#define cpu_has_ic_fills_f_dc 0
31#define cpu_has_dsp 0
31#define cpu_icache_snoops_remote_store 0 32#define cpu_icache_snoops_remote_store 0
32 33
33#define cpu_has_nofpuex 0 34#define cpu_has_nofpuex 0
diff --git a/include/asm-mips/mach-rm200/cpu-feature-overrides.h b/include/asm-mips/mach-rm200/cpu-feature-overrides.h
index f48736032b2a..9b2a40524679 100644
--- a/include/asm-mips/mach-rm200/cpu-feature-overrides.h
+++ b/include/asm-mips/mach-rm200/cpu-feature-overrides.h
@@ -31,6 +31,7 @@
31#define cpu_has_vtag_icache 0 31#define cpu_has_vtag_icache 0
32#define cpu_has_dc_aliases (PAGE_SIZE < 0x4000) 32#define cpu_has_dc_aliases (PAGE_SIZE < 0x4000)
33#define cpu_has_ic_fills_f_dc 0 33#define cpu_has_ic_fills_f_dc 0
34#define cpu_has_dsp 0
34#define cpu_has_nofpuex 0 35#define cpu_has_nofpuex 0
35#define cpu_has_64bits 1 36#define cpu_has_64bits 1
36 37
diff --git a/include/asm-mips/mach-sibyte/cpu-feature-overrides.h b/include/asm-mips/mach-sibyte/cpu-feature-overrides.h
index a3a2cc6014b2..193a666cd131 100644
--- a/include/asm-mips/mach-sibyte/cpu-feature-overrides.h
+++ b/include/asm-mips/mach-sibyte/cpu-feature-overrides.h
@@ -25,6 +25,7 @@
25#define cpu_has_vtag_icache 1 25#define cpu_has_vtag_icache 1
26#define cpu_has_dc_aliases 0 26#define cpu_has_dc_aliases 0
27#define cpu_has_ic_fills_f_dc 0 27#define cpu_has_ic_fills_f_dc 0
28#define cpu_has_dsp 0
28#define cpu_icache_snoops_remote_store 0 29#define cpu_icache_snoops_remote_store 0
29 30
30#define cpu_has_nofpuex 0 31#define cpu_has_nofpuex 0
diff --git a/include/asm-mips/mach-yosemite/cpu-feature-overrides.h b/include/asm-mips/mach-yosemite/cpu-feature-overrides.h
index 58603e3daca6..63e94342e087 100644
--- a/include/asm-mips/mach-yosemite/cpu-feature-overrides.h
+++ b/include/asm-mips/mach-yosemite/cpu-feature-overrides.h
@@ -25,6 +25,7 @@
25#define cpu_has_vtag_icache 0 25#define cpu_has_vtag_icache 0
26#define cpu_has_dc_aliases 0 26#define cpu_has_dc_aliases 0
27#define cpu_has_ic_fills_f_dc 0 27#define cpu_has_ic_fills_f_dc 0
28#define cpu_has_dsp 0
28#define cpu_icache_snoops_remote_store 0 29#define cpu_icache_snoops_remote_store 0
29 30
30#define cpu_has_nofpuex 0 31#define cpu_has_nofpuex 0
diff --git a/include/asm-mips/mipsregs.h b/include/asm-mips/mipsregs.h
index 9b0ce451286e..1fad6ec1daa0 100644
--- a/include/asm-mips/mipsregs.h
+++ b/include/asm-mips/mipsregs.h
@@ -281,6 +281,11 @@
281#define ST0_DL (_ULCAST_(1) << 24) 281#define ST0_DL (_ULCAST_(1) << 24)
282 282
283/* 283/*
284 * Enable the MIPS DSP ASE
285 */
286#define ST0_MX 0x01000000
287
288/*
284 * Bitfields in the TX39 family CP0 Configuration Register 3 289 * Bitfields in the TX39 family CP0 Configuration Register 3
285 */ 290 */
286#define TX39_CONF_ICS_SHIFT 19 291#define TX39_CONF_ICS_SHIFT 19
@@ -510,6 +515,7 @@
510#define MIPS_CONF3_VINT (_ULCAST_(1) << 5) 515#define MIPS_CONF3_VINT (_ULCAST_(1) << 5)
511#define MIPS_CONF3_VEIC (_ULCAST_(1) << 6) 516#define MIPS_CONF3_VEIC (_ULCAST_(1) << 6)
512#define MIPS_CONF3_LPA (_ULCAST_(1) << 7) 517#define MIPS_CONF3_LPA (_ULCAST_(1) << 7)
518#define MIPS_CONF3_DSP (_ULCAST_(1) << 10)
513 519
514/* 520/*
515 * Bits in the MIPS32/64 coprocessor 1 (FPU) revision register. 521 * Bits in the MIPS32/64 coprocessor 1 (FPU) revision register.
@@ -986,6 +992,287 @@ do { \
986 : "=r" (__res)); \ 992 : "=r" (__res)); \
987 __res;}) 993 __res;})
988 994
995#define rddsp(mask) \
996({ \
997 unsigned int __res; \
998 \
999 __asm__ __volatile__( \
1000 " .set push \n" \
1001 " .set noat \n" \
1002 " # rddsp $1, %x1 \n" \
1003 " .word 0x7c000cb8 | (%x1 << 16) \n" \
1004 " move %0, $1 \n" \
1005 " .set pop \n" \
1006 : "=r" (__res) \
1007 : "i" (mask)); \
1008 __res; \
1009})
1010
1011#define wrdsp(val, mask) \
1012do { \
1013 unsigned int __res; \
1014 \
1015 __asm__ __volatile__( \
1016 " .set push \n" \
1017 " .set noat \n" \
1018 " move $1, %0 \n" \
1019 " # wrdsp $1, %x1 \n" \
1020 " .word 0x7c2004f8 | (%x1 << 15) \n" \
1021 " .set pop \n" \
1022 : \
1023 : "r" (val), "i" (mask)); \
1024 __res; \
1025} while (0)
1026
1027#if 0 /* Need DSP ASE capable assembler ... */
1028#define mflo0() ({ long mflo0; __asm__("mflo %0, $ac0" : "=r" (mflo0)); mflo0;})
1029#define mflo1() ({ long mflo1; __asm__("mflo %0, $ac1" : "=r" (mflo1)); mflo1;})
1030#define mflo2() ({ long mflo2; __asm__("mflo %0, $ac2" : "=r" (mflo2)); mflo2;})
1031#define mflo3() ({ long mflo3; __asm__("mflo %0, $ac3" : "=r" (mflo3)); mflo3;})
1032
1033#define mfhi0() ({ long mfhi0; __asm__("mfhi %0, $ac0" : "=r" (mfhi0)); mfhi0;})
1034#define mfhi1() ({ long mfhi1; __asm__("mfhi %0, $ac1" : "=r" (mfhi1)); mfhi1;})
1035#define mfhi2() ({ long mfhi2; __asm__("mfhi %0, $ac2" : "=r" (mfhi2)); mfhi2;})
1036#define mfhi3() ({ long mfhi3; __asm__("mfhi %0, $ac3" : "=r" (mfhi3)); mfhi3;})
1037
1038#define mtlo0(x) __asm__("mtlo %0, $ac0" ::"r" (x))
1039#define mtlo1(x) __asm__("mtlo %0, $ac1" ::"r" (x))
1040#define mtlo2(x) __asm__("mtlo %0, $ac2" ::"r" (x))
1041#define mtlo3(x) __asm__("mtlo %0, $ac3" ::"r" (x))
1042
1043#define mthi0(x) __asm__("mthi %0, $ac0" ::"r" (x))
1044#define mthi1(x) __asm__("mthi %0, $ac1" ::"r" (x))
1045#define mthi2(x) __asm__("mthi %0, $ac2" ::"r" (x))
1046#define mthi3(x) __asm__("mthi %0, $ac3" ::"r" (x))
1047
1048#else
1049
1050#define mfhi0() \
1051({ \
1052 unsigned long __treg; \
1053 \
1054 __asm__ __volatile__( \
1055 " .set push \n" \
1056 " .set noat \n" \
1057 " # mfhi %0, $ac0 \n" \
1058 " .word 0x00000810 \n" \
1059 " move %0, $1 \n" \
1060 " .set pop \n" \
1061 : "=r" (__treg)); \
1062 __treg; \
1063})
1064
1065#define mfhi1() \
1066({ \
1067 unsigned long __treg; \
1068 \
1069 __asm__ __volatile__( \
1070 " .set push \n" \
1071 " .set noat \n" \
1072 " # mfhi %0, $ac1 \n" \
1073 " .word 0x00200810 \n" \
1074 " move %0, $1 \n" \
1075 " .set pop \n" \
1076 : "=r" (__treg)); \
1077 __treg; \
1078})
1079
1080#define mfhi2() \
1081({ \
1082 unsigned long __treg; \
1083 \
1084 __asm__ __volatile__( \
1085 " .set push \n" \
1086 " .set noat \n" \
1087 " # mfhi %0, $ac2 \n" \
1088 " .word 0x00400810 \n" \
1089 " move %0, $1 \n" \
1090 " .set pop \n" \
1091 : "=r" (__treg)); \
1092 __treg; \
1093})
1094
1095#define mfhi3() \
1096({ \
1097 unsigned long __treg; \
1098 \
1099 __asm__ __volatile__( \
1100 " .set push \n" \
1101 " .set noat \n" \
1102 " # mfhi %0, $ac3 \n" \
1103 " .word 0x00600810 \n" \
1104 " move %0, $1 \n" \
1105 " .set pop \n" \
1106 : "=r" (__treg)); \
1107 __treg; \
1108})
1109
1110#define mflo0() \
1111({ \
1112 unsigned long __treg; \
1113 \
1114 __asm__ __volatile__( \
1115 " .set push \n" \
1116 " .set noat \n" \
1117 " # mflo %0, $ac0 \n" \
1118 " .word 0x00000812 \n" \
1119 " move %0, $1 \n" \
1120 " .set pop \n" \
1121 : "=r" (__treg)); \
1122 __treg; \
1123})
1124
1125#define mflo1() \
1126({ \
1127 unsigned long __treg; \
1128 \
1129 __asm__ __volatile__( \
1130 " .set push \n" \
1131 " .set noat \n" \
1132 " # mflo %0, $ac1 \n" \
1133 " .word 0x00200812 \n" \
1134 " move %0, $1 \n" \
1135 " .set pop \n" \
1136 : "=r" (__treg)); \
1137 __treg; \
1138})
1139
1140#define mflo2() \
1141({ \
1142 unsigned long __treg; \
1143 \
1144 __asm__ __volatile__( \
1145 " .set push \n" \
1146 " .set noat \n" \
1147 " # mflo %0, $ac2 \n" \
1148 " .word 0x00400812 \n" \
1149 " move %0, $1 \n" \
1150 " .set pop \n" \
1151 : "=r" (__treg)); \
1152 __treg; \
1153})
1154
1155#define mflo3() \
1156({ \
1157 unsigned long __treg; \
1158 \
1159 __asm__ __volatile__( \
1160 " .set push \n" \
1161 " .set noat \n" \
1162 " # mflo %0, $ac3 \n" \
1163 " .word 0x00600812 \n" \
1164 " move %0, $1 \n" \
1165 " .set pop \n" \
1166 : "=r" (__treg)); \
1167 __treg; \
1168})
1169
1170#define mthi0(x) \
1171do { \
1172 __asm__ __volatile__( \
1173 " .set push \n" \
1174 " .set noat \n" \
1175 " move $1, %0 \n" \
1176 " # mthi $1, $ac0 \n" \
1177 " .word 0x00200011 \n" \
1178 " .set pop \n" \
1179 : \
1180 : "r" (x)); \
1181} while (0)
1182
1183#define mthi1(x) \
1184do { \
1185 __asm__ __volatile__( \
1186 " .set push \n" \
1187 " .set noat \n" \
1188 " move $1, %0 \n" \
1189 " # mthi $1, $ac1 \n" \
1190 " .word 0x00200811 \n" \
1191 " .set pop \n" \
1192 : \
1193 : "r" (x)); \
1194} while (0)
1195
1196#define mthi2(x) \
1197do { \
1198 __asm__ __volatile__( \
1199 " .set push \n" \
1200 " .set noat \n" \
1201 " move $1, %0 \n" \
1202 " # mthi $1, $ac2 \n" \
1203 " .word 0x00201011 \n" \
1204 " .set pop \n" \
1205 : \
1206 : "r" (x)); \
1207} while (0)
1208
1209#define mthi3(x) \
1210do { \
1211 __asm__ __volatile__( \
1212 " .set push \n" \
1213 " .set noat \n" \
1214 " move $1, %0 \n" \
1215 " # mthi $1, $ac3 \n" \
1216 " .word 0x00201811 \n" \
1217 " .set pop \n" \
1218 : \
1219 : "r" (x)); \
1220} while (0)
1221
1222#define mtlo0(x) \
1223do { \
1224 __asm__ __volatile__( \
1225 " .set push \n" \
1226 " .set noat \n" \
1227 " move $1, %0 \n" \
1228 " # mtlo $1, $ac0 \n" \
1229 " .word 0x00200013 \n" \
1230 " .set pop \n" \
1231 : \
1232 : "r" (x)); \
1233} while (0)
1234
1235#define mtlo1(x) \
1236do { \
1237 __asm__ __volatile__( \
1238 " .set push \n" \
1239 " .set noat \n" \
1240 " move $1, %0 \n" \
1241 " # mtlo $1, $ac1 \n" \
1242 " .word 0x00200813 \n" \
1243 " .set pop \n" \
1244 : \
1245 : "r" (x)); \
1246} while (0)
1247
1248#define mtlo2(x) \
1249do { \
1250 __asm__ __volatile__( \
1251 " .set push \n" \
1252 " .set noat \n" \
1253 " move $1, %0 \n" \
1254 " # mtlo $1, $ac2 \n" \
1255 " .word 0x00201013 \n" \
1256 " .set pop \n" \
1257 : \
1258 : "r" (x)); \
1259} while (0)
1260
1261#define mtlo3(x) \
1262do { \
1263 __asm__ __volatile__( \
1264 " .set push \n" \
1265 " .set noat \n" \
1266 " move $1, %0 \n" \
1267 " # mtlo $1, $ac3 \n" \
1268 " .word 0x00201813 \n" \
1269 " .set pop \n" \
1270 : \
1271 : "r" (x)); \
1272} while (0)
1273
1274#endif
1275
989/* 1276/*
990 * TLB operations. 1277 * TLB operations.
991 * 1278 *
diff --git a/include/asm-mips/processor.h b/include/asm-mips/processor.h
index d6466aa09fb7..f1980c6c3bcc 100644
--- a/include/asm-mips/processor.h
+++ b/include/asm-mips/processor.h
@@ -96,12 +96,26 @@ union mips_fpu_union {
96 {{0,},} \ 96 {{0,},} \
97} 97}
98 98
99#define NUM_DSP_REGS 6
100
101typedef __u32 dspreg_t;
102
103struct mips_dsp_state {
104 dspreg_t dspr[NUM_DSP_REGS];
105 unsigned int dspcontrol;
106 unsigned short used_dsp;
107};
108
109#define INIT_DSP {{0,},}
110
99typedef struct { 111typedef struct {
100 unsigned long seg; 112 unsigned long seg;
101} mm_segment_t; 113} mm_segment_t;
102 114
103#define ARCH_MIN_TASKALIGN 8 115#define ARCH_MIN_TASKALIGN 8
104 116
117struct mips_abi;
118
105/* 119/*
106 * If you change thread_struct remember to change the #defines below too! 120 * If you change thread_struct remember to change the #defines below too!
107 */ 121 */
@@ -117,6 +131,9 @@ struct thread_struct {
117 /* Saved fpu/fpu emulator stuff. */ 131 /* Saved fpu/fpu emulator stuff. */
118 union mips_fpu_union fpu; 132 union mips_fpu_union fpu;
119 133
134 /* Saved state of the DSP ASE, if available. */
135 struct mips_dsp_state dsp;
136
120 /* Other stuff associated with the thread. */ 137 /* Other stuff associated with the thread. */
121 unsigned long cp0_badvaddr; /* Last user fault */ 138 unsigned long cp0_badvaddr; /* Last user fault */
122 unsigned long cp0_baduaddr; /* Last kernel fault accessing USEG */ 139 unsigned long cp0_baduaddr; /* Last kernel fault accessing USEG */
@@ -129,6 +146,7 @@ struct thread_struct {
129 unsigned long mflags; 146 unsigned long mflags;
130 unsigned long irix_trampoline; /* Wheee... */ 147 unsigned long irix_trampoline; /* Wheee... */
131 unsigned long irix_oldctx; 148 unsigned long irix_oldctx;
149 struct mips_abi *abi;
132}; 150};
133 151
134#define MF_ABI_MASK (MF_32BIT_REGS | MF_32BIT_ADDR) 152#define MF_ABI_MASK (MF_32BIT_REGS | MF_32BIT_ADDR)
@@ -151,6 +169,10 @@ struct thread_struct {
151 */ \ 169 */ \
152 INIT_FPU, \ 170 INIT_FPU, \
153 /* \ 171 /* \
172 * saved dsp/dsp emulator stuff \
173 */ \
174 INIT_DSP, \
175 /* \
154 * Other stuff associated with the process \ 176 * Other stuff associated with the process \
155 */ \ 177 */ \
156 0, 0, 0, 0, \ 178 0, 0, 0, 0, \
diff --git a/include/asm-mips/ptrace.h b/include/asm-mips/ptrace.h
index 2b5c624c3d4f..8441a5ae96e3 100644
--- a/include/asm-mips/ptrace.h
+++ b/include/asm-mips/ptrace.h
@@ -22,6 +22,8 @@
22#define MMLO 68 22#define MMLO 68
23#define FPC_CSR 69 23#define FPC_CSR 69
24#define FPC_EIR 70 24#define FPC_EIR 70
25#define DSP_BASE 71 /* 3 more hi / lo register pairs */
26#define DSP_CONTROL 77
25 27
26/* 28/*
27 * This struct defines the way the registers are stored on the stack during a 29 * This struct defines the way the registers are stored on the stack during a
@@ -38,8 +40,8 @@ struct pt_regs {
38 40
39 /* Saved special registers. */ 41 /* Saved special registers. */
40 unsigned long cp0_status; 42 unsigned long cp0_status;
41 unsigned long lo;
42 unsigned long hi; 43 unsigned long hi;
44 unsigned long lo;
43 unsigned long cp0_badvaddr; 45 unsigned long cp0_badvaddr;
44 unsigned long cp0_cause; 46 unsigned long cp0_cause;
45 unsigned long cp0_epc; 47 unsigned long cp0_epc;
diff --git a/include/asm-mips/sigcontext.h b/include/asm-mips/sigcontext.h
index f7fbebaa0744..8edabb0be23f 100644
--- a/include/asm-mips/sigcontext.h
+++ b/include/asm-mips/sigcontext.h
@@ -27,14 +27,15 @@ struct sigcontext {
27 unsigned int sc_fpc_csr; 27 unsigned int sc_fpc_csr;
28 unsigned int sc_fpc_eir; /* Unused */ 28 unsigned int sc_fpc_eir; /* Unused */
29 unsigned int sc_used_math; 29 unsigned int sc_used_math;
30 unsigned int sc_ssflags; /* Unused */ 30 unsigned int sc_dsp; /* dsp status, was sc_ssflags */
31 unsigned long long sc_mdhi; 31 unsigned long long sc_mdhi;
32 unsigned long long sc_mdlo; 32 unsigned long long sc_mdlo;
33 33 unsigned long sc_hi1; /* Was sc_cause */
34 unsigned int sc_cause; /* Unused */ 34 unsigned long sc_lo1; /* Was sc_badvaddr */
35 unsigned int sc_badvaddr; /* Unused */ 35 unsigned long sc_hi2; /* Was sc_sigset[4] */
36 36 unsigned long sc_lo2;
37 unsigned long sc_sigset[4]; /* kernel's sigset_t */ 37 unsigned long sc_hi3;
38 unsigned long sc_lo3;
38}; 39};
39 40
40#endif /* _MIPS_SIM == _MIPS_SIM_ABI32 */ 41#endif /* _MIPS_SIM == _MIPS_SIM_ABI32 */
@@ -48,19 +49,19 @@ struct sigcontext {
48 * Warning: this structure illdefined with sc_badvaddr being just an unsigned 49 * Warning: this structure illdefined with sc_badvaddr being just an unsigned
49 * int so it was changed to unsigned long in 2.6.0-test1. This may break 50 * int so it was changed to unsigned long in 2.6.0-test1. This may break
50 * binary compatibility - no prisoners. 51 * binary compatibility - no prisoners.
52 * DSP ASE in 2.6.12-rc4. Turn sc_mdhi and sc_mdlo into an array of four
53 * entries, add sc_dsp and sc_reserved for padding. No prisoners.
51 */ 54 */
52struct sigcontext { 55struct sigcontext {
53 unsigned long sc_regs[32]; 56 unsigned long sc_regs[32];
54 unsigned long sc_fpregs[32]; 57 unsigned long sc_fpregs[32];
55 unsigned long sc_mdhi; 58 unsigned long sc_hi[4];
56 unsigned long sc_mdlo; 59 unsigned long sc_lo[4];
57 unsigned long sc_pc; 60 unsigned long sc_pc;
58 unsigned long sc_badvaddr;
59 unsigned int sc_status;
60 unsigned int sc_fpc_csr; 61 unsigned int sc_fpc_csr;
61 unsigned int sc_fpc_eir;
62 unsigned int sc_used_math; 62 unsigned int sc_used_math;
63 unsigned int sc_cause; 63 unsigned int sc_dsp;
64 unsigned int sc_reserved;
64}; 65};
65 66
66#ifdef __KERNEL__ 67#ifdef __KERNEL__
@@ -68,23 +69,24 @@ struct sigcontext {
68#include <linux/posix_types.h> 69#include <linux/posix_types.h>
69 70
70struct sigcontext32 { 71struct sigcontext32 {
71 __u32 sc_regmask; /* Unused */ 72 __u32 sc_regmask; /* Unused */
72 __u32 sc_status; 73 __u32 sc_status;
73 __u64 sc_pc; 74 __u64 sc_pc;
74 __u64 sc_regs[32]; 75 __u64 sc_regs[32];
75 __u64 sc_fpregs[32]; 76 __u64 sc_fpregs[32];
76 __u32 sc_ownedfp; /* Unused */ 77 __u32 sc_ownedfp; /* Unused */
77 __u32 sc_fpc_csr; 78 __u32 sc_fpc_csr;
78 __u32 sc_fpc_eir; /* Unused */ 79 __u32 sc_fpc_eir; /* Unused */
79 __u32 sc_used_math; 80 __u32 sc_used_math;
80 __u32 sc_ssflags; /* Unused */ 81 __u32 sc_dsp; /* dsp status, was sc_ssflags */
81 __u64 sc_mdhi; 82 __u64 sc_mdhi;
82 __u64 sc_mdlo; 83 __u64 sc_mdlo;
83 84 __u32 sc_hi1; /* Was sc_cause */
84 __u32 sc_cause; /* Unused */ 85 __u32 sc_lo1; /* Was sc_badvaddr */
85 __u32 sc_badvaddr; /* Unused */ 86 __u32 sc_hi2; /* Was sc_sigset[4] */
86 87 __u32 sc_lo2;
87 __u32 sc_sigset[4]; /* kernel's sigset_t */ 88 __u32 sc_hi3;
89 __u32 sc_lo3;
88}; 90};
89#endif /* __KERNEL__ */ 91#endif /* __KERNEL__ */
90 92
diff --git a/include/asm-mips/signal.h b/include/asm-mips/signal.h
index f2c470f1d369..8ca539e80d87 100644
--- a/include/asm-mips/signal.h
+++ b/include/asm-mips/signal.h
@@ -98,12 +98,39 @@ typedef unsigned long old_sigset_t; /* at least 32 bits */
98#define MINSIGSTKSZ 2048 98#define MINSIGSTKSZ 2048
99#define SIGSTKSZ 8192 99#define SIGSTKSZ 8192
100 100
101#ifdef __KERNEL__
102
103/*
104 * These values of sa_flags are used only by the kernel as part of the
105 * irq handling routines.
106 *
107 * SA_INTERRUPT is also used by the irq handling routines.
108 * SA_SHIRQ flag is for shared interrupt support on PCI and EISA.
109 */
110#define SA_SAMPLE_RANDOM SA_RESTART
111
112#ifdef CONFIG_TRAD_SIGNALS
113#define sig_uses_siginfo(ka) ((ka)->sa.sa_flags & SA_SIGINFO)
114#else
115#define sig_uses_siginfo(ka) (1)
116#endif
117
118#endif /* __KERNEL__ */
119
101#define SIG_BLOCK 1 /* for blocking signals */ 120#define SIG_BLOCK 1 /* for blocking signals */
102#define SIG_UNBLOCK 2 /* for unblocking signals */ 121#define SIG_UNBLOCK 2 /* for unblocking signals */
103#define SIG_SETMASK 3 /* for setting the signal mask */ 122#define SIG_SETMASK 3 /* for setting the signal mask */
104#define SIG_SETMASK32 256 /* Goodie from SGI for BSD compatibility: 123#define SIG_SETMASK32 256 /* Goodie from SGI for BSD compatibility:
105 set only the low 32 bit of the sigset. */ 124 set only the low 32 bit of the sigset. */
106#include <asm-generic/signal.h> 125
126/* Type of a signal handler. */
127typedef void __signalfn_t(int);
128typedef __signalfn_t __user *__sighandler_t;
129
130/* Fake signal functions */
131#define SIG_DFL ((__sighandler_t)0) /* default signal handling */
132#define SIG_IGN ((__sighandler_t)1) /* ignore signal */
133#define SIG_ERR ((__sighandler_t)-1) /* error return from signal */
107 134
108struct sigaction { 135struct sigaction {
109 unsigned int sa_flags; 136 unsigned int sa_flags;
diff --git a/include/asm-mips/system.h b/include/asm-mips/system.h
index 6663efd49b27..cd3a6bca7abd 100644
--- a/include/asm-mips/system.h
+++ b/include/asm-mips/system.h
@@ -17,6 +17,7 @@
17 17
18#include <asm/addrspace.h> 18#include <asm/addrspace.h>
19#include <asm/cpu-features.h> 19#include <asm/cpu-features.h>
20#include <asm/dsp.h>
20#include <asm/ptrace.h> 21#include <asm/ptrace.h>
21#include <asm/war.h> 22#include <asm/war.h>
22#include <asm/interrupt.h> 23#include <asm/interrupt.h>
@@ -154,9 +155,13 @@ extern asmlinkage void *resume(void *last, void *next, void *next_ti);
154 155
155struct task_struct; 156struct task_struct;
156 157
157#define switch_to(prev,next,last) \ 158#define switch_to(prev,next,last) \
158do { \ 159do { \
159 (last) = resume(prev, next, next->thread_info); \ 160 if (cpu_has_dsp) \
161 __save_dsp(prev); \
162 (last) = resume(prev, next, next->thread_info); \
163 if (cpu_has_dsp) \
164 __restore_dsp(current); \
160} while(0) 165} while(0)
161 166
162#define ROT_IN_PIECES \ 167#define ROT_IN_PIECES \