Commit e50c0a8fa60da9ac0e0a70caa8a3a803815c1f2f

Authored by Ralf Baechle
1 parent 10f650db1b

Support the MIPS32 / MIPS64 DSP ASE.

Signed-off-by: Ralf Baechle <ralf@linux-mips.org>

Showing 34 changed files with 876 additions and 139 deletions Side-by-side Diff

arch/mips/kernel/asm-offsets.c
... ... @@ -95,7 +95,7 @@
95 95 offset("#define TI_PRE_COUNT ", struct thread_info, preempt_count);
96 96 offset("#define TI_ADDR_LIMIT ", struct thread_info, addr_limit);
97 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 99 constant("#define _THREAD_SIZE_ORDER ", THREAD_SIZE_ORDER);
100 100 constant("#define _THREAD_SIZE ", THREAD_SIZE);
101 101 constant("#define _THREAD_MASK ", THREAD_MASK);
... ... @@ -241,6 +241,7 @@
241 241 linefeed;
242 242 }
243 243  
  244 +#ifdef CONFIG_32BIT
244 245 void output_sc_defines(void)
245 246 {
246 247 text("/* Linux sigcontext offsets. */");
247 248  
... ... @@ -252,10 +253,29 @@
252 253 offset("#define SC_STATUS ", struct sigcontext, sc_status);
253 254 offset("#define SC_FPC_CSR ", struct sigcontext, sc_fpc_csr);
254 255 offset("#define SC_FPC_EIR ", struct sigcontext, sc_fpc_eir);
255   - offset("#define SC_CAUSE ", struct sigcontext, sc_cause);
256   - offset("#define SC_BADVADDR ", struct sigcontext, sc_badvaddr);
  256 + offset("#define SC_HI1 ", struct sigcontext, sc_hi1);
  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 262 linefeed;
258 263 }
  264 +#endif
  265 +
  266 +#ifdef CONFIG_64BIT
  267 +void 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 280 #ifdef CONFIG_MIPS32_COMPAT
261 281 void output_sc32_defines(void)
arch/mips/kernel/branch.c
... ... @@ -22,7 +22,7 @@
22 22 */
23 23 int __compute_return_epc(struct pt_regs *regs)
24 24 {
25   - unsigned int *addr, bit, fcr31;
  25 + unsigned int *addr, bit, fcr31, dspcontrol;
26 26 long epc;
27 27 union mips_instruction insn;
28 28  
... ... @@ -99,6 +99,18 @@
99 99 epc += 8;
100 100 regs->cp0_epc = epc;
101 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 115 break;
104 116  
... ... @@ -198,6 +210,11 @@
198 210  
199 211 unaligned:
200 212 printk("%s: unaligned epc - sending SIGBUS.\n", current->comm);
  213 + force_sig(SIGBUS, current);
  214 + return -EFAULT;
  215 +
  216 +sigill:
  217 + printk("%s: DSP branch but not DSP ASE - sending SIGBUS.\n", current->comm);
201 218 force_sig(SIGBUS, current);
202 219 return -EFAULT;
203 220 }
arch/mips/kernel/cpu-probe.c
... ... @@ -482,6 +482,8 @@
482 482  
483 483 if (config3 & MIPS_CONF3_SM)
484 484 c->ases |= MIPS_ASE_SMARTMIPS;
  485 + if (config3 & MIPS_CONF3_DSP)
  486 + c->ases |= MIPS_ASE_DSP;
485 487  
486 488 return config3 & MIPS_CONF_M;
487 489 }
... ... @@ -529,6 +531,7 @@
529 531 c->cputype = CPU_20KC;
530 532 break;
531 533 case PRID_IMP_24K:
  534 + case PRID_IMP_24KE:
532 535 c->cputype = CPU_24K;
533 536 break;
534 537 case PRID_IMP_25KF:
arch/mips/kernel/genex.S
... ... @@ -291,6 +291,7 @@
291 291 BUILD_HANDLER mdmx mdmx sti silent /* #22 */
292 292 BUILD_HANDLER watch watch sti verbose /* #23 */
293 293 BUILD_HANDLER mcheck mcheck cli verbose /* #24 */
  294 + BUILD_HANDLER dsp dsp sti silent /* #26 */
294 295 BUILD_HANDLER reserved reserved sti verbose /* others */
295 296  
296 297 #ifdef CONFIG_64BIT
arch/mips/kernel/process.c
... ... @@ -25,8 +25,10 @@
25 25 #include <linux/init.h>
26 26 #include <linux/completion.h>
27 27  
  28 +#include <asm/abi.h>
28 29 #include <asm/bootinfo.h>
29 30 #include <asm/cpu.h>
  31 +#include <asm/dsp.h>
