public inbox for linux-ia64@vger.kernel.org
 help / color / mirror / Atom feed
From: "Luck, Tony" <tony.luck@intel.com>
To: linux-ia64@vger.kernel.org
Subject: [Linux-ia64] [patch] fix unaligned references inside s/w pipelined loops
Date: Tue, 16 Oct 2001 15:54:08 +0000	[thread overview]
Message-ID: <marc-linux-ia64-105590698805353@msgid-missing> (raw)

[-- Attachment #1: Type: text/plain, Size: 655 bytes --]

If an application takes an unaligned trap on a "rotating"
register inside a software pipelined loop[1], then the kernel
will use the wrong register when it fixes the fault.  This
results in corrupted memory or register depending on whether
the unaligned reference was a store or a load respectively.

Attached is a patch to fix this (both for the integer case,
which was the one actually reported to me, and the floating
point case too).  Patch is against 2.4.10.

-Tony Luck

[1] Don't ask me why someone would go through all the effort
of writing a s/w pipelined loop, but not check for unaligned
access, I don't understand it either ... but they did.


[-- Attachment #2: diff.unaligned.txt --]
[-- Type: text/plain, Size: 3957 bytes --]

--- ../../REF/2.4.10-ia64-combo/arch/ia64/kernel/unaligned.c	Wed Oct  3 11:02:18 2001
+++ linux/arch/ia64/kernel/unaligned.c	Thu Oct 11 09:00:54 2001
@@ -5,6 +5,7 @@
  * Copyright (C) 1999-2000 Stephane Eranian <eranian@hpl.hp.com>
  * Copyright (C) 2001 David Mosberger-Tang <davidm@hpl.hp.com>
  *
+ * 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.
  */
@@ -283,9 +284,19 @@
 	unsigned long rnats, nat_mask;
 	unsigned long on_kbs;
 	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\n",
-	       r1, sw->ar_bspstore, regs->ar_bspstore, sof, (regs->cr_ifs >> 7) & 0x7f);
+	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 */
@@ -294,7 +305,7 @@
 	}
 
 	on_kbs = ia64_rse_num_regs(kbs, (unsigned long *) sw->ar_bspstore);
-	addr = ia64_rse_skip_regs((unsigned long *) sw->ar_bspstore, -sof + (r1 - 32));
+	addr = ia64_rse_skip_regs((unsigned long *) sw->ar_bspstore, ridx);
 	if (addr >= kbs) {
 		/* the register is on the kernel backing store: easy... */
 		rnat_addr = ia64_rse_rnat_addr(addr);
@@ -319,12 +330,12 @@
 		return;
 	}
 
-	bspstore = (unsigned long *) regs->ar_bspstore;
+	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, r1 - 32);
+	addr    = ia64_rse_skip_regs(bsp, ridx + sof);
 
-	DPRINT("ubs_end=%p bsp=%p addr=%px\n", (void *) ubs_end, (void *) bsp, (void *) addr);
+	DPRINT("ubs_end=%p bsp=%p addr=%p\n", (void *) ubs_end, (void *) bsp, (void *) addr);
 
 	ia64_poke(current, sw, (unsigned long) ubs_end, (unsigned long) addr, val);
 
@@ -354,9 +365,19 @@
 	unsigned long rnats, nat_mask;
 	unsigned long on_kbs;
 	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\n",
-	       r1, sw->ar_bspstore, regs->ar_bspstore, sof, (regs->cr_ifs >> 7) & 0x7f);
+	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 */
@@ -365,7 +386,7 @@
 	}
 
 	on_kbs = ia64_rse_num_regs(kbs, (unsigned long *) sw->ar_bspstore);
-	addr = ia64_rse_skip_regs((unsigned long *) sw->ar_bspstore, -sof + (r1 - 32));
+	addr = ia64_rse_skip_regs((unsigned long *) sw->ar_bspstore, ridx);
 	if (addr >= kbs) {
 		/* the register is on the kernel backing store: easy... */
 		*val = *addr;
@@ -391,7 +412,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, r1 - 32);
+	addr    = ia64_rse_skip_regs(bsp, ridx + sof);
 
 	DPRINT("ubs_end=%p bsp=%p addr=%p\n", (void *) ubs_end, (void *) bsp, (void *) addr);
 

                 reply	other threads:[~2001-10-16 15:54 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-105590698805353@msgid-missing \
    --to=tony.luck@intel.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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox