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"); |