30 32 #include <asm/fpu.h>
31 33 #include <asm/pgtable.h>
32 34 #include <asm/system.h>
... ... @@ -54,6 +56,54 @@
54 56 }
55 57 }
56 58  
  59 +extern int do_signal(sigset_t *oldset, struct pt_regs *regs);
  60 +extern int do_signal32(sigset_t *oldset, struct pt_regs *regs);
  61 +
  62 +/*
  63 + * Native o32 and N64 ABI without DSP ASE
  64 + */
  65 +extern void setup_frame(struct k_sigaction * ka, struct pt_regs *regs,
  66 + int signr, sigset_t *set);
  67 +extern void setup_rt_frame(struct k_sigaction * ka, struct pt_regs *regs,
  68 + int signr, sigset_t *set, siginfo_t *info);
  69 +
  70 +struct 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 + */
  82 +extern void setup_frame_32(struct k_sigaction * ka, struct pt_regs *regs,
  83 + int signr, sigset_t *set);
  84 +extern void setup_rt_frame_32(struct k_sigaction * ka, struct pt_regs *regs,
  85 + int signr, sigset_t *set, siginfo_t *info);
  86 +
  87 +struct 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 + */
  98 +extern void setup_rt_frame_n32(struct k_sigaction * ka, struct pt_regs *regs,
  99 + int signr, sigset_t *set, siginfo_t *info);
  100 +
  101 +struct 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 +
57 107 asmlinkage void ret_from_fork(void);
58 108  
59 109 void start_thread(struct pt_regs * regs, unsigned long pc, unsigned long sp)
... ... @@ -70,6 +120,8 @@
70 120 regs->cp0_status = status;
71 121 clear_used_math();
72 122 lose_fpu();
  123 + if (cpu_has_dsp)
  124 + __init_dsp();
73 125 regs->cp0_epc = pc;
74 126 regs->regs[29] = sp;
75 127 current_thread_info()->addr_limit = USER_DS;
76 128  
... ... @@ -95,9 +147,11 @@
95 147  
96 148 preempt_disable();
97 149  
98   - if (is_fpu_owner()) {
  150 + if (is_fpu_owner())
99 151 save_fp(p);
100   - }
  152 +
  153 + if (cpu_has_dsp)
  154 + save_dsp(p);
101 155  
102 156 preempt_enable();
103 157  
arch/mips/kernel/ptrace.c
... ... @@ -30,6 +30,7 @@
30 30  
31 31 #include <asm/byteorder.h>
32 32 #include <asm/cpu.h>
  33 +#include <asm/dsp.h>
33 34 #include <asm/fpu.h>
34 35 #include <asm/mipsregs.h>
35 36 #include <asm/pgtable.h>
... ... @@ -176,6 +177,27 @@
176 177 write_c0_status(flags);
177 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 201 default:
180 202 tmp = 0;
181 203 ret = -EIO;
... ... @@ -247,6 +269,22 @@
247 269 child->thread.fpu.hard.fcr31 = data;
248 270 else
249 271 child->thread.fpu.soft.fcr31 = data;
  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;
250 288 break;
251 289 default:
252 290 /* The rest are not allowed. */
arch/mips/kernel/ptrace32.c
... ... @@ -26,6 +26,7 @@
26 26 #include <linux/security.h>
27 27  
28 28 #include <asm/cpu.h>
  29 +#include <asm/dsp.h>
29 30 #include <asm/fpu.h>
30 31 #include <asm/mipsregs.h>
31 32 #include <asm/pgtable.h>
... ... @@ -161,6 +162,27 @@
161 162 write_c0_status(flags);
162 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 186 default:
165 187 tmp = 0;
166 188 ret = -EIO;
... ... @@ -229,6 +251,22 @@
229 251 child->thread.fpu.hard.fcr31 = data;
230 252 else
231 253 child->thread.fpu.soft.fcr31 = data;
  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;
232 270 break;
233 271 default:
234 272 /* The rest are not allowed. */
arch/mips/kernel/r4k_fpu.S
... ... @@ -32,7 +32,7 @@
32 32  
33 33 .set noreorder
34 34 .set mips3
35   - /* Save floating point context */
  35 +
36 36 LEAF(_save_fp_context)
37 37 cfc1 t1, fcr31
38 38  
... ... @@ -74,9 +74,6 @@
74 74 EX sdc1 $f28, SC_FPREGS+224(a0)
75 75 EX sdc1 $f30, SC_FPREGS+240(a0)
76 76 EX sw t1, SC_FPC_CSR(a0)
77   - cfc1 t0, $0 # implementation/version
78   - EX sw t0, SC_FPC_EIR(a0)
79   -
80 77 jr ra
81 78 li v0, 0 # success
82 79 END(_save_fp_context)
arch/mips/kernel/scall32-o32.S
... ... @@ -620,7 +620,7 @@
620 620 sys sys_ni_syscall 0 /* sys_vserver */
621 621 sys sys_waitid 5
622 622 sys sys_ni_syscall 0 /* available, was setaltroot */
623   - sys sys_add_key 5
  623 + sys sys_add_key 5 /* 4280 */
