Commit 0f227137 authored by Kenneth W. Chen's avatar Kenneth W. Chen Committed by David Mosberger

[PATCH] ia64: fix ld.a emulation

This patch fixes a corner-case of ld.a emulation.  ld.a should be
emulated such that it always loads a misaligned value and clears the
corresponding ALAT entry.  The old emulation was correct for the case
where ld.a was followed by ld.c/chk.a (since ALAT entry was cleared),
but wrong for the case where it _wasn't_ followed by ld.c/chk.a.  In
that case, the misaligned value wasn't read from memory, as it should
have been.
parent 33d55a8a
...@@ -740,6 +740,7 @@ static int ...@@ -740,6 +740,7 @@ static int
emulate_load_int (unsigned long ifa, load_store_t ld, struct pt_regs *regs) emulate_load_int (unsigned long ifa, load_store_t ld, struct pt_regs *regs)
{ {
unsigned int len = 1 << ld.x6_sz; unsigned int len = 1 << ld.x6_sz;
unsigned long val = 0;
/* /*
* r0, as target, doesn't need to be checked because Illegal Instruction * r0, as target, doesn't need to be checked because Illegal Instruction
...@@ -750,21 +751,18 @@ emulate_load_int (unsigned long ifa, load_store_t ld, struct pt_regs *regs) ...@@ -750,21 +751,18 @@ emulate_load_int (unsigned long ifa, load_store_t ld, struct pt_regs *regs)
*/ */
/* /*
* ldX.a we don't try to emulate anything but we must invalidate the ALAT entry. * ldX.a we will emulate load and also invalidate the ALAT entry.
* See comment below for explanation on how we handle ldX.a * See comment below for explanation on how we handle ldX.a
*/ */
if (ld.x6_op != 0x2) {
unsigned long val = 0;
if (len != 2 && len != 4 && len != 8) { if (len != 2 && len != 4 && len != 8) {
DPRINT("unknown size: x6=%d\n", ld.x6_sz); DPRINT("unknown size: x6=%d\n", ld.x6_sz);
return -1; return -1;
}
/* this assumes little-endian byte-order: */
if (copy_from_user(&val, (void *) ifa, len))
return -1;
setreg(ld.r1, val, 0, regs);
} }
/* this assumes little-endian byte-order: */
if (copy_from_user(&val, (void *) ifa, len))
return -1;
setreg(ld.r1, val, 0, regs);
/* /*
* check for updates on any kind of loads * check for updates on any kind of loads
...@@ -817,7 +815,7 @@ emulate_load_int (unsigned long ifa, load_store_t ld, struct pt_regs *regs) ...@@ -817,7 +815,7 @@ emulate_load_int (unsigned long ifa, load_store_t ld, struct pt_regs *regs)
* store & shift to temporary; * store & shift to temporary;
* r1=temporary * r1=temporary
* *
* So int this case, you would get the right value is r1 but the wrong info in * So in this case, you would get the right value is r1 but the wrong info in
* the ALAT. Notice that you could do it in reverse to finish with address 3 * the ALAT. Notice that you could do it in reverse to finish with address 3
* but you would still get the size wrong. To get the size right, one needs to * but you would still get the size wrong. To get the size right, one needs to
* execute exactly the same kind of load. You could do it from a aligned * execute exactly the same kind of load. You could do it from a aligned
...@@ -826,9 +824,12 @@ emulate_load_int (unsigned long ifa, load_store_t ld, struct pt_regs *regs) ...@@ -826,9 +824,12 @@ emulate_load_int (unsigned long ifa, load_store_t ld, struct pt_regs *regs)
* So no matter what, it is not possible to emulate an advanced load * So no matter what, it is not possible to emulate an advanced load
* correctly. But is that really critical ? * correctly. But is that really critical ?
* *
* We will always convert ld.a into a normal load with ALAT invalidated. This
* will enable compiler to do optimization where certain code path after ld.a
* is not required to have ld.c/chk.a, e.g., code path with no intervening stores.
* *
* Now one has to look at how ld.a is used, one must either do a ld.c.* or * If there is a store after the advanced load, one must either do a ld.c.* or
* chck.a.* to reuse the value stored in the ALAT. Both can "fail" (meaning no * chk.a.* to reuse the value stored in the ALAT. Both can "fail" (meaning no
* entry found in ALAT), and that's perfectly ok because: * entry found in ALAT), and that's perfectly ok because:
* *
* - ld.c.*, if the entry is not present a normal load is executed * - ld.c.*, if the entry is not present a normal load is executed
...@@ -836,19 +837,8 @@ emulate_load_int (unsigned long ifa, load_store_t ld, struct pt_regs *regs) ...@@ -836,19 +837,8 @@ emulate_load_int (unsigned long ifa, load_store_t ld, struct pt_regs *regs)
* *
* In either case, the load can be potentially retried in another form. * In either case, the load can be potentially retried in another form.
* *
* So it's okay NOT to do any actual load on an unaligned ld.a. However the ALAT * ALAT must be invalidated for the register (so that chk.a or ld.c don't pick
* must be invalidated for the register (so that's chck.a.*,ld.c.* don't pick up * up a stale entry later). The register base update MUST also be performed.
* a stale entry later) The register base update MUST also be performed.
*
* Now what is the content of the register and its NaT bit in the case we don't
* do the load ? EAS2.4, says (in case an actual load is needed)
*
* - r1 = [r3], Nat = 0 if succeeds
* - r1 = 0 Nat = 0 if trying to access non-speculative memory
*
* For us, there is nothing to do, because both ld.c.* and chk.a.* are going to
* retry and thus eventually reload the register thereby changing Nat and
* register content.
*/ */
/* /*
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment