diff options
author | David S. Miller <davem@davemloft.net> | 2012-05-25 03:31:56 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2012-05-25 03:31:56 -0400 |
commit | 456d3d42460c1fc20ba0d27442443fcd63aaac35 (patch) | |
tree | 2bdd7021420f845f3c775e91ccc91aa791ef6c45 /arch/sparc/kernel/traps_64.c | |
parent | 07acfc2a9349a8ce45b236c2624dad452001966b (diff) |
sparc64: Fix several bugs in quad floating point emulation.
UltraSPARC-T2 and later do not use the fp_exception_other trap and do
not set the floating point trap type field in the %fsr at all when you
try to execute an unimplemented FPU operation.
Instead, it uses the illegal_instruction trap and it leaves the
floating point trap type field clear.
So we should not validate the %fsr trap type field when do_mathemu()
is invoked from the illegal instruction handler.
Also, the floating point trap type field is 3 bits, not 4 bits.
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'arch/sparc/kernel/traps_64.c')
-rw-r--r-- | arch/sparc/kernel/traps_64.c | 12 |
1 files changed, 7 insertions, 5 deletions
diff --git a/arch/sparc/kernel/traps_64.c b/arch/sparc/kernel/traps_64.c index c72fdf55e1c1..3b05e6697710 100644 --- a/arch/sparc/kernel/traps_64.c +++ b/arch/sparc/kernel/traps_64.c | |||
@@ -2054,7 +2054,7 @@ void do_fpieee(struct pt_regs *regs) | |||
2054 | do_fpe_common(regs); | 2054 | do_fpe_common(regs); |
2055 | } | 2055 | } |
2056 | 2056 | ||
2057 | extern int do_mathemu(struct pt_regs *, struct fpustate *); | 2057 | extern int do_mathemu(struct pt_regs *, struct fpustate *, bool); |
2058 | 2058 | ||
2059 | void do_fpother(struct pt_regs *regs) | 2059 | void do_fpother(struct pt_regs *regs) |
2060 | { | 2060 | { |
@@ -2068,7 +2068,7 @@ void do_fpother(struct pt_regs *regs) | |||
2068 | switch ((current_thread_info()->xfsr[0] & 0x1c000)) { | 2068 | switch ((current_thread_info()->xfsr[0] & 0x1c000)) { |
2069 | case (2 << 14): /* unfinished_FPop */ | 2069 | case (2 << 14): /* unfinished_FPop */ |
2070 | case (3 << 14): /* unimplemented_FPop */ | 2070 | case (3 << 14): /* unimplemented_FPop */ |
2071 | ret = do_mathemu(regs, f); | 2071 | ret = do_mathemu(regs, f, false); |
2072 | break; | 2072 | break; |
2073 | } | 2073 | } |
2074 | if (ret) | 2074 | if (ret) |
@@ -2308,10 +2308,12 @@ void do_illegal_instruction(struct pt_regs *regs) | |||
2308 | } else { | 2308 | } else { |
2309 | struct fpustate *f = FPUSTATE; | 2309 | struct fpustate *f = FPUSTATE; |
2310 | 2310 | ||
2311 | /* XXX maybe verify XFSR bits like | 2311 | /* On UltraSPARC T2 and later, FPU insns which |
2312 | * XXX do_fpother() does? | 2312 | * are not implemented in HW signal an illegal |
2313 | * instruction trap and do not set the FP Trap | ||
2314 | * Trap in the %fsr to unimplemented_FPop. | ||
2313 | */ | 2315 | */ |
2314 | if (do_mathemu(regs, f)) | 2316 | if (do_mathemu(regs, f, true)) |
2315 | return; | 2317 | return; |
2316 | } | 2318 | } |
2317 | } | 2319 | } |