diff options
| -rw-r--r-- | arch/mips/Makefile | 2 | ||||
| -rw-r--r-- | arch/mips/boot/dts/mti/malta.dts | 3 | ||||
| -rw-r--r-- | arch/mips/generic/init.c | 16 | ||||
| -rw-r--r-- | arch/mips/include/asm/fpu_emulator.h | 13 | ||||
| -rw-r--r-- | arch/mips/include/asm/switch_to.h | 18 | ||||
| -rw-r--r-- | arch/mips/kernel/mips-cpc.c | 11 | ||||
| -rw-r--r-- | arch/mips/kernel/mips-r2-to-r6-emul.c | 10 | ||||
| -rw-r--r-- | arch/mips/kernel/ptrace.c | 8 | ||||
| -rw-r--r-- | arch/mips/kernel/r2300_fpu.S | 138 | ||||
| -rw-r--r-- | arch/mips/kernel/r6000_fpu.S | 89 | ||||
| -rw-r--r-- | arch/mips/kernel/relocate.c | 2 | ||||
| -rw-r--r-- | arch/mips/kernel/setup.c | 13 | ||||
| -rw-r--r-- | arch/mips/kernel/traps.c | 137 | ||||
| -rw-r--r-- | arch/mips/lib/dump_tlb.c | 44 | ||||
| -rw-r--r-- | arch/mips/lib/r3k_dump_tlb.c | 18 |
15 files changed, 287 insertions, 235 deletions
diff --git a/arch/mips/Makefile b/arch/mips/Makefile index fbf40d3c8123..1a6bac7b076f 100644 --- a/arch/mips/Makefile +++ b/arch/mips/Makefile | |||
| @@ -263,7 +263,7 @@ KBUILD_CPPFLAGS += -DDATAOFFSET=$(if $(dataoffset-y),$(dataoffset-y),0) | |||
| 263 | 263 | ||
| 264 | bootvars-y = VMLINUX_LOAD_ADDRESS=$(load-y) \ | 264 | bootvars-y = VMLINUX_LOAD_ADDRESS=$(load-y) \ |
| 265 | VMLINUX_ENTRY_ADDRESS=$(entry-y) \ | 265 | VMLINUX_ENTRY_ADDRESS=$(entry-y) \ |
| 266 | PLATFORM=$(platform-y) | 266 | PLATFORM="$(platform-y)" |
| 267 | ifdef CONFIG_32BIT | 267 | ifdef CONFIG_32BIT |
| 268 | bootvars-y += ADDR_BITS=32 | 268 | bootvars-y += ADDR_BITS=32 |
| 269 | endif | 269 | endif |
diff --git a/arch/mips/boot/dts/mti/malta.dts b/arch/mips/boot/dts/mti/malta.dts index f604a272d91d..ffe3a1508e72 100644 --- a/arch/mips/boot/dts/mti/malta.dts +++ b/arch/mips/boot/dts/mti/malta.dts | |||
| @@ -84,12 +84,13 @@ | |||
| 84 | fpga_regs: system-controller@1f000000 { | 84 | fpga_regs: system-controller@1f000000 { |
| 85 | compatible = "mti,malta-fpga", "syscon", "simple-mfd"; | 85 | compatible = "mti,malta-fpga", "syscon", "simple-mfd"; |
| 86 | reg = <0x1f000000 0x1000>; | 86 | reg = <0x1f000000 0x1000>; |
| 87 | native-endian; | ||
| 87 | 88 | ||
| 88 | reboot { | 89 | reboot { |
| 89 | compatible = "syscon-reboot"; | 90 | compatible = "syscon-reboot"; |
| 90 | regmap = <&fpga_regs>; | 91 | regmap = <&fpga_regs>; |
| 91 | offset = <0x500>; | 92 | offset = <0x500>; |
| 92 | mask = <0x4d>; | 93 | mask = <0x42>; |
| 93 | }; | 94 | }; |
| 94 | }; | 95 | }; |
| 95 | 96 | ||
diff --git a/arch/mips/generic/init.c b/arch/mips/generic/init.c index 0ea73e845440..d493ccbf274a 100644 --- a/arch/mips/generic/init.c +++ b/arch/mips/generic/init.c | |||
| @@ -30,9 +30,19 @@ static __initdata const void *mach_match_data; | |||
| 30 | 30 | ||
| 31 | void __init prom_init(void) | 31 | void __init prom_init(void) |
| 32 | { | 32 | { |
| 33 | plat_get_fdt(); | ||
| 34 | BUG_ON(!fdt); | ||
| 35 | } | ||
| 36 | |||
| 37 | void __init *plat_get_fdt(void) | ||
| 38 | { | ||
| 33 | const struct mips_machine *check_mach; | 39 | const struct mips_machine *check_mach; |
| 34 | const struct of_device_id *match; | 40 | const struct of_device_id *match; |
| 35 | 41 | ||
| 42 | if (fdt) | ||
| 43 | /* Already set up */ | ||
| 44 | return (void *)fdt; | ||
| 45 | |||
| 36 | if ((fw_arg0 == -2) && !fdt_check_header((void *)fw_arg1)) { | 46 | if ((fw_arg0 == -2) && !fdt_check_header((void *)fw_arg1)) { |
| 37 | /* | 47 | /* |
| 38 | * We booted using the UHI boot protocol, so we have been | 48 | * We booted using the UHI boot protocol, so we have been |
| @@ -75,12 +85,6 @@ void __init prom_init(void) | |||
| 75 | /* Retrieve the machine's FDT */ | 85 | /* Retrieve the machine's FDT */ |
| 76 | fdt = mach->fdt; | 86 | fdt = mach->fdt; |
| 77 | } | 87 | } |
| 78 | |||
| 79 | BUG_ON(!fdt); | ||
| 80 | } | ||
| 81 | |||
| 82 | void __init *plat_get_fdt(void) | ||
| 83 | { | ||
| 84 | return (void *)fdt; | 88 | return (void *)fdt; |
| 85 | } | 89 | } |
| 86 | 90 | ||
diff --git a/arch/mips/include/asm/fpu_emulator.h b/arch/mips/include/asm/fpu_emulator.h index 355dc25172e7..c05369e0b8d6 100644 --- a/arch/mips/include/asm/fpu_emulator.h +++ b/arch/mips/include/asm/fpu_emulator.h | |||
| @@ -63,6 +63,8 @@ do { \ | |||
| 63 | extern int fpu_emulator_cop1Handler(struct pt_regs *xcp, | 63 | extern int fpu_emulator_cop1Handler(struct pt_regs *xcp, |
| 64 | struct mips_fpu_struct *ctx, int has_fpu, | 64 | struct mips_fpu_struct *ctx, int has_fpu, |
| 65 | void *__user *fault_addr); | 65 | void *__user *fault_addr); |
| 66 | void force_fcr31_sig(unsigned long fcr31, void __user *fault_addr, | ||
| 67 | struct task_struct *tsk); | ||
| 66 | int process_fpemu_return(int sig, void __user *fault_addr, | 68 | int process_fpemu_return(int sig, void __user *fault_addr, |
| 67 | unsigned long fcr31); | 69 | unsigned long fcr31); |
| 68 | int isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn, | 70 | int isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn, |
| @@ -81,4 +83,15 @@ static inline void fpu_emulator_init_fpu(void) | |||
| 81 | set_fpr64(&t->thread.fpu.fpr[i], 0, SIGNALLING_NAN); | 83 | set_fpr64(&t->thread.fpu.fpr[i], 0, SIGNALLING_NAN); |
| 82 | } | 84 | } |
| 83 | 85 | ||
| 86 | /* | ||
| 87 | * Mask the FCSR Cause bits according to the Enable bits, observing | ||
| 88 | * that Unimplemented is always enabled. | ||
| 89 | */ | ||
| 90 | static inline unsigned long mask_fcr31_x(unsigned long fcr31) | ||
| 91 | { | ||
| 92 | return fcr31 & (FPU_CSR_UNI_X | | ||
| 93 | ((fcr31 & FPU_CSR_ALL_E) << | ||
| 94 | (ffs(FPU_CSR_ALL_X) - ffs(FPU_CSR_ALL_E)))); | ||
| 95 | } | ||
| 96 | |||
| 84 | #endif /* _ASM_FPU_EMULATOR_H */ | 97 | #endif /* _ASM_FPU_EMULATOR_H */ |
diff --git a/arch/mips/include/asm/switch_to.h b/arch/mips/include/asm/switch_to.h index ebb5c0f2f90d..c0ae27971e31 100644 --- a/arch/mips/include/asm/switch_to.h +++ b/arch/mips/include/asm/switch_to.h | |||
| @@ -76,6 +76,22 @@ do { if (cpu_has_rw_llb) { \ | |||
| 76 | } while (0) | 76 | } while (0) |
| 77 | 77 | ||
| 78 | /* | 78 | /* |
| 79 | * Check FCSR for any unmasked exceptions pending set with `ptrace', | ||
| 80 | * clear them and send a signal. | ||
| 81 | */ | ||
| 82 | #define __sanitize_fcr31(next) \ | ||
| 83 | do { \ | ||
| 84 | unsigned long fcr31 = mask_fcr31_x(next->thread.fpu.fcr31); \ | ||
| 85 | void __user *pc; \ | ||
| 86 | \ | ||
| 87 | if (unlikely(fcr31)) { \ | ||
| 88 | pc = (void __user *)task_pt_regs(next)->cp0_epc; \ | ||
| 89 | next->thread.fpu.fcr31 &= ~fcr31; \ | ||
| 90 | force_fcr31_sig(fcr31, pc, next); \ | ||
| 91 | } \ | ||
| 92 | } while (0) | ||
| 93 | |||
| 94 | /* | ||
| 79 | * For newly created kernel threads switch_to() will return to | 95 | * For newly created kernel threads switch_to() will return to |
| 80 | * ret_from_kernel_thread, newly created user threads to ret_from_fork. | 96 | * ret_from_kernel_thread, newly created user threads to ret_from_fork. |
| 81 | * That is, everything following resume() will be skipped for new threads. | 97 | * That is, everything following resume() will be skipped for new threads. |
| @@ -85,6 +101,8 @@ do { if (cpu_has_rw_llb) { \ | |||
| 85 | do { \ | 101 | do { \ |
| 86 | __mips_mt_fpaff_switch_to(prev); \ | 102 | __mips_mt_fpaff_switch_to(prev); \ |
| 87 | lose_fpu_inatomic(1, prev); \ | 103 | lose_fpu_inatomic(1, prev); \ |
| 104 | if (tsk_used_math(next)) \ | ||
| 105 | __sanitize_fcr31(next); \ | ||
| 88 | if (cpu_has_dsp) { \ | 106 | if (cpu_has_dsp) { \ |
| 89 | __save_dsp(prev); \ | 107 | __save_dsp(prev); \ |
| 90 | __restore_dsp(next); \ | 108 | __restore_dsp(next); \ |
diff --git a/arch/mips/kernel/mips-cpc.c b/arch/mips/kernel/mips-cpc.c index 2a45867d3b4f..a4964c334cab 100644 --- a/arch/mips/kernel/mips-cpc.c +++ b/arch/mips/kernel/mips-cpc.c | |||
| @@ -21,6 +21,11 @@ static DEFINE_PER_CPU_ALIGNED(spinlock_t, cpc_core_lock); | |||
| 21 | 21 | ||
| 22 | static DEFINE_PER_CPU_ALIGNED(unsigned long, cpc_core_lock_flags); | 22 | static DEFINE_PER_CPU_ALIGNED(unsigned long, cpc_core_lock_flags); |
| 23 | 23 | ||
| 24 | phys_addr_t __weak mips_cpc_default_phys_base(void) | ||
| 25 | { | ||
| 26 | return 0; | ||
| 27 | } | ||
| 28 | |||
| 24 | /** | 29 | /** |
| 25 | * mips_cpc_phys_base - retrieve the physical base address of the CPC | 30 | * mips_cpc_phys_base - retrieve the physical base address of the CPC |
| 26 | * | 31 | * |
| @@ -43,8 +48,12 @@ static phys_addr_t mips_cpc_phys_base(void) | |||
| 43 | if (cpc_base & CM_GCR_CPC_BASE_CPCEN_MSK) | 48 | if (cpc_base & CM_GCR_CPC_BASE_CPCEN_MSK) |
| 44 | return cpc_base & CM_GCR_CPC_BASE_CPCBASE_MSK; | 49 | return cpc_base & CM_GCR_CPC_BASE_CPCBASE_MSK; |
| 45 | 50 | ||
| 46 | /* Otherwise, give it the default address & enable it */ | 51 | /* Otherwise, use the default address */ |
| 47 | cpc_base = mips_cpc_default_phys_base(); | 52 | cpc_base = mips_cpc_default_phys_base(); |
| 53 | if (!cpc_base) | ||
| 54 | return cpc_base; | ||
| 55 | |||
| 56 | /* Enable the CPC, mapped at the default address */ | ||
| 48 | write_gcr_cpc_base(cpc_base | CM_GCR_CPC_BASE_CPCEN_MSK); | 57 | write_gcr_cpc_base(cpc_base | CM_GCR_CPC_BASE_CPCEN_MSK); |
| 49 | return cpc_base; | 58 | return cpc_base; |
| 50 | } | 59 | } |
diff --git a/arch/mips/kernel/mips-r2-to-r6-emul.c b/arch/mips/kernel/mips-r2-to-r6-emul.c index 22dedd62818a..bd09853aecdf 100644 --- a/arch/mips/kernel/mips-r2-to-r6-emul.c +++ b/arch/mips/kernel/mips-r2-to-r6-emul.c | |||
| @@ -899,7 +899,7 @@ static inline int mipsr2_find_op_func(struct pt_regs *regs, u32 inst, | |||
| 899 | * mipsr2_decoder: Decode and emulate a MIPS R2 instruction | 899 | * mipsr2_decoder: Decode and emulate a MIPS R2 instruction |
| 900 | * @regs: Process register set | 900 | * @regs: Process register set |
| 901 | * @inst: Instruction to decode and emulate | 901 | * @inst: Instruction to decode and emulate |
| 902 | * @fcr31: Floating Point Control and Status Register returned | 902 | * @fcr31: Floating Point Control and Status Register Cause bits returned |
| 903 | */ | 903 | */ |
| 904 | int mipsr2_decoder(struct pt_regs *regs, u32 inst, unsigned long *fcr31) | 904 | int mipsr2_decoder(struct pt_regs *regs, u32 inst, unsigned long *fcr31) |
| 905 | { | 905 | { |
| @@ -1172,13 +1172,13 @@ fpu_emul: | |||
| 1172 | 1172 | ||
| 1173 | err = fpu_emulator_cop1Handler(regs, ¤t->thread.fpu, 0, | 1173 | err = fpu_emulator_cop1Handler(regs, ¤t->thread.fpu, 0, |
| 1174 | &fault_addr); | 1174 | &fault_addr); |
| 1175 | *fcr31 = current->thread.fpu.fcr31; | ||
| 1176 | 1175 | ||
| 1177 | /* | 1176 | /* |
| 1178 | * We can't allow the emulated instruction to leave any of | 1177 | * We can't allow the emulated instruction to leave any |
| 1179 | * the cause bits set in $fcr31. | 1178 | * enabled Cause bits set in $fcr31. |
| 1180 | */ | 1179 | */ |
| 1181 | current->thread.fpu.fcr31 &= ~FPU_CSR_ALL_X; | 1180 | *fcr31 = res = mask_fcr31_x(current->thread.fpu.fcr31); |
| 1181 | current->thread.fpu.fcr31 &= ~res; | ||
| 1182 | 1182 | ||
| 1183 | /* | 1183 | /* |
| 1184 | * this is a tricky issue - lose_fpu() uses LL/SC atomics | 1184 | * this is a tricky issue - lose_fpu() uses LL/SC atomics |
diff --git a/arch/mips/kernel/ptrace.c b/arch/mips/kernel/ptrace.c index 6103b24d1bfc..a92994d60e91 100644 --- a/arch/mips/kernel/ptrace.c +++ b/arch/mips/kernel/ptrace.c | |||
| @@ -79,16 +79,15 @@ void ptrace_disable(struct task_struct *child) | |||
| 79 | } | 79 | } |
| 80 | 80 | ||
| 81 | /* | 81 | /* |
| 82 | * Poke at FCSR according to its mask. Don't set the cause bits as | 82 | * Poke at FCSR according to its mask. Set the Cause bits even |
| 83 | * this is currently not handled correctly in FP context restoration | 83 | * if a corresponding Enable bit is set. This will be noticed at |
| 84 | * and will cause an oops if a corresponding enable bit is set. | 84 | * the time the thread is switched to and SIGFPE thrown accordingly. |
| 85 | */ | 85 | */ |
| 86 | static void ptrace_setfcr31(struct task_struct *child, u32 value) | 86 | static void ptrace_setfcr31(struct task_struct *child, u32 value) |
| 87 | { | 87 | { |
| 88 | u32 fcr31; | 88 | u32 fcr31; |
| 89 | u32 mask; | 89 | u32 mask; |
| 90 | 90 | ||
| 91 | value &= ~FPU_CSR_ALL_X; | ||
| 92 | fcr31 = child->thread.fpu.fcr31; | 91 | fcr31 = child->thread.fpu.fcr31; |
| 93 | mask = boot_cpu_data.fpu_msk31; | 92 | mask = boot_cpu_data.fpu_msk31; |
| 94 | child->thread.fpu.fcr31 = (value & ~mask) | (fcr31 & mask); | 93 | child->thread.fpu.fcr31 = (value & ~mask) | (fcr31 & mask); |
| @@ -817,6 +816,7 @@ long arch_ptrace(struct task_struct *child, long request, | |||
| 817 | break; | 816 | break; |
| 818 | #endif | 817 | #endif |
| 819 | case FPC_CSR: | 818 | case FPC_CSR: |
| 819 | init_fp_ctx(child); | ||
| 820 | ptrace_setfcr31(child, data); | 820 | ptrace_setfcr31(child, data); |
| 821 | break; | 821 | break; |
| 822 | case DSP_BASE ... DSP_BASE + 5: { | 822 | case DSP_BASE ... DSP_BASE + 5: { |
diff --git a/arch/mips/kernel/r2300_fpu.S b/arch/mips/kernel/r2300_fpu.S index b4ac6374a38f..918f2f6d3861 100644 --- a/arch/mips/kernel/r2300_fpu.S +++ b/arch/mips/kernel/r2300_fpu.S | |||
| @@ -21,106 +21,84 @@ | |||
| 21 | #define EX(a,b) \ | 21 | #define EX(a,b) \ |
| 22 | 9: a,##b; \ | 22 | 9: a,##b; \ |
| 23 | .section __ex_table,"a"; \ | 23 | .section __ex_table,"a"; \ |
| 24 | PTR 9b,fault; \ | ||
| 25 | .previous | ||
| 26 | |||
| 27 | #define EX2(a,b) \ | ||
| 28 | 9: a,##b; \ | ||
| 29 | .section __ex_table,"a"; \ | ||
| 24 | PTR 9b,bad_stack; \ | 30 | PTR 9b,bad_stack; \ |
| 31 | PTR 9b+4,bad_stack; \ | ||
| 25 | .previous | 32 | .previous |
| 26 | 33 | ||
| 27 | .set noreorder | 34 | .set noreorder |
| 28 | .set mips1 | 35 | .set mips1 |
| 29 | /* Save floating point context */ | 36 | |
| 37 | /** | ||
| 38 | * _save_fp_context() - save FP context from the FPU | ||
| 39 | * @a0 - pointer to fpregs field of sigcontext | ||
| 40 | * @a1 - pointer to fpc_csr field of sigcontext | ||
| 41 | * | ||
| 42 | * Save FP context, including the 32 FP data registers and the FP | ||
| 43 | * control & status register, from the FPU to signal context. | ||
| 44 | */ | ||
| 30 | LEAF(_save_fp_context) | 45 | LEAF(_save_fp_context) |
| 31 | .set push | 46 | .set push |
| 32 | SET_HARDFLOAT | 47 | SET_HARDFLOAT |
| 33 | li v0, 0 # assume success | 48 | li v0, 0 # assume success |
| 34 | cfc1 t1,fcr31 | 49 | cfc1 t1, fcr31 |
| 35 | EX(swc1 $f0,(SC_FPREGS+0)(a0)) | 50 | EX2(s.d $f0, 0(a0)) |
| 36 | EX(swc1 $f1,(SC_FPREGS+8)(a0)) | 51 | EX2(s.d $f2, 16(a0)) |
| 37 | EX(swc1 $f2,(SC_FPREGS+16)(a0)) | 52 | EX2(s.d $f4, 32(a0)) |
| 38 | EX(swc1 $f3,(SC_FPREGS+24)(a0)) | 53 | EX2(s.d $f6, 48(a0)) |
| 39 | EX(swc1 $f4,(SC_FPREGS+32)(a0)) | 54 | EX2(s.d $f8, 64(a0)) |
| 40 | EX(swc1 $f5,(SC_FPREGS+40)(a0)) | 55 | EX2(s.d $f10, 80(a0)) |
| 41 | EX(swc1 $f6,(SC_FPREGS+48)(a0)) | 56 | EX2(s.d $f12, 96(a0)) |
| 42 | EX(swc1 $f7,(SC_FPREGS+56)(a0)) | 57 | EX2(s.d $f14, 112(a0)) |
| 43 | EX(swc1 $f8,(SC_FPREGS+64)(a0)) | 58 | EX2(s.d $f16, 128(a0)) |
| 44 | EX(swc1 $f9,(SC_FPREGS+72)(a0)) | 59 | EX2(s.d $f18, 144(a0)) |
| 45 | EX(swc1 $f10,(SC_FPREGS+80)(a0)) | 60 | EX2(s.d $f20, 160(a0)) |
| 46 | EX(swc1 $f11,(SC_FPREGS+88)(a0)) | 61 | EX2(s.d $f22, 176(a0)) |
| 47 | EX(swc1 $f12,(SC_FPREGS+96)(a0)) | 62 | EX2(s.d $f24, 192(a0)) |
| 48 | EX(swc1 $f13,(SC_FPREGS+104)(a0)) | 63 | EX2(s.d $f26, 208(a0)) |
| 49 | EX(swc1 $f14,(SC_FPREGS+112)(a0)) | 64 | EX2(s.d $f28, 224(a0)) |
| 50 | EX(swc1 $f15,(SC_FPREGS+120)(a0)) | 65 | EX2(s.d $f30, 240(a0)) |
| 51 | EX(swc1 $f16,(SC_FPREGS+128)(a0)) | ||
| 52 | EX(swc1 $f17,(SC_FPREGS+136)(a0)) | ||
| 53 | EX(swc1 $f18,(SC_FPREGS+144)(a0)) | ||
| 54 | EX(swc1 $f19,(SC_FPREGS+152)(a0)) | ||
| 55 | EX(swc1 $f20,(SC_FPREGS+160)(a0)) | ||
| 56 | EX(swc1 $f21,(SC_FPREGS+168)(a0)) | ||
| 57 | EX(swc1 $f22,(SC_FPREGS+176)(a0)) | ||
| 58 | EX(swc1 $f23,(SC_FPREGS+184)(a0)) | ||
| 59 | EX(swc1 $f24,(SC_FPREGS+192)(a0)) | ||
| 60 | EX(swc1 $f25,(SC_FPREGS+200)(a0)) | ||
| 61 | EX(swc1 $f26,(SC_FPREGS+208)(a0)) | ||
| 62 | EX(swc1 $f27,(SC_FPREGS+216)(a0)) | ||
| 63 | EX(swc1 $f28,(SC_FPREGS+224)(a0)) | ||
| 64 | EX(swc1 $f29,(SC_FPREGS+232)(a0)) | ||
| 65 | EX(swc1 $f30,(SC_FPREGS+240)(a0)) | ||
| 66 | EX(swc1 $f31,(SC_FPREGS+248)(a0)) | ||
| 67 | EX(sw t1,(SC_FPC_CSR)(a0)) | ||
| 68 | cfc1 t0,$0 # implementation/version | ||
| 69 | jr ra | 66 | jr ra |
| 67 | EX(sw t1, (a1)) | ||
| 70 | .set pop | 68 | .set pop |
| 71 | .set nomacro | ||
| 72 | EX(sw t0,(SC_FPC_EIR)(a0)) | ||
| 73 | .set macro | ||
| 74 | END(_save_fp_context) | 69 | END(_save_fp_context) |
| 75 | 70 | ||
| 76 | /* | 71 | /** |
| 77 | * Restore FPU state: | 72 | * _restore_fp_context() - restore FP context to the FPU |
| 78 | * - fp gp registers | 73 | * @a0 - pointer to fpregs field of sigcontext |
| 79 | * - cp1 status/control register | 74 | * @a1 - pointer to fpc_csr field of sigcontext |
| 80 | * | 75 | * |
| 81 | * We base the decision which registers to restore from the signal stack | 76 | * Restore FP context, including the 32 FP data registers and the FP |
| 82 | * frame on the current content of c0_status, not on the content of the | 77 | * control & status register, from signal context to the FPU. |
| 83 | * stack frame which might have been changed by the user. | ||
| 84 | */ | 78 | */ |
| 85 | LEAF(_restore_fp_context) | 79 | LEAF(_restore_fp_context) |
| 86 | .set push | 80 | .set push |
| 87 | SET_HARDFLOAT | 81 | SET_HARDFLOAT |
| 88 | li v0, 0 # assume success | 82 | li v0, 0 # assume success |
| 89 | EX(lw t0,(SC_FPC_CSR)(a0)) | 83 | EX(lw t0, (a1)) |
| 90 | EX(lwc1 $f0,(SC_FPREGS+0)(a0)) | 84 | EX2(l.d $f0, 0(a0)) |
| 91 | EX(lwc1 $f1,(SC_FPREGS+8)(a0)) | 85 | EX2(l.d $f2, 16(a0)) |
| 92 | EX(lwc1 $f2,(SC_FPREGS+16)(a0)) | 86 | EX2(l.d $f4, 32(a0)) |
| 93 | EX(lwc1 $f3,(SC_FPREGS+24)(a0)) | 87 | EX2(l.d $f6, 48(a0)) |
| 94 | EX(lwc1 $f4,(SC_FPREGS+32)(a0)) | 88 | EX2(l.d $f8, 64(a0)) |
| 95 | EX(lwc1 $f5,(SC_FPREGS+40)(a0)) | 89 | EX2(l.d $f10, 80(a0)) |
| 96 | EX(lwc1 $f6,(SC_FPREGS+48)(a0)) | 90 | EX2(l.d $f12, 96(a0)) |
| 97 | EX(lwc1 $f7,(SC_FPREGS+56)(a0)) | 91 | EX2(l.d $f14, 112(a0)) |
| 98 | EX(lwc1 $f8,(SC_FPREGS+64)(a0)) | 92 | EX2(l.d $f16, 128(a0)) |
| 99 | EX(lwc1 $f9,(SC_FPREGS+72)(a0)) | 93 | EX2(l.d $f18, 144(a0)) |
| 100 | EX(lwc1 $f10,(SC_FPREGS+80)(a0)) | 94 | EX2(l.d $f20, 160(a0)) |
| 101 | EX(lwc1 $f11,(SC_FPREGS+88)(a0)) | 95 | EX2(l.d $f22, 176(a0)) |
| 102 | EX(lwc1 $f12,(SC_FPREGS+96)(a0)) | 96 | EX2(l.d $f24, 192(a0)) |
| 103 | EX(lwc1 $f13,(SC_FPREGS+104)(a0)) | 97 | EX2(l.d $f26, 208(a0)) |
| 104 | EX(lwc1 $f14,(SC_FPREGS+112)(a0)) | 98 | EX2(l.d $f28, 224(a0)) |
| 105 | EX(lwc1 $f15,(SC_FPREGS+120)(a0)) | 99 | EX2(l.d $f30, 240(a0)) |
| 106 | EX(lwc1 $f16,(SC_FPREGS+128)(a0)) | ||
| 107 | EX(lwc1 $f17,(SC_FPREGS+136)(a0)) | ||
| 108 | EX(lwc1 $f18,(SC_FPREGS+144)(a0)) | ||
| 109 | EX(lwc1 $f19,(SC_FPREGS+152)(a0)) | ||
| 110 | EX(lwc1 $f20,(SC_FPREGS+160)(a0)) | ||
| 111 | EX(lwc1 $f21,(SC_FPREGS+168)(a0)) | ||
| 112 | EX(lwc1 $f22,(SC_FPREGS+176)(a0)) | ||
| 113 | EX(lwc1 $f23,(SC_FPREGS+184)(a0)) | ||
| 114 | EX(lwc1 $f24,(SC_FPREGS+192)(a0)) | ||
| 115 | EX(lwc1 $f25,(SC_FPREGS+200)(a0)) | ||
| 116 | EX(lwc1 $f26,(SC_FPREGS+208)(a0)) | ||
| 117 | EX(lwc1 $f27,(SC_FPREGS+216)(a0)) | ||
| 118 | EX(lwc1 $f28,(SC_FPREGS+224)(a0)) | ||
| 119 | EX(lwc1 $f29,(SC_FPREGS+232)(a0)) | ||
| 120 | EX(lwc1 $f30,(SC_FPREGS+240)(a0)) | ||
| 121 | EX(lwc1 $f31,(SC_FPREGS+248)(a0)) | ||
| 122 | jr ra | 100 | jr ra |
| 123 | ctc1 t0,fcr31 | 101 | ctc1 t0, fcr31 |
| 124 | .set pop | 102 | .set pop |
| 125 | END(_restore_fp_context) | 103 | END(_restore_fp_context) |
| 126 | .set reorder | 104 | .set reorder |
diff --git a/arch/mips/kernel/r6000_fpu.S b/arch/mips/kernel/r6000_fpu.S index 47077380c15c..9cc7bfab3419 100644 --- a/arch/mips/kernel/r6000_fpu.S +++ b/arch/mips/kernel/r6000_fpu.S | |||
| @@ -21,7 +21,14 @@ | |||
| 21 | .set push | 21 | .set push |
| 22 | SET_HARDFLOAT | 22 | SET_HARDFLOAT |
| 23 | 23 | ||
| 24 | /* Save floating point context */ | 24 | /** |
| 25 | * _save_fp_context() - save FP context from the FPU | ||
| 26 | * @a0 - pointer to fpregs field of sigcontext | ||
| 27 | * @a1 - pointer to fpc_csr field of sigcontext | ||
| 28 | * | ||
| 29 | * Save FP context, including the 32 FP data registers and the FP | ||
| 30 | * control & status register, from the FPU to signal context. | ||
| 31 | */ | ||
| 25 | LEAF(_save_fp_context) | 32 | LEAF(_save_fp_context) |
| 26 | mfc0 t0,CP0_STATUS | 33 | mfc0 t0,CP0_STATUS |
| 27 | sll t0,t0,2 | 34 | sll t0,t0,2 |
| @@ -30,59 +37,59 @@ | |||
| 30 | 37 | ||
| 31 | cfc1 t1,fcr31 | 38 | cfc1 t1,fcr31 |
| 32 | /* Store the 16 double precision registers */ | 39 | /* Store the 16 double precision registers */ |
| 33 | sdc1 $f0,(SC_FPREGS+0)(a0) | 40 | sdc1 $f0,0(a0) |
| 34 | sdc1 $f2,(SC_FPREGS+16)(a0) | 41 | sdc1 $f2,16(a0) |
| 35 | sdc1 $f4,(SC_FPREGS+32)(a0) | 42 | sdc1 $f4,32(a0) |
| 36 | sdc1 $f6,(SC_FPREGS+48)(a0) | 43 | sdc1 $f6,48(a0) |
| 37 | sdc1 $f8,(SC_FPREGS+64)(a0) | 44 | sdc1 $f8,64(a0) |
| 38 | sdc1 $f10,(SC_FPREGS+80)(a0) | 45 | sdc1 $f10,80(a0) |
| 39 | sdc1 $f12,(SC_FPREGS+96)(a0) | 46 | sdc1 $f12,96(a0) |
| 40 | sdc1 $f14,(SC_FPREGS+112)(a0) | 47 | sdc1 $f14,112(a0) |
| 41 | sdc1 $f16,(SC_FPREGS+128)(a0) | 48 | sdc1 $f16,128(a0) |
| 42 | sdc1 $f18,(SC_FPREGS+144)(a0) | 49 | sdc1 $f18,144(a0) |
| 43 | sdc1 $f20,(SC_FPREGS+160)(a0) | 50 | sdc1 $f20,160(a0) |
| 44 | sdc1 $f22,(SC_FPREGS+176)(a0) | 51 | sdc1 $f22,176(a0) |
| 45 | sdc1 $f24,(SC_FPREGS+192)(a0) | 52 | sdc1 $f24,192(a0) |
| 46 | sdc1 $f26,(SC_FPREGS+208)(a0) | 53 | sdc1 $f26,208(a0) |
| 47 | sdc1 $f28,(SC_FPREGS+224)(a0) | 54 | sdc1 $f28,224(a0) |
| 48 | sdc1 $f30,(SC_FPREGS+240)(a0) | 55 | sdc1 $f30,240(a0) |
| 49 | jr ra | 56 | jr ra |
| 50 | sw t0,SC_FPC_CSR(a0) | 57 | sw t0,(a1) |
| 51 | 1: jr ra | 58 | 1: jr ra |
| 52 | nop | 59 | nop |
| 53 | END(_save_fp_context) | 60 | END(_save_fp_context) |
| 54 | 61 | ||
| 55 | /* Restore FPU state: | 62 | /** |
| 56 | * - fp gp registers | 63 | * _restore_fp_context() - restore FP context to the FPU |
| 57 | * - cp1 status/control register | 64 | * @a0 - pointer to fpregs field of sigcontext |
| 65 | * @a1 - pointer to fpc_csr field of sigcontext | ||
| 58 | * | 66 | * |
| 59 | * We base the decision which registers to restore from the signal stack | 67 | * Restore FP context, including the 32 FP data registers and the FP |
| 60 | * frame on the current content of c0_status, not on the content of the | 68 | * control & status register, from signal context to the FPU. |
| 61 | * stack frame which might have been changed by the user. | ||
| 62 | */ | 69 | */ |
| 63 | LEAF(_restore_fp_context) | 70 | LEAF(_restore_fp_context) |
| 64 | mfc0 t0,CP0_STATUS | 71 | mfc0 t0,CP0_STATUS |
| 65 | sll t0,t0,2 | 72 | sll t0,t0,2 |
| 66 | 73 | ||
| 67 | bgez t0,1f | 74 | bgez t0,1f |
| 68 | lw t0,SC_FPC_CSR(a0) | 75 | lw t0,(a1) |
| 69 | /* Restore the 16 double precision registers */ | 76 | /* Restore the 16 double precision registers */ |
| 70 | ldc1 $f0,(SC_FPREGS+0)(a0) | 77 | ldc1 $f0,0(a0) |
| 71 | ldc1 $f2,(SC_FPREGS+16)(a0) | 78 | ldc1 $f2,16(a0) |
| 72 | ldc1 $f4,(SC_FPREGS+32)(a0) | 79 | ldc1 $f4,32(a0) |
| 73 | ldc1 $f6,(SC_FPREGS+48)(a0) | 80 | ldc1 $f6,48(a0) |
| 74 | ldc1 $f8,(SC_FPREGS+64)(a0) | 81 | ldc1 $f8,64(a0) |
| 75 | ldc1 $f10,(SC_FPREGS+80)(a0) | 82 | ldc1 $f10,80(a0) |
| 76 | ldc1 $f12,(SC_FPREGS+96)(a0) | 83 | ldc1 $f12,96(a0) |
| 77 | ldc1 $f14,(SC_FPREGS+112)(a0) | 84 | ldc1 $f14,112(a0) |
| 78 | ldc1 $f16,(SC_FPREGS+128)(a0) | 85 | ldc1 $f16,128(a0) |
| 79 | ldc1 $f18,(SC_FPREGS+144)(a0) | 86 | ldc1 $f18,144(a0) |
| 80 | ldc1 $f20,(SC_FPREGS+160)(a0) | 87 | ldc1 $f20,160(a0) |
| 81 | ldc1 $f22,(SC_FPREGS+176)(a0) | 88 | ldc1 $f22,176(a0) |
| 82 | ldc1 $f24,(SC_FPREGS+192)(a0) | 89 | ldc1 $f24,192(a0) |
| 83 | ldc1 $f26,(SC_FPREGS+208)(a0) | 90 | ldc1 $f26,208(a0) |
| 84 | ldc1 $f28,(SC_FPREGS+224)(a0) | 91 | ldc1 $f28,224(a0) |
| 85 | ldc1 $f30,(SC_FPREGS+240)(a0) | 92 | ldc1 $f30,240(a0) |
| 86 | jr ra | 93 | jr ra |
| 87 | ctc1 t0,fcr31 | 94 | ctc1 t0,fcr31 |
| 88 | 1: jr ra | 95 | 1: jr ra |
diff --git a/arch/mips/kernel/relocate.c b/arch/mips/kernel/relocate.c index ca1cc30c0891..1958910b75c0 100644 --- a/arch/mips/kernel/relocate.c +++ b/arch/mips/kernel/relocate.c | |||
| @@ -200,7 +200,7 @@ static inline __init unsigned long get_random_boot(void) | |||
| 200 | 200 | ||
| 201 | #if defined(CONFIG_USE_OF) | 201 | #if defined(CONFIG_USE_OF) |
| 202 | /* Get any additional entropy passed in device tree */ | 202 | /* Get any additional entropy passed in device tree */ |
| 203 | { | 203 | if (initial_boot_params) { |
| 204 | int node, len; | 204 | int node, len; |
| 205 | u64 *prop; | 205 | u64 *prop; |
| 206 | 206 | ||
diff --git a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c index 0d57909d9026..f66e5ce505b2 100644 --- a/arch/mips/kernel/setup.c +++ b/arch/mips/kernel/setup.c | |||
| @@ -368,6 +368,19 @@ static void __init bootmem_init(void) | |||
| 368 | end = PFN_DOWN(boot_mem_map.map[i].addr | 368 | end = PFN_DOWN(boot_mem_map.map[i].addr |
| 369 | + boot_mem_map.map[i].size); | 369 | + boot_mem_map.map[i].size); |
| 370 | 370 | ||
| 371 | #ifndef CONFIG_HIGHMEM | ||
| 372 | /* | ||
| 373 | * Skip highmem here so we get an accurate max_low_pfn if low | ||
| 374 | * memory stops short of high memory. | ||
| 375 | * If the region overlaps HIGHMEM_START, end is clipped so | ||
| 376 | * max_pfn excludes the highmem portion. | ||
| 377 | */ | ||
| 378 | if (start >= PFN_DOWN(HIGHMEM_START)) | ||
| 379 | continue; | ||
| 380 | if (end > PFN_DOWN(HIGHMEM_START)) | ||
| 381 | end = PFN_DOWN(HIGHMEM_START); | ||
| 382 | #endif | ||
| 383 | |||
| 371 | if (end > max_low_pfn) | 384 | if (end > max_low_pfn) |
| 372 | max_low_pfn = end; | 385 | max_low_pfn = end; |
| 373 | if (start < min_low_pfn) | 386 | if (start < min_low_pfn) |
diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c index 1f5fdee1dfc3..3905003dfe2b 100644 --- a/arch/mips/kernel/traps.c +++ b/arch/mips/kernel/traps.c | |||
| @@ -156,7 +156,7 @@ static void show_backtrace(struct task_struct *task, const struct pt_regs *regs) | |||
| 156 | print_ip_sym(pc); | 156 | print_ip_sym(pc); |
| 157 | pc = unwind_stack(task, &sp, pc, &ra); | 157 | pc = unwind_stack(task, &sp, pc, &ra); |
| 158 | } while (pc); | 158 | } while (pc); |
| 159 | printk("\n"); | 159 | pr_cont("\n"); |
| 160 | } | 160 | } |
| 161 | 161 | ||
| 162 | /* | 162 | /* |
| @@ -174,22 +174,24 @@ static void show_stacktrace(struct task_struct *task, | |||
| 174 | printk("Stack :"); | 174 | printk("Stack :"); |
| 175 | i = 0; | 175 | i = 0; |
| 176 | while ((unsigned long) sp & (PAGE_SIZE - 1)) { | 176 | while ((unsigned long) sp & (PAGE_SIZE - 1)) { |
| 177 | if (i && ((i % (64 / field)) == 0)) | 177 | if (i && ((i % (64 / field)) == 0)) { |
| 178 | printk("\n "); | 178 | pr_cont("\n"); |
| 179 | printk(" "); | ||
| 180 | } | ||
| 179 | if (i > 39) { | 181 | if (i > 39) { |
| 180 | printk(" ..."); | 182 | pr_cont(" ..."); |
| 181 | break; | 183 | break; |
| 182 | } | 184 | } |
| 183 | 185 | ||
| 184 | if (__get_user(stackdata, sp++)) { | 186 | if (__get_user(stackdata, sp++)) { |
| 185 | printk(" (Bad stack address)"); | 187 | pr_cont(" (Bad stack address)"); |
| 186 | break; | 188 | break; |
| 187 | } | 189 | } |
| 188 | 190 | ||
| 189 | printk(" %0*lx", field, stackdata); | 191 | pr_cont(" %0*lx", field, stackdata); |
| 190 | i++; | 192 | i++; |
| 191 | } | 193 | } |
| 192 | printk("\n"); | 194 | pr_cont("\n"); |
| 193 | show_backtrace(task, regs); | 195 | show_backtrace(task, regs); |
| 194 | } | 196 | } |
| 195 | 197 | ||
| @@ -229,18 +231,19 @@ static void show_code(unsigned int __user *pc) | |||
| 229 | long i; | 231 | long i; |
| 230 | unsigned short __user *pc16 = NULL; | 232 | unsigned short __user *pc16 = NULL; |
| 231 | 233 | ||
| 232 | printk("\nCode:"); | 234 | printk("Code:"); |
| 233 | 235 | ||
| 234 | if ((unsigned long)pc & 1) | 236 | if ((unsigned long)pc & 1) |
| 235 | pc16 = (unsigned short __user *)((unsigned long)pc & ~1); | 237 | pc16 = (unsigned short __user *)((unsigned long)pc & ~1); |
| 236 | for(i = -3 ; i < 6 ; i++) { | 238 | for(i = -3 ; i < 6 ; i++) { |
| 237 | unsigned int insn; | 239 | unsigned int insn; |
| 238 | if (pc16 ? __get_user(insn, pc16 + i) : __get_user(insn, pc + i)) { | 240 | if (pc16 ? __get_user(insn, pc16 + i) : __get_user(insn, pc + i)) { |
| 239 | printk(" (Bad address in epc)\n"); | 241 | pr_cont(" (Bad address in epc)\n"); |
| 240 | break; | 242 | break; |
| 241 | } | 243 | } |
| 242 | printk("%c%0*x%c", (i?' ':'<'), pc16 ? 4 : 8, insn, (i?' ':'>')); | 244 | pr_cont("%c%0*x%c", (i?' ':'<'), pc16 ? 4 : 8, insn, (i?' ':'>')); |
| 243 | } | 245 | } |
| 246 | pr_cont("\n"); | ||
| 244 | } | 247 | } |
| 245 | 248 | ||
| 246 | static void __show_regs(const struct pt_regs *regs) | 249 | static void __show_regs(const struct pt_regs *regs) |
| @@ -259,15 +262,15 @@ static void __show_regs(const struct pt_regs *regs) | |||
| 259 | if ((i % 4) == 0) | 262 | if ((i % 4) == 0) |
| 260 | printk("$%2d :", i); | 263 | printk("$%2d :", i); |
| 261 | if (i == 0) | 264 | if (i == 0) |
| 262 | printk(" %0*lx", field, 0UL); | 265 | pr_cont(" %0*lx", field, 0UL); |
| 263 | else if (i == 26 || i == 27) | 266 | else if (i == 26 || i == 27) |
| 264 | printk(" %*s", field, ""); | 267 | pr_cont(" %*s", field, ""); |
| 265 | else | 268 | else |
| 266 | printk(" %0*lx", field, regs->regs[i]); | 269 | pr_cont(" %0*lx", field, regs->regs[i]); |
| 267 | 270 | ||
| 268 | i++; | 271 | i++; |
| 269 | if ((i % 4) == 0) | 272 | if ((i % 4) == 0) |
| 270 | printk("\n"); | 273 | pr_cont("\n"); |
| 271 | } | 274 | } |
| 272 | 275 | ||
| 273 | #ifdef CONFIG_CPU_HAS_SMARTMIPS | 276 | #ifdef CONFIG_CPU_HAS_SMARTMIPS |
| @@ -288,46 +291,46 @@ static void __show_regs(const struct pt_regs *regs) | |||
| 288 | 291 | ||
| 289 | if (cpu_has_3kex) { | 292 | if (cpu_has_3kex) { |
| 290 | if (regs->cp0_status & ST0_KUO) | 293 | if (regs->cp0_status & ST0_KUO) |
| 291 | printk("KUo "); | 294 | pr_cont("KUo "); |
| 292 | if (regs->cp0_status & ST0_IEO) | 295 | if (regs->cp0_status & ST0_IEO) |
| 293 | printk("IEo "); | 296 | pr_cont("IEo "); |
| 294 | if (regs->cp0_status & ST0_KUP) | 297 | if (regs->cp0_status & ST0_KUP) |
| 295 | printk("KUp "); | 298 | pr_cont("KUp "); |
| 296 | if (regs->cp0_status & ST0_IEP) | 299 | if (regs->cp0_status & ST0_IEP) |
| 297 | printk("IEp "); | 300 | pr_cont("IEp "); |
| 298 | if (regs->cp0_status & ST0_KUC) | 301 | if (regs->cp0_status & ST0_KUC) |
| 299 | printk("KUc "); | 302 | pr_cont("KUc "); |
| 300 | if (regs->cp0_status & ST0_IEC) | 303 | if (regs->cp0_status & ST0_IEC) |
| 301 | printk("IEc "); | 304 | pr_cont("IEc "); |
| 302 | } else if (cpu_has_4kex) { | 305 | } else if (cpu_has_4kex) { |
| 303 | if (regs->cp0_status & ST0_KX) | 306 | if (regs->cp0_status & ST0_KX) |
| 304 | printk("KX "); | 307 | pr_cont("KX "); |
| 305 | if (regs->cp0_status & ST0_SX) | 308 | if (regs->cp0_status & ST0_SX) |
| 306 | printk("SX "); | 309 | pr_cont("SX "); |
| 307 | if (regs->cp0_status & ST0_UX) | 310 | if (regs->cp0_status & ST0_UX) |
| 308 | printk("UX "); | 311 | pr_cont("UX "); |
| 309 | switch (regs->cp0_status & ST0_KSU) { | 312 | switch (regs->cp0_status & ST0_KSU) { |
| 310 | case KSU_USER: | 313 | case KSU_USER: |
| 311 | printk("USER "); | 314 | pr_cont("USER "); |
| 312 | break; | 315 | break; |
| 313 | case KSU_SUPERVISOR: | 316 | case KSU_SUPERVISOR: |
| 314 | printk("SUPERVISOR "); | 317 | pr_cont("SUPERVISOR "); |
| 315 | break; | 318 | break; |
| 316 | case KSU_KERNEL: | 319 | case KSU_KERNEL: |
| 317 | printk("KERNEL "); | 320 | pr_cont("KERNEL "); |
| 318 | break; | 321 | break; |
| 319 | default: | 322 | default: |
| 320 | printk("BAD_MODE "); | 323 | pr_cont("BAD_MODE "); |
| 321 | break; | 324 | break; |
| 322 | } | 325 | } |
| 323 | if (regs->cp0_status & ST0_ERL) | 326 | if (regs->cp0_status & ST0_ERL) |
| 324 | printk("ERL "); | 327 | pr_cont("ERL "); |
| 325 | if (regs->cp0_status & ST0_EXL) | 328 | if (regs->cp0_status & ST0_EXL) |
| 326 | printk("EXL "); | 329 | pr_cont("EXL "); |
| 327 | if (regs->cp0_status & ST0_IE) | 330 | if (regs->cp0_status & ST0_IE) |
| 328 | printk("IE "); | 331 | pr_cont("IE "); |
| 329 | } | 332 | } |
| 330 | printk("\n"); | 333 | pr_cont("\n"); |
| 331 | 334 | ||
| 332 | exccode = (cause & CAUSEF_EXCCODE) >> CAUSEB_EXCCODE; | 335 | exccode = (cause & CAUSEF_EXCCODE) >> CAUSEB_EXCCODE; |
| 333 | printk("Cause : %08x (ExcCode %02x)\n", cause, exccode); | 336 | printk("Cause : %08x (ExcCode %02x)\n", cause, exccode); |
| @@ -705,6 +708,32 @@ asmlinkage void do_ov(struct pt_regs *regs) | |||
| 705 | exception_exit(prev_state); | 708 | exception_exit(prev_state); |
| 706 | } | 709 | } |
| 707 | 710 | ||
| 711 | /* | ||
| 712 | * Send SIGFPE according to FCSR Cause bits, which must have already | ||
| 713 | * been masked against Enable bits. This is impotant as Inexact can | ||
| 714 | * happen together with Overflow or Underflow, and `ptrace' can set | ||
| 715 | * any bits. | ||
| 716 | */ | ||
| 717 | void force_fcr31_sig(unsigned long fcr31, void __user *fault_addr, | ||
| 718 | struct task_struct *tsk) | ||
| 719 | { | ||
| 720 | struct siginfo si = { .si_addr = fault_addr, .si_signo = SIGFPE }; | ||
| 721 | |||
| 722 | if (fcr31 & FPU_CSR_INV_X) | ||
| 723 | si.si_code = FPE_FLTINV; | ||
| 724 | else if (fcr31 & FPU_CSR_DIV_X) | ||
| 725 | si.si_code = FPE_FLTDIV; | ||
| 726 | else if (fcr31 & FPU_CSR_OVF_X) | ||
| 727 | si.si_code = FPE_FLTOVF; | ||
| 728 | else if (fcr31 & FPU_CSR_UDF_X) | ||
| 729 | si.si_code = FPE_FLTUND; | ||
| 730 | else if (fcr31 & FPU_CSR_INE_X) | ||
| 731 | si.si_code = FPE_FLTRES; | ||
| 732 | else | ||
| 733 | si.si_code = __SI_FAULT; | ||
| 734 | force_sig_info(SIGFPE, &si, tsk); | ||
| 735 | } | ||
| 736 | |||
| 708 | int process_fpemu_return(int sig, void __user *fault_addr, unsigned long fcr31) | 737 | int process_fpemu_return(int sig, void __user *fault_addr, unsigned long fcr31) |
| 709 | { | 738 | { |
| 710 | struct siginfo si = { 0 }; | 739 | struct siginfo si = { 0 }; |
| @@ -715,27 +744,7 @@ int process_fpemu_return(int sig, void __user *fault_addr, unsigned long fcr31) | |||
| 715 | return 0; | 744 | return 0; |
| 716 | 745 | ||
| 717 | case SIGFPE: | 746 | case SIGFPE: |
| 718 | si.si_addr = fault_addr; | 747 | force_fcr31_sig(fcr31, fault_addr, current); |
| 719 | si.si_signo = sig; | ||
| 720 | /* | ||
| 721 | * Inexact can happen together with Overflow or Underflow. | ||
| 722 | * Respect the mask to deliver the correct exception. | ||
| 723 | */ | ||
| 724 | fcr31 &= (fcr31 & FPU_CSR_ALL_E) << | ||
| 725 | (ffs(FPU_CSR_ALL_X) - ffs(FPU_CSR_ALL_E)); | ||
| 726 | if (fcr31 & FPU_CSR_INV_X) | ||
| 727 | si.si_code = FPE_FLTINV; | ||
| 728 | else if (fcr31 & FPU_CSR_DIV_X) | ||
| 729 | si.si_code = FPE_FLTDIV; | ||
| 730 | else if (fcr31 & FPU_CSR_OVF_X) | ||
| 731 | si.si_code = FPE_FLTOVF; | ||
| 732 | else if (fcr31 & FPU_CSR_UDF_X) | ||
| 733 | si.si_code = FPE_FLTUND; | ||
| 734 | else if (fcr31 & FPU_CSR_INE_X) | ||
| 735 | si.si_code = FPE_FLTRES; | ||
| 736 | else | ||
| 737 | si.si_code = __SI_FAULT; | ||
| 738 | force_sig_info(sig, &si, current); | ||
| 739 | return 1; | 748 | return 1; |
| 740 | 749 | ||
| 741 | case SIGBUS: | 750 | case SIGBUS: |
| @@ -799,13 +808,13 @@ static int simulate_fp(struct pt_regs *regs, unsigned int opcode, | |||
| 799 | /* Run the emulator */ | 808 | /* Run the emulator */ |
| 800 | sig = fpu_emulator_cop1Handler(regs, ¤t->thread.fpu, 1, | 809 | sig = fpu_emulator_cop1Handler(regs, ¤t->thread.fpu, 1, |
| 801 | &fault_addr); | 810 | &fault_addr); |
| 802 | fcr31 = current->thread.fpu.fcr31; | ||
| 803 | 811 | ||
| 804 | /* | 812 | /* |
| 805 | * We can't allow the emulated instruction to leave any of | 813 | * We can't allow the emulated instruction to leave any |
| 806 | * the cause bits set in $fcr31. | 814 | * enabled Cause bits set in $fcr31. |
| 807 | */ | 815 | */ |
| 808 | current->thread.fpu.fcr31 &= ~FPU_CSR_ALL_X; | 816 | fcr31 = mask_fcr31_x(current->thread.fpu.fcr31); |
| 817 | current->thread.fpu.fcr31 &= ~fcr31; | ||
| 809 | 818 | ||
| 810 | /* Restore the hardware register state */ | 819 | /* Restore the hardware register state */ |
| 811 | own_fpu(1); | 820 | own_fpu(1); |
| @@ -831,7 +840,7 @@ asmlinkage void do_fpe(struct pt_regs *regs, unsigned long fcr31) | |||
| 831 | goto out; | 840 | goto out; |
| 832 | 841 | ||
| 833 | /* Clear FCSR.Cause before enabling interrupts */ | 842 | /* Clear FCSR.Cause before enabling interrupts */ |
| 834 | write_32bit_cp1_register(CP1_STATUS, fcr31 & ~FPU_CSR_ALL_X); | 843 | write_32bit_cp1_register(CP1_STATUS, fcr31 & ~mask_fcr31_x(fcr31)); |
| 835 | local_irq_enable(); | 844 | local_irq_enable(); |
| 836 | 845 | ||
| 837 | die_if_kernel("FP exception in kernel code", regs); | 846 | die_if_kernel("FP exception in kernel code", regs); |
| @@ -853,13 +862,13 @@ asmlinkage void do_fpe(struct pt_regs *regs, unsigned long fcr31) | |||
| 853 | /* Run the emulator */ | 862 | /* Run the emulator */ |
| 854 | sig = fpu_emulator_cop1Handler(regs, ¤t->thread.fpu, 1, | 863 | sig = fpu_emulator_cop1Handler(regs, ¤t->thread.fpu, 1, |
| 855 | &fault_addr); | 864 | &fault_addr); |
| 856 | fcr31 = current->thread.fpu.fcr31; | ||
| 857 | 865 | ||
| 858 | /* | 866 | /* |
| 859 | * We can't allow the emulated instruction to leave any of | 867 | * We can't allow the emulated instruction to leave any |
| 860 | * the cause bits set in $fcr31. | 868 | * enabled Cause bits set in $fcr31. |
| 861 | */ | 869 | */ |
| 862 | current->thread.fpu.fcr31 &= ~FPU_CSR_ALL_X; | 870 | fcr31 = mask_fcr31_x(current->thread.fpu.fcr31); |
| 871 | current->thread.fpu.fcr31 &= ~fcr31; | ||
| 863 | 872 | ||
| 864 | /* Restore the hardware register state */ | 873 | /* Restore the hardware register state */ |
| 865 | own_fpu(1); /* Using the FPU again. */ | 874 | own_fpu(1); /* Using the FPU again. */ |
| @@ -1424,13 +1433,13 @@ asmlinkage void do_cpu(struct pt_regs *regs) | |||
| 1424 | 1433 | ||
| 1425 | sig = fpu_emulator_cop1Handler(regs, ¤t->thread.fpu, 0, | 1434 | sig = fpu_emulator_cop1Handler(regs, ¤t->thread.fpu, 0, |
| 1426 | &fault_addr); | 1435 | &fault_addr); |
| 1427 | fcr31 = current->thread.fpu.fcr31; | ||
| 1428 | 1436 | ||
| 1429 | /* | 1437 | /* |
| 1430 | * We can't allow the emulated instruction to leave | 1438 | * We can't allow the emulated instruction to leave |
| 1431 | * any of the cause bits set in $fcr31. | 1439 | * any enabled Cause bits set in $fcr31. |
| 1432 | */ | 1440 | */ |
| 1433 | current->thread.fpu.fcr31 &= ~FPU_CSR_ALL_X; | 1441 | fcr31 = mask_fcr31_x(current->thread.fpu.fcr31); |
| 1442 | current->thread.fpu.fcr31 &= ~fcr31; | ||
| 1434 | 1443 | ||
| 1435 | /* Send a signal if required. */ | 1444 | /* Send a signal if required. */ |
| 1436 | if (!process_fpemu_return(sig, fault_addr, fcr31) && !err) | 1445 | if (!process_fpemu_return(sig, fault_addr, fcr31) && !err) |
diff --git a/arch/mips/lib/dump_tlb.c b/arch/mips/lib/dump_tlb.c index 0f80b936e75e..6eb50a7137db 100644 --- a/arch/mips/lib/dump_tlb.c +++ b/arch/mips/lib/dump_tlb.c | |||
| @@ -135,42 +135,42 @@ static void dump_tlb(int first, int last) | |||
| 135 | c0 = (entrylo0 & ENTRYLO_C) >> ENTRYLO_C_SHIFT; | 135 | c0 = (entrylo0 & ENTRYLO_C) >> ENTRYLO_C_SHIFT; |
| 136 | c1 = (entrylo1 & ENTRYLO_C) >> ENTRYLO_C_SHIFT; | 136 | c1 = (entrylo1 & ENTRYLO_C) >> ENTRYLO_C_SHIFT; |
| 137 | 137 | ||
| 138 | printk("va=%0*lx asid=%0*lx", | 138 | pr_cont("va=%0*lx asid=%0*lx", |
| 139 | vwidth, (entryhi & ~0x1fffUL), | 139 | vwidth, (entryhi & ~0x1fffUL), |
| 140 | asidwidth, entryhi & asidmask); | 140 | asidwidth, entryhi & asidmask); |
| 141 | if (cpu_has_guestid) | 141 | if (cpu_has_guestid) |
| 142 | printk(" gid=%02lx", | 142 | pr_cont(" gid=%02lx", |
| 143 | (guestctl1 & MIPS_GCTL1_RID) | 143 | (guestctl1 & MIPS_GCTL1_RID) |
| 144 | >> MIPS_GCTL1_RID_SHIFT); | 144 | >> MIPS_GCTL1_RID_SHIFT); |
| 145 | /* RI/XI are in awkward places, so mask them off separately */ | 145 | /* RI/XI are in awkward places, so mask them off separately */ |
| 146 | pa = entrylo0 & ~(MIPS_ENTRYLO_RI | MIPS_ENTRYLO_XI); | 146 | pa = entrylo0 & ~(MIPS_ENTRYLO_RI | MIPS_ENTRYLO_XI); |
| 147 | if (xpa) | 147 | if (xpa) |
| 148 | pa |= (unsigned long long)readx_c0_entrylo0() << 30; | 148 | pa |= (unsigned long long)readx_c0_entrylo0() << 30; |
| 149 | pa = (pa << 6) & PAGE_MASK; | 149 | pa = (pa << 6) & PAGE_MASK; |
| 150 | printk("\n\t["); | 150 | pr_cont("\n\t["); |
| 151 | if (cpu_has_rixi) | 151 | if (cpu_has_rixi) |
| 152 | printk("ri=%d xi=%d ", | 152 | pr_cont("ri=%d xi=%d ", |
| 153 | (entrylo0 & MIPS_ENTRYLO_RI) ? 1 : 0, | 153 | (entrylo0 & MIPS_ENTRYLO_RI) ? 1 : 0, |
| 154 | (entrylo0 & MIPS_ENTRYLO_XI) ? 1 : 0); | 154 | (entrylo0 & MIPS_ENTRYLO_XI) ? 1 : 0); |
| 155 | printk("pa=%0*llx c=%d d=%d v=%d g=%d] [", | 155 | pr_cont("pa=%0*llx c=%d d=%d v=%d g=%d] [", |
| 156 | pwidth, pa, c0, | 156 | pwidth, pa, c0, |
| 157 | (entrylo0 & ENTRYLO_D) ? 1 : 0, | 157 | (entrylo0 & ENTRYLO_D) ? 1 : 0, |
| 158 | (entrylo0 & ENTRYLO_V) ? 1 : 0, | 158 | (entrylo0 & ENTRYLO_V) ? 1 : 0, |
| 159 | (entrylo0 & ENTRYLO_G) ? 1 : 0); | 159 | (entrylo0 & ENTRYLO_G) ? 1 : 0); |
| 160 | /* RI/XI are in awkward places, so mask them off separately */ | 160 | /* RI/XI are in awkward places, so mask them off separately */ |
| 161 | pa = entrylo1 & ~(MIPS_ENTRYLO_RI | MIPS_ENTRYLO_XI); | 161 | pa = entrylo1 & ~(MIPS_ENTRYLO_RI | MIPS_ENTRYLO_XI); |
| 162 | if (xpa) | 162 | if (xpa) |
| 163 | pa |= (unsigned long long)readx_c0_entrylo1() << 30; | 163 | pa |= (unsigned long long)readx_c0_entrylo1() << 30; |
| 164 | pa = (pa << 6) & PAGE_MASK; | 164 | pa = (pa << 6) & PAGE_MASK; |
| 165 | if (cpu_has_rixi) | 165 | if (cpu_has_rixi) |
| 166 | printk("ri=%d xi=%d ", | 166 | pr_cont("ri=%d xi=%d ", |
| 167 | (entrylo1 & MIPS_ENTRYLO_RI) ? 1 : 0, | 167 | (entrylo1 & MIPS_ENTRYLO_RI) ? 1 : 0, |
| 168 | (entrylo1 & MIPS_ENTRYLO_XI) ? 1 : 0); | 168 | (entrylo1 & MIPS_ENTRYLO_XI) ? 1 : 0); |
| 169 | printk("pa=%0*llx c=%d d=%d v=%d g=%d]\n", | 169 | pr_cont("pa=%0*llx c=%d d=%d v=%d g=%d]\n", |
| 170 | pwidth, pa, c1, | 170 | pwidth, pa, c1, |
| 171 | (entrylo1 & ENTRYLO_D) ? 1 : 0, | 171 | (entrylo1 & ENTRYLO_D) ? 1 : 0, |
| 172 | (entrylo1 & ENTRYLO_V) ? 1 : 0, | 172 | (entrylo1 & ENTRYLO_V) ? 1 : 0, |
| 173 | (entrylo1 & ENTRYLO_G) ? 1 : 0); | 173 | (entrylo1 & ENTRYLO_G) ? 1 : 0); |
| 174 | } | 174 | } |
| 175 | printk("\n"); | 175 | printk("\n"); |
| 176 | 176 | ||
diff --git a/arch/mips/lib/r3k_dump_tlb.c b/arch/mips/lib/r3k_dump_tlb.c index 744f4a7bc49d..85b4086e553e 100644 --- a/arch/mips/lib/r3k_dump_tlb.c +++ b/arch/mips/lib/r3k_dump_tlb.c | |||
| @@ -53,15 +53,15 @@ static void dump_tlb(int first, int last) | |||
| 53 | */ | 53 | */ |
| 54 | printk("Index: %2d ", i); | 54 | printk("Index: %2d ", i); |
| 55 | 55 | ||
| 56 | printk("va=%08lx asid=%08lx" | 56 | pr_cont("va=%08lx asid=%08lx" |
| 57 | " [pa=%06lx n=%d d=%d v=%d g=%d]", | 57 | " [pa=%06lx n=%d d=%d v=%d g=%d]", |
| 58 | entryhi & PAGE_MASK, | 58 | entryhi & PAGE_MASK, |
| 59 | entryhi & asid_mask, | 59 | entryhi & asid_mask, |
| 60 | entrylo0 & PAGE_MASK, | 60 | entrylo0 & PAGE_MASK, |
| 61 | (entrylo0 & R3K_ENTRYLO_N) ? 1 : 0, | 61 | (entrylo0 & R3K_ENTRYLO_N) ? 1 : 0, |
| 62 | (entrylo0 & R3K_ENTRYLO_D) ? 1 : 0, | 62 | (entrylo0 & R3K_ENTRYLO_D) ? 1 : 0, |
| 63 | (entrylo0 & R3K_ENTRYLO_V) ? 1 : 0, | 63 | (entrylo0 & R3K_ENTRYLO_V) ? 1 : 0, |
| 64 | (entrylo0 & R3K_ENTRYLO_G) ? 1 : 0); | 64 | (entrylo0 & R3K_ENTRYLO_G) ? 1 : 0); |
| 65 | } | 65 | } |
| 66 | } | 66 | } |
| 67 | printk("\n"); | 67 | printk("\n"); |
