diff options
| author | Jeff Garzik <jgarzik@pobox.com> | 2005-10-29 17:49:12 -0400 | 
|---|---|---|
| committer | Jeff Garzik <jgarzik@pobox.com> | 2005-10-29 17:49:12 -0400 | 
| commit | b0c4e148bd591629749d02a8fbc8d81c26d548cf (patch) | |
| tree | 3e2142635f3dc2ceeae870ead2dceab7b9c6def1 /arch/mips/kernel/branch.c | |
| parent | 5615ca7906aefbdc3318604c89db5931d0a25910 (diff) | |
| parent | be15cd72d256e5eb3261a781b8507fac83ab33f6 (diff) | |
Merge branch 'master'
Diffstat (limited to 'arch/mips/kernel/branch.c')
| -rw-r--r-- | arch/mips/kernel/branch.c | 29 | 
1 files changed, 25 insertions, 4 deletions
diff --git a/arch/mips/kernel/branch.c b/arch/mips/kernel/branch.c index 01117e977a7f..374de839558d 100644 --- a/arch/mips/kernel/branch.c +++ b/arch/mips/kernel/branch.c  | |||
| @@ -12,6 +12,7 @@ | |||
| 12 | #include <asm/branch.h> | 12 | #include <asm/branch.h> | 
| 13 | #include <asm/cpu.h> | 13 | #include <asm/cpu.h> | 
| 14 | #include <asm/cpu-features.h> | 14 | #include <asm/cpu-features.h> | 
| 15 | #include <asm/fpu.h> | ||
| 15 | #include <asm/inst.h> | 16 | #include <asm/inst.h> | 
| 16 | #include <asm/ptrace.h> | 17 | #include <asm/ptrace.h> | 
| 17 | #include <asm/uaccess.h> | 18 | #include <asm/uaccess.h> | 
| @@ -21,7 +22,7 @@ | |||
| 21 | */ | 22 | */ | 
| 22 | int __compute_return_epc(struct pt_regs *regs) | 23 | int __compute_return_epc(struct pt_regs *regs) | 
| 23 | { | 24 | { | 
| 24 | unsigned int *addr, bit, fcr31; | 25 | unsigned int *addr, bit, fcr31, dspcontrol; | 
| 25 | long epc; | 26 | long epc; | 
| 26 | union mips_instruction insn; | 27 | union mips_instruction insn; | 
| 27 | 28 | ||
| @@ -98,6 +99,18 @@ int __compute_return_epc(struct pt_regs *regs) | |||
| 98 | epc += 8; | 99 | epc += 8; | 
| 99 | regs->cp0_epc = epc; | 100 | regs->cp0_epc = epc; | 
| 100 | 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; | ||
| 101 | } | 114 | } | 
| 102 | break; | 115 | break; | 
| 103 | 116 | ||
| @@ -161,10 +174,13 @@ int __compute_return_epc(struct pt_regs *regs) | |||
| 161 | * And now the FPA/cp1 branch instructions. | 174 | * And now the FPA/cp1 branch instructions. | 
| 162 | */ | 175 | */ | 
| 163 | case cop1_op: | 176 | case cop1_op: | 
| 164 | if (!cpu_has_fpu) | 177 | preempt_disable(); | 
| 165 | fcr31 = current->thread.fpu.soft.fcr31; | 178 | if (is_fpu_owner()) | 
| 166 | else | ||
| 167 | asm volatile("cfc1\t%0,$31" : "=r" (fcr31)); | 179 | asm volatile("cfc1\t%0,$31" : "=r" (fcr31)); | 
| 180 | else | ||
| 181 | fcr31 = current->thread.fpu.hard.fcr31; | ||
| 182 | preempt_enable(); | ||
| 183 | |||
| 168 | bit = (insn.i_format.rt >> 2); | 184 | bit = (insn.i_format.rt >> 2); | 
| 169 | bit += (bit != 0); | 185 | bit += (bit != 0); | 
| 170 | bit += 23; | 186 | bit += 23; | 
| @@ -196,4 +212,9 @@ unaligned: | |||
| 196 | printk("%s: unaligned epc - sending SIGBUS.\n", current->comm); | 212 | printk("%s: unaligned epc - sending SIGBUS.\n", current->comm); | 
| 197 | force_sig(SIGBUS, current); | 213 | force_sig(SIGBUS, current); | 
| 198 | return -EFAULT; | 214 | return -EFAULT; | 
| 215 | |||
| 216 | sigill: | ||
| 217 | printk("%s: DSP branch but not DSP ASE - sending SIGBUS.\n", current->comm); | ||
| 218 | force_sig(SIGBUS, current); | ||
| 219 | return -EFAULT; | ||
| 199 | } | 220 | } | 
