aboutsummaryrefslogtreecommitdiffstats
path: root/arch/ia64/kernel/unaligned.c
diff options
context:
space:
mode:
authorLuck, Tony <tony.luck@intel.com>2008-01-14 12:59:24 -0500
committerTony Luck <tony.luck@intel.com>2008-01-15 17:26:55 -0500
commit1a499150e4ec1299232e24389f648d059ce5617a (patch)
treeed83bc200faa49a67a18f6ca331f7e9275e43b13 /arch/ia64/kernel/unaligned.c
parent0938e7586440ac97cedc0f5528a8684ebfa4ce43 (diff)
[IA64] Fix unaligned handler for floating point instructions with base update
The compiler team did the hard work for this distilling a problem in large fortran application which showed up when applied to a 290MB input data set down to this instruction: ldfd f34=[r17],-8 Which they noticed incremented r17 by 0x10 rather than decrementing it by 8 when the value in r17 caused an unaligned data fault. I tracked it down to some bad instruction decoding in unaligned.c. The code assumes that the 'x' bit can determine whether the instruction is an "ldf" or "ldfp" ... which it is for opcode=6 (see table 4-29 on page 3:302 of the SDM). But for opcode=7 the 'x' bit is irrelevent, all variants are "ldf" instructions (see table 4-36 on page 3:306). Note also that interpreting the instruction as "ldfp" means that the "paired" floating point register (f35 in the example here) will also be corrupted. Signed-off-by: Tony Luck <tony.luck@intel.com>
Diffstat (limited to 'arch/ia64/kernel/unaligned.c')
-rw-r--r--arch/ia64/kernel/unaligned.c11
1 files changed, 7 insertions, 4 deletions
diff --git a/arch/ia64/kernel/unaligned.c b/arch/ia64/kernel/unaligned.c
index 2173de9fe917..f6a1aeb742b3 100644
--- a/arch/ia64/kernel/unaligned.c
+++ b/arch/ia64/kernel/unaligned.c
@@ -1488,16 +1488,19 @@ ia64_handle_unaligned (unsigned long ifa, struct pt_regs *regs)
1488 case LDFA_OP: 1488 case LDFA_OP:
1489 case LDFCCLR_OP: 1489 case LDFCCLR_OP:
1490 case LDFCNC_OP: 1490 case LDFCNC_OP:
1491 case LDF_IMM_OP:
1492 case LDFA_IMM_OP:
1493 case LDFCCLR_IMM_OP:
1494 case LDFCNC_IMM_OP:
1495 if (u.insn.x) 1491 if (u.insn.x)
1496 ret = emulate_load_floatpair(ifa, u.insn, regs); 1492 ret = emulate_load_floatpair(ifa, u.insn, regs);
1497 else 1493 else
1498 ret = emulate_load_float(ifa, u.insn, regs); 1494 ret = emulate_load_float(ifa, u.insn, regs);
1499 break; 1495 break;
1500 1496
1497 case LDF_IMM_OP:
1498 case LDFA_IMM_OP:
1499 case LDFCCLR_IMM_OP:
1500 case LDFCNC_IMM_OP:
1501 ret = emulate_load_float(ifa, u.insn, regs);
1502 break;
1503
1501 case STF_OP: 1504 case STF_OP:
1502 case STF_IMM_OP: 1505 case STF_IMM_OP:
1503 ret = emulate_store_float(ifa, u.insn, regs); 1506 ret = emulate_store_float(ifa, u.insn, regs);