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
emulate_load_int (unsigned long ifa, load_store_t ld, struct pt_regs *regs)
{
unsigned int len = 1 << ld.x6_sz;
unsigned long val = 0;
/*
* 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)
*/
/*
* 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
*/
if (ld.x6_op != 0x2) {
unsigned long val = 0;
if (len != 2 && len != 4 && len != 8) {
DPRINT("unknown size: x6=%d\n", ld.x6_sz);
return -1;
}
/* this assumes little-endian byte-order: */
if (copy_from_user(&val, (void *) ifa, len))
return -1;
setreg(ld.r1, val, 0, regs);
if (len != 2 && len != 4 && len != 8) {
DPRINT("unknown size: x6=%d\n", ld.x6_sz);
return -1;
}
/* 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
......@@ -817,7 +815,7 @@ emulate_load_int (unsigned long ifa, load_store_t ld, struct pt_regs *regs)
* store & shift to 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
* 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
......@@ -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
* 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
* chck.a.* to reuse the value stored in the ALAT. Both can "fail" (meaning no
* If there is a store after the advanced load, one must either do a ld.c.* or
* 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:
*
* - 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)
*
* 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
* must be invalidated for the register (so that's chck.a.*,ld.c.* don't pick up
* 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.
* ALAT must be invalidated for the register (so that chk.a or ld.c don't pick
* up a stale entry later). The register base update MUST also be performed.
*/
/*
......
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