From: Tom Musta <hidden> Date: 2013-10-18 19:38:52
This patch series addresses bugs in the PowerPC single-step emulation
code (arch/powerpc/lib/sstep.c) pertaining to Little Endian.
The existing code has a chicken switch for little endian. The first
patch softens the restriction so that only cross-endian modes are not
supported.
There is a general problem with unaligned little endian loads and stores.
This is addressed by the second patch.
Finally, there is a problem with unaligned single precision floating point
loads and stores which is addressed by the third patch.
Tom Musta (3):
powerpc: Enable emulate_step In Little Endian Mode
powerpc: Fix Unaligned Fixed Point Loads and Stores
powerpc: Fix Unaligned LE Floating Point Loads and Stores
arch/powerpc/lib/sstep.c | 109 +++++++++++++++++++++++++++++++++++++++------
1 files changed, 94 insertions(+), 15 deletions(-)
From: Tom Musta <hidden> Date: 2013-10-18 19:40:41
This patch modifies the endian chicken switch in the single step
emulation code (emulate_step()). The old (big endian) code bailed
early if a load or store instruction was to be emulated in little
endian mode.
The new code modifies the check and only bails in a cross-endian
situation (LE mode in a kernel compiled for BE and vice verse).
Signed-off-by: Tom Musta <redacted>
---
arch/powerpc/lib/sstep.c | 12 +++++++++---
1 files changed, 9 insertions(+), 3 deletions(-)
@@ -1222,12 +1222,18 @@ int __kprobes emulate_step(struct pt_regs *regs,
unsigned int instr)
}
/*
- * Following cases are for loads and stores, so bail out
- * if we're in little-endian mode.
+ * Following cases are for loads and stores and this
+ * implementation does not support cross-endian. So
+ * bail out if this is the case.
*/
+#ifdef __BIG_ENDIAN__
if (regs->msr & MSR_LE)
return 0;
-
+#endif
+#ifdef __LITTLE_ENDIAN__
+ if (!regs->msr & MSR_LE)
+ return 0;
+#endif
/*
* Save register RA in case it's an update form load or store
* and the access faults.
--
1.7.1
From: Tom Musta <hidden> Date: 2013-10-18 19:42:13
This patch modifies the unaligned access routines of the sstep.c
module so that it properly reverses the bytes of storage operands
in the little endian kernel kernel. This is implemented by
breaking an unaligned little endian access into a combination of
single byte accesses plus an overal byte reversal operation.
Signed-off-by: Tom Musta <redacted>
---
arch/powerpc/lib/sstep.c | 45 +++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 45 insertions(+), 0 deletions(-)
@@ -212,11 +212,19 @@ static int __kprobes read_mem_unaligned(unsigned long *dest, unsigned long ea,{interr;unsignedlongx,b,c;+#ifdef __LITTLE_ENDIAN__+intlen=nb;/* save a copy of the length for byte reversal */+#endif/* unaligned, do this in pieces */x=0;for(;nb>0;nb-=c){+#ifdef __LITTLE_ENDIAN__+c=1;+#endif+#ifdef __BIG_ENDIAN__c=max_align(ea);+#endifif(c>nb)c=max_align(nb);err=read_mem_aligned(&b,ea,c);
@@ -225,7 +233,24 @@ static int __kprobes read_mem_unaligned(unsigned long *dest, unsigned long ea,x=(x<<(8*c))+b;ea+=c;}+#ifdef __LITTLE_ENDIAN__+switch(len){+case2:+*dest=byterev_2(x);+break;+case4:+*dest=byterev_4(x);+break;+#ifdef __powerpc64__+case8:+*dest=byterev_8(x);+break;+#endif+}+#endif+#ifdef __BIG_ENDIAN__*dest=x;+#endifreturn0;}
@@ -273,9 +298,29 @@ static int __kprobes write_mem_unaligned(unsigned long val, unsigned long ea,interr;unsignedlongc;+#ifdef __LITTLE_ENDIAN__+switch(nb){+case2:+val=byterev_2(val);+break;+case4:+val=byterev_4(val);+break;+#ifdef __powerpc64__+case8:+val=byterev_8(val);+break;+#endif+}+#endif/* unaligned or little-endian, do this in pieces */for(;nb>0;nb-=c){+#ifdef __LITTLE_ENDIAN__+c=1;+#endif+#ifdef __BIG_ENDIAN__c=max_align(ea);+#endifif(c>nb)c=max_align(nb);err=write_mem_aligned(val>>(nb-c)*8,ea,c);
From: Tom Musta <hidden> Date: 2013-10-18 19:44:22
This patch addresses unaligned single precision floating point loads
and stores in the single-step code. The old implementation
improperly treated an 8 byte structure as an array of two 4 byte
words, which is a classic little endian bug.
Signed-off-by: Tom Musta <redacted>
---
arch/powerpc/lib/sstep.c | 52 +++++++++++++++++++++++++++++++++++----------
1 files changed, 40 insertions(+), 12 deletions(-)
From: Benjamin Herrenschmidt <benh@kernel.crashing.org> Date: 2013-10-30 02:04:18
On Fri, 2013-10-18 at 14:40 -0500, Tom Musta wrote:
This patch modifies the endian chicken switch in the single step
emulation code (emulate_step()). The old (big endian) code bailed
early if a load or store instruction was to be emulated in little
endian mode.
The new code modifies the check and only bails in a cross-endian
situation (LE mode in a kernel compiled for BE and vice verse).
I get a malformed patch error, looks like it got wrapped.
Cheers,
Ben.
quoted hunk
Signed-off-by: Tom Musta <redacted>
---
arch/powerpc/lib/sstep.c | 12 +++++++++---
1 files changed, 9 insertions(+), 3 deletions(-)
@@ -1222,12 +1222,18 @@ int __kprobes emulate_step(struct pt_regs *regs,
unsigned int instr)
}
/*
- * Following cases are for loads and stores, so bail out
- * if we're in little-endian mode.
+ * Following cases are for loads and stores and this
+ * implementation does not support cross-endian. So
+ * bail out if this is the case.
*/
+#ifdef __BIG_ENDIAN__
if (regs->msr & MSR_LE)
return 0;
-
+#endif
+#ifdef __LITTLE_ENDIAN__
+ if (!regs->msr & MSR_LE)
+ return 0;
+#endif
/*
* Save register RA in case it's an update form load or store
* and the access faults.
On Wed, Oct 30, 2013 at 8:35 PM, Tom Musta [off-list ref] wrote:
On 10/30/2013 12:43 PM, Andreas Schwab wrote:
quoted
Tom Musta [off-list ref] writes:
quoted
+#ifdef __LITTLE_ENDIAN__
+ if (!regs->msr & MSR_LE)
That won't work.
Andreas.
Please elaborate.
You want to test for "!(regs & MSR_LE)".
Gr{oetje,eeting}s,
Geert
--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org
In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds
From: Tom Musta <hidden> Date: 2013-10-30 21:46:08
On 10/30/2013 2:43 PM, Geert Uytterhoeven wrote:
On Wed, Oct 30, 2013 at 8:35 PM, Tom Musta [off-list ref] wrote:
quoted
On 10/30/2013 12:43 PM, Andreas Schwab wrote:
quoted
Tom Musta [off-list ref] writes:
quoted
+#ifdef __LITTLE_ENDIAN__
+ if (!regs->msr & MSR_LE)
That won't work.
Andreas.
Please elaborate.
You want to test for "!(regs & MSR_LE)".
Gr{oetje,eeting}s,
Geert
--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org
In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds
Thanks Adnreas and Geert. I will fix and resubmit.