624 624 sys sys_request_key 4
625 625 sys sys_keyctl 5
626 626 sys sys_set_thread_area 1
arch/mips/kernel/setup.c
... ... @@ -549,4 +549,13 @@
549 549 }
550 550  
551 551 __setup("nofpu", fpu_disable);
  552 +
  553 +int __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);
arch/mips/kernel/signal-common.h
... ... @@ -8,13 +8,14 @@
8 8 * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
9 9 */
10 10  
  11 +#include <linux/config.h>
  12 +
11 13 static inline int
12 14 setup_sigcontext(struct pt_regs *regs, struct sigcontext *sc)
13 15 {
14 16 int err = 0;
15 17  
16 18 err |= __put_user(regs->cp0_epc, &sc->sc_pc);
17   - err |= __put_user(regs->cp0_status, &sc->sc_status);
18 19  
19 20 #define save_gp_reg(i) do { \
20 21 err |= __put_user(regs->regs[i], &sc->sc_regs[i]); \
21 22  
... ... @@ -30,10 +31,32 @@
30 31 save_gp_reg(31);
31 32 #undef save_gp_reg
32 33  
  34 +#ifdef CONFIG_32BIT
33 35 err |= __put_user(regs->hi, &sc->sc_mdhi);
34 36 err |= __put_user(regs->lo, &sc->sc_mdlo);
35   - err |= __put_user(regs->cp0_cause, &sc->sc_cause);
36   - err |= __put_user(regs->cp0_badvaddr, &sc->sc_badvaddr);
  37 + if (cpu_has_dsp) {
  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 61 err |= __put_user(!!used_math(), &sc->sc_used_math);
39 62  
40 63  
41 64  
42 65  
... ... @@ -61,15 +84,40 @@
61 84 static inline int
62 85 restore_sigcontext(struct pt_regs *regs, struct sigcontext *sc)
63 86 {
64   - int err = 0;
65 87 unsigned int used_math;
  88 + unsigned long treg;
  89 + int err = 0;
66 90  
67 91 /* Always make any pending restarted system calls return -EINTR */
68 92 current_thread_info()->restart_block.fn = do_no_restart_syscall;
69 93  
70 94 err |= __get_user(regs->cp0_epc, &sc->sc_pc);
  95 +#ifdef CONFIG_32BIT
71 96 err |= __get_user(regs->hi, &sc->sc_mdhi);
72 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 122 #define restore_gp_reg(i) do { \
75 123 err |= __get_user(regs->regs[i], &sc->sc_regs[i]); \
arch/mips/kernel/signal.c
... ... @@ -21,6 +21,7 @@
21 21 #include <linux/unistd.h>
22 22 #include <linux/compiler.h>
23 23  
  24 +#include <asm/abi.h>
24 25 #include <asm/asm.h>
25 26 #include <linux/bitops.h>
26 27 #include <asm/cacheflush.h>
... ... @@ -36,7 +37,7 @@
36 37  
37 38 #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
38 39  
39   -static int do_signal(sigset_t *oldset, struct pt_regs *regs);
  40 +int do_signal(sigset_t *oldset, struct pt_regs *regs);
40 41  
41 42 /*
42 43 * Atomically swap in the new signal mask, and wait for a signal.
... ... @@ -216,7 +217,7 @@
216 217 badframe:
217 218 force_sig(SIGSEGV, current);
218 219 }
219   -#endif
  220 +#endif /* CONFIG_TRAD_SIGNALS */
220 221  
221 222 save_static_function(sys_rt_sigreturn);
222 223 __attribute_used__ noinline static void
... ... @@ -262,7 +263,7 @@
262 263 }
263 264  
264 265 #ifdef CONFIG_TRAD_SIGNALS
265   -static void inline setup_frame(struct k_sigaction * ka, struct pt_regs *regs,
  266 +void setup_frame(struct k_sigaction * ka, struct pt_regs *regs,
266 267 int signr, sigset_t *set)
267 268 {
268 269 struct sigframe *frame;
... ... @@ -318,7 +319,7 @@
318 319 }
319 320 #endif
320 321  
321   -static void inline setup_rt_frame(struct k_sigaction * ka, struct pt_regs *regs,
  322 +void setup_rt_frame(struct k_sigaction * ka, struct pt_regs *regs,
322 323 int signr, sigset_t *set, siginfo_t *info)
323 324 {
324 325 struct rt_sigframe *frame;
325 326  
... ... @@ -410,22 +411,10 @@
410 411  
411 412 regs->regs[0] = 0; /* Don't deal with this again. */
412 413  
413   -#ifdef CONFIG_TRAD_SIGNALS
414   - if (ka->sa.sa_flags & SA_SIGINFO) {
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
  414 + if (sig_uses_siginfo(ka))
  415 + current->thread.abi->setup_rt_frame(ka, regs, sig, oldset, info);
426 416 else
427   - setup_frame(ka, regs, sig, oldset);
428   -#endif
  417 + current->thread.abi->setup_frame(ka, regs, sig, oldset);
429 418  
430 419 spin_lock_irq(&current->sighand->siglock);
431 420 sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
432 421  
... ... @@ -435,21 +424,12 @@
435 424 spin_unlock_irq(&current->sighand->siglock);
436 425 }
437 426  
438   -extern int do_signal32(sigset_t *oldset, struct pt_regs *regs);
439   -extern int do_irix_signal(sigset_t *oldset, struct pt_regs *regs);
440   -
441   -static int do_signal(sigset_t *oldset, struct pt_regs *regs)
  427 +int do_signal(sigset_t *oldset, struct pt_regs *regs)
442 428 {
443 429 struct k_sigaction ka;
444 430 siginfo_t info;
445 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 434 * We want the common case to go fast, which is why we may in certain
455 435 * cases get here from kernel mode. Just return without doing anything
... ... @@ -501,19 +481,7 @@
501 481 {
502 482 /* deal with pending signal delivery */
503 483 if (thread_info_flags & _TIF_SIGPENDING) {
504   -#ifdef CONFIG_BINFMT_ELF32
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);
  484 + current->thread.abi->do_signal(oldset, regs);
517 485 }
518 486 }
arch/mips/kernel/signal32.c
... ... @@ -21,6 +21,7 @@
21 21 #include <linux/suspend.h>
22 22 #include <linux/compiler.h>
23 23  
  24 +#include <asm/abi.h>
24 25 #include <asm/asm.h>
25 26 #include <linux/bitops.h>
26 27 #include <asm/cacheflush.h>
27 28  
... ... @@ -334,8 +335,9 @@
334 335  
335 336 static int restore_sigcontext32(struct pt_regs *regs, struct sigcontext32 *sc)
336 337 {
  338 + u32 used_math;
337 339 int err = 0;
338   - __u32 used_math;
  340 + s32 treg;
339 341  
340 342 /* Always make any pending restarted system calls return -EINTR */
341 343 current_thread_info()->restart_block.fn = do_no_restart_syscall;
... ... @@ -343,6 +345,15 @@
343 345 err |= __get_user(regs->cp0_epc, &sc->sc_pc);
344 346 err |= __get_user(regs->hi, &sc->sc_mdhi);
345 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 358 #define restore_gp_reg(i) do { \
348 359 err |= __get_user(regs->regs[i], &sc->sc_regs[i]); \
... ... @@ -562,8 +573,15 @@
562 573  
563 574 err |= __put_user(regs->hi, &sc->sc_mdhi);
564 575 err |= __put_user(regs->lo, &sc->sc_mdlo);
565   - err |= __put_user(regs->cp0_cause, &sc->sc_cause);
566   - err |= __put_user(regs->cp0_badvaddr, &sc->sc_badvaddr);
  576 + if (cpu_has_dsp) {
  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 586 err |= __put_user(!!used_math(), &sc->sc_used_math);
569 587  
... ... @@ -613,7 +631,7 @@
613 631 return (void *)((sp - frame_size) & ALMASK);
614 632 }
615 633  
616   -static inline void setup_frame(struct k_sigaction * ka, struct pt_regs *regs,
  634 +void setup_frame_32(struct k_sigaction * ka, struct pt_regs *regs,
617 635 int signr, sigset_t *set)
618 636 {
619 637 struct sigframe *frame;
... ... @@ -666,9 +684,7 @@
666 684 force_sigsegv(signr, current);
667 685 }
668 686  
669   -static inline void setup_rt_frame(struct k_sigaction * ka,
670   - struct pt_regs *regs, int signr,
671   - sigset_t *set, siginfo_t *info)
  687 +void setup_rt_frame_32(struct k_sigaction * ka, struct pt_regs *regs, int signr, sigset_t *set, siginfo_t *info)
672 688 {
673 689 struct rt_sigframe32 *frame;
674 690 int err = 0;
675 691  
... ... @@ -759,9 +775,9 @@
759 775 regs->regs[0] = 0; /* Don't deal with this again. */
760 776  
761 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 779 else
764   - setup_frame(ka, regs, sig, oldset);
  780 + current->thread.abi->setup_frame(ka, regs, sig, oldset);
765 781  
766 782 spin_lock_irq(&current->sighand->siglock);
767 783 sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
arch/mips/kernel/traps.c
... ... @@ -25,6 +25,7 @@
25 25 #include <asm/branch.h>
26 26 #include <asm/break.h>
27 27 #include <asm/cpu.h>
  28 +#include <asm/dsp.h>
28 29 #include <asm/fpu.h>
29 30 #include <asm/module.h>
30 31 #include <asm/pgtable.h>
... ... @@ -54,6 +55,7 @@
54 55 extern asmlinkage void handle_fpe(void);
55 56 extern asmlinkage void handle_mdmx(void);
56 57 extern asmlinkage void handle_watch(void);
  58 +extern asmlinkage void handle_dsp(void);
57 59 extern asmlinkage void handle_mcheck(void);
58 60 extern asmlinkage void handle_reserved(void);
59 61  
... ... @@ -775,6 +777,14 @@
775 777 (regs->cp0_status & ST0_TS) ? "" : "not ");
776 778 }
777 779  
  780 +asmlinkage 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 +
778 788 asmlinkage void do_reserved(struct pt_regs *regs)
779 789 {
780 790 /*
781 791  
... ... @@ -984,9 +994,12 @@
984 994 #endif
985 995 if (current_cpu_data.isa_level == MIPS_CPU_ISA_IV)
986 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 998 status_set);
989 999  
  1000 + if (cpu_has_dsp)
  1001 + set_c0_status(ST0_MX);
  1002 +
990 1003 /*
991 1004 * Some MIPS CPUs have a dedicated interrupt vector which reduces the
992 1005 * interrupt processing overhead. Use it where available.
993 1006  
... ... @@ -1078,22 +1091,7 @@
1078 1091 set_except_vector(11, handle_cpu);
1079 1092 set_except_vector(12, handle_ov);
1080 1093 set_except_vector(13, handle_tr);
1081   - set_except_vector(22, handle_mdmx);
1082 1094  
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   -
1097 1095 if (current_cpu_data.cputype == CPU_R6000 ||
1098 1096 current_cpu_data.cputype == CPU_R6000A) {
1099 1097 /*
... ... @@ -1107,6 +1105,25 @@
1107 1105 //set_except_vector(14, handle_mc);
1108 1106 //set_except_vector(15, handle_ndc);
1109 1107 }
  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);
1110 1127  
1111 1128 signal_init();
1112 1129 #ifdef CONFIG_MIPS32_COMPAT
include/asm-mips/abi.h
  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 +
  15 +struct 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 */
include/asm-mips/cpu-features.h
... ... @@ -105,6 +105,10 @@
105 105 #endif
106 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 113 * Certain CPUs may throw bizarre exceptions if not the whole cacheline
110 114 * contains valid instructions. For these we ensure proper alignment of
include/asm-mips/cpu.h
... ... @@ -77,6 +77,7 @@
77 77 #define PRID_IMP_4KEMPR2 0x9100
78 78 #define PRID_IMP_4KSD 0x9200
79 79 #define PRID_IMP_24K 0x9300
  80 +#define PRID_IMP_24KE 0x9600
80 81  
81 82 #define PRID_IMP_UNKNOWN 0xff00
82 83  
... ... @@ -232,6 +233,7 @@
232 233 #define MIPS_ASE_MDMX 0x00000002 /* MIPS digital media extension */
233 234 #define MIPS_ASE_MIPS3D 0x00000004 /* MIPS-3D */
234 235 #define MIPS_ASE_SMARTMIPS 0x00000008 /* SmartMIPS */
  236 +#define MIPS_ASE_DSP 0x00000010 /* Signal Processing ASE */
235 237  
236 238 #endif /* _ASM_CPU_H */
include/asm-mips/dsp.h
  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() \
  22 +do { \
  23 + asm("_ehb"); \
  24 +} while (0)
  25 +
  26 +static 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 +
  37 +static inline void init_dsp(void)
  38 +{
  39 + if (cpu_has_dsp)
  40 + __init_dsp();
  41 +}
  42 +
  43 +#define __save_dsp(tsk) \
  44 +do { \
  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) \
  54 +do { \
  55 + if (cpu_has_dsp) \
  56 + __save_dsp(tsk); \
  57 +} while (0)
  58 +
  59 +#define __restore_dsp(tsk) \
  60 +do { \
  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) \
  70 +do { \
  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 */
include/asm-mips/elf.h
... ... @@ -193,33 +193,76 @@
193 193  
194 194 #ifdef __KERNEL__
195 195  
  196 +struct mips_abi;
  197 +
  198 +extern struct mips_abi mips_abi;
  199 +extern struct mips_abi mips_abi_32;
  200 +extern struct mips_abi mips_abi_n32;
  201 +
196 202 #ifdef CONFIG_32BIT
197 203  
198   -#define SET_PERSONALITY(ex, ibcs2) \
199   -do { \
200   - if (ibcs2) \
201   - set_personality(PER_SVR4); \
202   - set_personality(PER_LINUX); \
  204 +#define SET_PERSONALITY(ex, ibcs2) \
  205 +do { \
  206 + if (ibcs2) \
  207 + set_personality(PER_SVR4); \
  208 + set_personality(PER_LINUX); \
  209 + \
  210 + current->thread.abi = &mips_abi; \
203 211 } while (0)
204 212  
205 213 #endif /* CONFIG_32BIT */
206 214  
207 215 #ifdef CONFIG_64BIT
208 216  
209   -#define SET_PERSONALITY(ex, ibcs2) \
210   -do { current->thread.mflags &= ~MF_ABI_MASK; \
211   - if ((ex).e_ident[EI_CLASS] == ELFCLASS32) { \
212   - if ((((ex).e_flags & EF_MIPS_ABI2) != 0) && \
213   - ((ex).e_flags & EF_MIPS_ABI) == 0) \
214   - current->thread.mflags |= MF_N32; \
215   - else \
216   - current->thread.mflags |= MF_O32; \
217   - } else \
218   - current->thread.mflags |= MF_N64; \
219   - if (ibcs2) \
220   - set_personality(PER_SVR4); \
221   - else if (current->personality != PER_LINUX32) \
222   - set_personality(PER_LINUX); \
  217 +#ifdef CONFIG_MIPS32_N32
  218 +#define __SET_PERSONALITY32_N32() \
  219 + do { \
  220 + current->thread.mflags |= MF_N32; \
  221 + current->thread.abi = &mips_abi_n32; \
  222 + } while (0)
  223 +#else
  224 +#define __SET_PERSONALITY32_N32() \
  225 + do { } while (0)
  226 +#endif
  227 +
  228 +#ifdef CONFIG_MIPS32_O32
  229 +#define __SET_PERSONALITY32_O32() \
  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) \
  241 +do { \
  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) \
  253 +do { \
  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 266 } while (0)
224 267  
225 268 #endif /* CONFIG_64BIT */
include/asm-mips/inst.h
... ... @@ -62,10 +62,10 @@
62 62 spimi_op, unused_rt_op_0x05, unused_rt_op_0x06, unused_rt_op_0x07,
63 63 tgei_op, tgeiu_op, tlti_op, tltiu_op,
64 64 teqi_op, unused_0x0d_rt_op, tnei_op, unused_0x0f_rt_op,
65   - bltzal_op, bgezal_op, bltzall_op, bgezall_op
66   - /*
67   - * The others (0x14 - 0x1f) are unused.
68   - */
  65 + bltzal_op, bgezal_op, bltzall_op, bgezall_op,
  66 + rt_op_0x14, rt_op_0x15, rt_op_0x16, rt_op_0x17,
  67 + rt_op_0x18, rt_op_0x19, rt_op_0x1a, rt_op_0x1b,
  68 + bposge32_op, rt_op_0x1d, rt_op_0x1e, rt_op_0x1f
69 69 };
70 70  
71 71 /*
include/asm-mips/mach-ip22/cpu-feature-overrides.h
... ... @@ -23,6 +23,8 @@
23 23 #define cpu_has_dc_aliases (PAGE_SIZE < 0x4000)
24 24 #define cpu_has_ic_fills_f_dc 0
25 25  
  26 +#define cpu_has_dsp 0
  27 +
26 28 #define cpu_has_nofpuex 0
27 29 #define cpu_has_64bits 1
28 30  
include/asm-mips/mach-ip27/cpu-feature-overrides.h
... ... @@ -25,6 +25,7 @@
25 25 #define cpu_has_vtag_icache 0
26 26 #define cpu_has_dc_aliases 0
27 27 #define cpu_has_ic_fills_f_dc 0
  28 +#define cpu_has_dsp 0
28 29 #define cpu_icache_snoops_remote_store 1
29 30  
30 31 #define cpu_has_nofpuex 0
include/asm-mips/mach-ip32/cpu-feature-overrides.h
... ... @@ -37,6 +37,7 @@
37 37 #define cpu_has_ejtag 0
38 38 #define cpu_has_vtag_icache 0
39 39 #define cpu_has_ic_fills_f_dc 0
  40 +#define cpu_has_dsp 0
40 41  
41 42 #endif /* __ASM_MACH_IP32_CPU_FEATURE_OVERRIDES_H */
include/asm-mips/mach-ja/cpu-feature-overrides.h
... ... @@ -25,6 +25,7 @@
25 25 #define cpu_has_vtag_icache 0
26 26 #define cpu_has_dc_aliases 0
27 27 #define cpu_has_ic_fills_f_dc 0
  28 +#define cpu_has_dsp 0
28 29 #define cpu_icache_snoops_remote_store 0
29 30  
30 31 #define cpu_has_nofpuex 0
include/asm-mips/mach-ocelot3/cpu-feature-overrides.h
... ... @@ -28,6 +28,7 @@
28 28 #define cpu_has_vtag_icache 0
29 29 #define cpu_has_dc_aliases 0
30 30 #define cpu_has_ic_fills_f_dc 0
  31 +#define cpu_has_dsp 0
31 32 #define cpu_icache_snoops_remote_store 0
32 33  
33 34 #define cpu_has_nofpuex 0
include/asm-mips/mach-rm200/cpu-feature-overrides.h
... ... @@ -31,6 +31,7 @@
31 31 #define cpu_has_vtag_icache 0
32 32 #define cpu_has_dc_aliases (PAGE_SIZE < 0x4000)
33 33 #define cpu_has_ic_fills_f_dc 0
  34 +#define cpu_has_dsp 0
34 35 #define cpu_has_nofpuex 0
35 36 #define cpu_has_64bits 1
36 37  
include/asm-mips/mach-sibyte/cpu-feature-overrides.h
... ... @@ -25,6 +25,7 @@
25 25 #define cpu_has_vtag_icache 1
26 26 #define cpu_has_dc_aliases 0
27 27 #define cpu_has_ic_fills_f_dc 0
  28 +#define cpu_has_dsp 0
28 29 #define cpu_icache_snoops_remote_store 0
29 30  
30 31 #define cpu_has_nofpuex 0
include/asm-mips/mach-yosemite/cpu-feature-overrides.h
... ... @@ -25,6 +25,7 @@
25 25 #define cpu_has_vtag_icache 0
26 26 #define cpu_has_dc_aliases 0
27 27 #define cpu_has_ic_fills_f_dc 0
  28 +#define cpu_has_dsp 0
28 29 #define cpu_icache_snoops_remote_store 0
29 30  
30 31 #define cpu_has_nofpuex 0
include/asm-mips/mipsregs.h
... ... @@ -281,6 +281,11 @@
281 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 289 * Bitfields in the TX39 family CP0 Configuration Register 3
285 290 */
286 291 #define TX39_CONF_ICS_SHIFT 19
... ... @@ -510,6 +515,7 @@
510 515 #define MIPS_CONF3_VINT (_ULCAST_(1) << 5)
511 516 #define MIPS_CONF3_VEIC (_ULCAST_(1) << 6)
512 517 #define MIPS_CONF3_LPA (_ULCAST_(1) << 7)
  518 +#define MIPS_CONF3_DSP (_ULCAST_(1) << 10)
513 519  
514 520 /*
515 521 * Bits in the MIPS32/64 coprocessor 1 (FPU) revision register.
... ... @@ -985,6 +991,287 @@
985 991 ".set\tpop" \
986 992 : "=r" (__res)); \
987 993 __res;})
  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) \
  1012 +do { \
  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) \
  1171 +do { \
  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) \
  1184 +do { \
  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) \
  1197 +do { \
  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) \
  1210 +do { \
  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) \
  1223 +do { \
  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) \
  1236 +do { \
  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) \
  1249 +do { \
  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) \
  1262 +do { \
  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
988 1275  
989 1276 /*
990 1277 * TLB operations.
include/asm-mips/processor.h
... ... @@ -96,12 +96,26 @@
96 96 {{0,},} \
97 97 }
98 98  
  99 +#define NUM_DSP_REGS 6
  100 +
  101 +typedef __u32 dspreg_t;
  102 +
  103 +struct 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 +
99 111 typedef struct {
100 112 unsigned long seg;
101 113 } mm_segment_t;
102 114  
103 115 #define ARCH_MIN_TASKALIGN 8
104 116  
  117 +struct mips_abi;
  118 +
105 119 /*
106 120 * If you change thread_struct remember to change the #defines below too!
107 121 */
... ... @@ -117,6 +131,9 @@
117 131 /* Saved fpu/fpu emulator stuff. */
118 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 137 /* Other stuff associated with the thread. */
121 138 unsigned long cp0_badvaddr; /* Last user fault */
122 139 unsigned long cp0_baduaddr; /* Last kernel fault accessing USEG */
... ... @@ -129,6 +146,7 @@
129 146 unsigned long mflags;
130 147 unsigned long irix_trampoline; /* Wheee... */
131 148 unsigned long irix_oldctx;
  149 + struct mips_abi *abi;
132 150 };
133 151  
134 152 #define MF_ABI_MASK (MF_32BIT_REGS | MF_32BIT_ADDR)
... ... @@ -150,6 +168,10 @@
150 168 * saved fpu/fpu emulator stuff \
151 169 */ \
152 170 INIT_FPU, \
  171 + /* \
  172 + * saved dsp/dsp emulator stuff \
  173 + */ \
  174 + INIT_DSP, \
153 175 /* \
154 176 * Other stuff associated with the process \
155 177 */ \
include/asm-mips/ptrace.h
... ... @@ -22,6 +22,8 @@
22 22 #define MMLO 68
23 23 #define FPC_CSR 69
24 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 29 * This struct defines the way the registers are stored on the stack during a
28 30  
... ... @@ -38,8 +40,8 @@
38 40  
39 41 /* Saved special registers. */
40 42 unsigned long cp0_status;
41   - unsigned long lo;
42 43 unsigned long hi;
  44 + unsigned long lo;
43 45 unsigned long cp0_badvaddr;
44 46 unsigned long cp0_cause;
45 47 unsigned long cp0_epc;
include/asm-mips/sigcontext.h
... ... @@ -27,14 +27,15 @@
27 27 unsigned int sc_fpc_csr;
28 28 unsigned int sc_fpc_eir; /* Unused */
29 29 unsigned int sc_used_math;
30   - unsigned int sc_ssflags; /* Unused */
  30 + unsigned int sc_dsp; /* dsp status, was sc_ssflags */
31 31 unsigned long long sc_mdhi;
32 32 unsigned long long sc_mdlo;
33   -
34   - unsigned int sc_cause; /* Unused */
35   - unsigned int sc_badvaddr; /* Unused */
36   -
37   - unsigned long sc_sigset[4]; /* kernel's sigset_t */
  33 + unsigned long sc_hi1; /* Was sc_cause */
  34 + unsigned long sc_lo1; /* Was sc_badvaddr */
  35 + unsigned long sc_hi2; /* Was sc_sigset[4] */
  36 + unsigned long sc_lo2;
  37 + unsigned long sc_hi3;
  38 + unsigned long sc_lo3;
38 39 };
39 40  
40 41 #endif /* _MIPS_SIM == _MIPS_SIM_ABI32 */
41 42  
42 43  
43 44  
44 45  
... ... @@ -48,19 +49,19 @@
48 49 * Warning: this structure illdefined with sc_badvaddr being just an unsigned
49 50 * int so it was changed to unsigned long in 2.6.0-test1. This may break
50 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 */
52 55 struct sigcontext {
53 56 unsigned long sc_regs[32];
54 57 unsigned long sc_fpregs[32];
55   - unsigned long sc_mdhi;
56   - unsigned long sc_mdlo;
  58 + unsigned long sc_hi[4];
  59 + unsigned long sc_lo[4];
57 60 unsigned long sc_pc;
58   - unsigned long sc_badvaddr;
59   - unsigned int sc_status;
60 61 unsigned int sc_fpc_csr;
61   - unsigned int sc_fpc_eir;
62 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 67 #ifdef __KERNEL__
... ... @@ -68,23 +69,24 @@
68 69 #include <linux/posix_types.h>
69 70  
70 71 struct sigcontext32 {
71   - __u32 sc_regmask; /* Unused */
72   - __u32 sc_status;
73   - __u64 sc_pc;
74   - __u64 sc_regs[32];
75   - __u64 sc_fpregs[32];
76   - __u32 sc_ownedfp; /* Unused */
77   - __u32 sc_fpc_csr;
78   - __u32 sc_fpc_eir; /* Unused */
79   - __u32 sc_used_math;
80   - __u32 sc_ssflags; /* Unused */
81   - __u64 sc_mdhi;
82   - __u64 sc_mdlo;
83   -
84   - __u32 sc_cause; /* Unused */
85   - __u32 sc_badvaddr; /* Unused */
86   -
87   - __u32 sc_sigset[4]; /* kernel's sigset_t */
  72 + __u32 sc_regmask; /* Unused */
  73 + __u32 sc_status;
  74 + __u64 sc_pc;
  75 + __u64 sc_regs[32];
  76 + __u64 sc_fpregs[32];
  77 + __u32 sc_ownedfp; /* Unused */
  78 + __u32 sc_fpc_csr;
  79 + __u32 sc_fpc_eir; /* Unused */
  80 + __u32 sc_used_math;
  81 + __u32 sc_dsp; /* dsp status, was sc_ssflags */
  82 + __u64 sc_mdhi;
  83 + __u64 sc_mdlo;
  84 + __u32 sc_hi1; /* Was sc_cause */
  85 + __u32 sc_lo1; /* Was sc_badvaddr */
  86 + __u32 sc_hi2; /* Was sc_sigset[4] */
  87 + __u32 sc_lo2;
  88 + __u32 sc_hi3;
  89 + __u32 sc_lo3;
88 90 };
89 91 #endif /* __KERNEL__ */
90 92  
include/asm-mips/signal.h
... ... @@ -98,12 +98,39 @@
98 98 #define MINSIGSTKSZ 2048
99 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 120 #define SIG_BLOCK 1 /* for blocking signals */
102 121 #define SIG_UNBLOCK 2 /* for unblocking signals */
103 122 #define SIG_SETMASK 3 /* for setting the signal mask */
104 123 #define SIG_SETMASK32 256 /* Goodie from SGI for BSD compatibility:
105 124 set only the low 32 bit of the sigset. */
106   -#include <asm-generic/signal.h>
  125 +
  126 +/* Type of a signal handler. */
  127 +typedef void __signalfn_t(int);
  128 +typedef __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  
108 135 struct sigaction {
109 136 unsigned int sa_flags;
include/asm-mips/system.h
... ... @@ -17,6 +17,7 @@
17 17  
18 18 #include <asm/addrspace.h>
19 19 #include <asm/cpu-features.h>
  20 +#include <asm/dsp.h>
20 21 #include <asm/ptrace.h>
21 22 #include <asm/war.h>
22 23 #include <asm/interrupt.h>
... ... @@ -154,9 +155,13 @@
154 155  
155 156 struct task_struct;
156 157  
157   -#define switch_to(prev,next,last) \
158   -do { \
159   - (last) = resume(prev, next, next->thread_info); \
  158 +#define switch_to(prev,next,last) \
  159 +do { \
  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 165 } while(0)
161 166  
162 167 #define ROT_IN_PIECES \