From: David Mosberger <davidm@napali.hpl.hp.com>
To: linux-ia64@vger.kernel.org
Subject: [Linux-ia64] more unaligned.c cleanup/fixes
Date: Tue, 10 Dec 2002 03:13:31 +0000 [thread overview]
Message-ID: <marc-linux-ia64-105590709805532@msgid-missing> (raw)
While working on unaligned.c, I found some opportunities to simplify
the existing rotation code and while doing that, discovered two more
bugs:
- the old code rotated one register beyond the rotating partition
(e.g., with 8 registers allocated, r40 would incorrectly get
rotated)
- the old code inadvertently leaked kernel bits when an unaligned
access read from an out-of-frame register occurred
- someone was a bit overeager in "fixing" printk() formats; printing
KERN_ERR as the first format string doesn't do much good...
(not sure how this happened...)
Bjorn, I think this patch should apply on 2.4 as well.
--david
=== arch/ia64/kernel/unaligned.c 1.6 vs edited ==--- 1.6/arch/ia64/kernel/unaligned.c Thu Mar 14 00:28:41 2002
+++ edited/arch/ia64/kernel/unaligned.c Mon Dec 9 19:05:05 2002
@@ -5,6 +5,10 @@
* Stephane Eranian <eranian@hpl.hp.com>
* David Mosberger-Tang <davidm@hpl.hp.com>
*
+ * 2002/12/09 Fix rotating register handling (off-by-1 error, missing fr-rotation). Fix
+ * get_rse_reg() to not leak kernel bits to user-level (reading an out-of-frame
+ * stacked register returns an undefined value; it does NOT trigger a
+ * "rsvd register fault").
* 2001/10/11 Fix unaligned access to rotating registers in s/w pipelined loops.
* 2001/08/13 Correct size of extended floats (float_fsz) from 16 to 10 bytes.
* 2001/01/17 Add support emulation of unaligned kernel accesses.
@@ -276,6 +280,15 @@
# undef F
}
+static inline unsigned long
+rotate_reg (unsigned long sor, unsigned long rrb, unsigned long reg)
+{
+ reg += rrb;
+ if (reg >= sor)
+ reg -= sor;
+ return reg;
+}
+
static void
set_rse_reg (struct pt_regs *regs, unsigned long r1, unsigned long val, int nat)
{
@@ -287,26 +300,22 @@
long sof = (regs->cr_ifs) & 0x7f;
long sor = 8 * ((regs->cr_ifs >> 14) & 0xf);
long rrb_gr = (regs->cr_ifs >> 18) & 0x7f;
- long ridx;
-
- if ((r1 - 32) > sor)
- ridx = -sof + (r1 - 32);
- else if ((r1 - 32) < (sor - rrb_gr))
- ridx = -sof + (r1 - 32) + rrb_gr;
- else
- ridx = -sof + (r1 - 32) - (sor - rrb_gr);
-
- DPRINT("r%lu, sw.bspstore=%lx pt.bspstore=%lx sof=%ld sol=%ld ridx=%ld\n",
- r1, sw->ar_bspstore, regs->ar_bspstore, sof, (regs->cr_ifs >> 7) & 0x7f, ridx);
+ long ridx = r1 - 32;
- if ((r1 - 32) >= sof) {
+ if (ridx >= sof) {
/* this should never happen, as the "rsvd register fault" has higher priority */
DPRINT("ignoring write to r%lu; only %lu registers are allocated!\n", r1, sof);
return;
}
+ if (ridx < sor)
+ ridx = rotate_reg(sor, rrb_gr, ridx);
+
+ DPRINT("r%lu, sw.bspstore=%lx pt.bspstore=%lx sof=%ld sol=%ld ridx=%ld\n",
+ r1, sw->ar_bspstore, regs->ar_bspstore, sof, (regs->cr_ifs >> 7) & 0x7f, ridx);
+
on_kbs = ia64_rse_num_regs(kbs, (unsigned long *) sw->ar_bspstore);
- addr = ia64_rse_skip_regs((unsigned long *) sw->ar_bspstore, ridx);
+ addr = ia64_rse_skip_regs((unsigned long *) sw->ar_bspstore, -sof + ridx);
if (addr >= kbs) {
/* the register is on the kernel backing store: easy... */
rnat_addr = ia64_rse_rnat_addr(addr);
@@ -334,7 +343,7 @@
bspstore = (unsigned long *)regs->ar_bspstore;
ubs_end = ia64_rse_skip_regs(bspstore, on_kbs);
bsp = ia64_rse_skip_regs(ubs_end, -sof);
- addr = ia64_rse_skip_regs(bsp, ridx + sof);
+ addr = ia64_rse_skip_regs(bsp, ridx);
DPRINT("ubs_end=%p bsp=%p addr=%p\n", (void *) ubs_end, (void *) bsp, (void *) addr);
@@ -368,26 +377,22 @@
long sof = (regs->cr_ifs) & 0x7f;
long sor = 8 * ((regs->cr_ifs >> 14) & 0xf);
long rrb_gr = (regs->cr_ifs >> 18) & 0x7f;
- long ridx;
+ long ridx = r1 - 32;
- if ((r1 - 32) > sor)
- ridx = -sof + (r1 - 32);
- else if ((r1 - 32) < (sor - rrb_gr))
- ridx = -sof + (r1 - 32) + rrb_gr;
- else
- ridx = -sof + (r1 - 32) - (sor - rrb_gr);
+ if (ridx >= sof) {
+ /* read of out-of-frame register returns an undefined value; 0 in our case. */
+ DPRINT("ignoring read from r%lu; only %lu registers are allocated!\n", r1, sof);
+ goto fail;
+ }
+
+ if (ridx < sor)
+ ridx = rotate_reg(sor, rrb_gr, ridx);
DPRINT("r%lu, sw.bspstore=%lx pt.bspstore=%lx sof=%ld sol=%ld ridx=%ld\n",
r1, sw->ar_bspstore, regs->ar_bspstore, sof, (regs->cr_ifs >> 7) & 0x7f, ridx);
- if ((r1 - 32) >= sof) {
- /* this should never happen, as the "rsvd register fault" has higher priority */
- DPRINT("ignoring read from r%lu; only %lu registers are allocated!\n", r1, sof);
- return;
- }
-
on_kbs = ia64_rse_num_regs(kbs, (unsigned long *) sw->ar_bspstore);
- addr = ia64_rse_skip_regs((unsigned long *) sw->ar_bspstore, ridx);
+ addr = ia64_rse_skip_regs((unsigned long *) sw->ar_bspstore, -sof + ridx);
if (addr >= kbs) {
/* the register is on the kernel backing store: easy... */
*val = *addr;
@@ -407,13 +412,13 @@
*/
if (regs->r12 >= TASK_SIZE) {
DPRINT("ignoring kernel read of r%lu; register isn't on the RBS!", r1);
- return;
+ goto fail;
}
bspstore = (unsigned long *)regs->ar_bspstore;
ubs_end = ia64_rse_skip_regs(bspstore, on_kbs);
bsp = ia64_rse_skip_regs(ubs_end, -sof);
- addr = ia64_rse_skip_regs(bsp, ridx + sof);
+ addr = ia64_rse_skip_regs(bsp, ridx);
DPRINT("ubs_end=%p bsp=%p addr=%p\n", (void *) ubs_end, (void *) bsp, (void *) addr);
@@ -428,6 +433,13 @@
ia64_peek(current, sw, (unsigned long) ubs_end, (unsigned long) rnat_addr, &rnats);
*nat = (rnats & nat_mask) != 0;
}
+ return;
+
+ fail:
+ *val = 0;
+ if (nat)
+ *nat = 0;
+ return;
}
@@ -486,7 +498,16 @@
DPRINT("*0x%lx=0x%lx NaT=%d new unat: %p=%lx\n", addr, val, nat, (void *) unat,*unat);
}
-#define IA64_FPH_OFFS(r) (r - IA64_FIRST_ROTATING_FR)
+/*
+ * Return the (rotated) index for floating point register REGNUM (REGNUM must be in the
+ * range from 32-127, result is in the range from 0-95.
+ */
+static inline unsigned long
+fph_index (struct pt_regs *regs, long regnum)
+{
+ unsigned long rrb_fr = (regs->cr_ifs >> 25) & 0x7f;
+ return rotate_reg(96, rrb_fr, (regnum - IA64_FIRST_ROTATING_FR));
+}
static void
setfpreg (unsigned long regnum, struct ia64_fpreg *fpval, struct pt_regs *regs)
@@ -507,7 +528,7 @@
*/
if (regnum >= IA64_FIRST_ROTATING_FR) {
ia64_sync_fph(current);
- current->thread.fph[IA64_FPH_OFFS(regnum)] = *fpval;
+ current->thread.fph[fph_index(regs, regnum)] = *fpval;
} else {
/*
* pt_regs or switch_stack ?
@@ -566,7 +587,7 @@
*/
if (regnum >= IA64_FIRST_ROTATING_FR) {
ia64_flush_fph(current);
- *fpval = current->thread.fph[IA64_FPH_OFFS(regnum)];
+ *fpval = current->thread.fph[fph_index(regs, regnum)];
} else {
/*
* f0 = 0.0, f1= 1.0. Those registers are constant and are thus
@@ -651,7 +672,7 @@
* just in case.
*/
if (ld.x6_op = 1 || ld.x6_op = 3) {
- printk("%s %s: register update on speculative load, error\n", KERN_ERR, __FUNCTION__);
+ printk(KERN_ERR "%s: register update on speculative load, error\n", __FUNCTION__);
die_if_kernel("unaligned reference on specualtive load with register update\n",
regs, 30);
}
@@ -1081,8 +1102,8 @@
* For this reason we keep this sanity check
*/
if (ld.x6_op = 1 || ld.x6_op = 3)
- printk("%s %s: register update on speculative load pair, "
- "error\n",KERN_ERR, __FUNCTION__);
+ printk(KERN_ERR "%s: register update on speculative load pair, error\n",
+ __FUNCTION__);
setreg(ld.r3, ifa, 0, regs);
}
reply other threads:[~2002-12-10 3:13 UTC|newest]
Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=marc-linux-ia64-105590709805532@msgid-missing \
--to=davidm@napali.hpl.hp.com \
--cc=linux-ia64@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.