From 0f2271373ee6a230d83cf7163fa190cdc7f8bd94 Mon Sep 17 00:00:00 2001 From: "Kenneth W. Chen" Date: Mon, 9 Feb 2004 20:55:53 -0800 Subject: [PATCH] [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. --- arch/ia64/kernel/unaligned.c | 44 ++++++++++++++---------------------- 1 file changed, 17 insertions(+), 27 deletions(-) diff --git a/arch/ia64/kernel/unaligned.c b/arch/ia64/kernel/unaligned.c index 6cb14f493cd9f..81b57c063be85 100644 --- a/arch/ia64/kernel/unaligned.c +++ b/arch/ia64/kernel/unaligned.c @@ -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. */ /* -- 2.53.0