summaryrefslogtreecommitdiff
path: root/include/linux
diff options
context:
space:
mode:
authorAnton Blanchard <anton@samba.org>2006-01-10 10:21:20 +0300
committerLinus Torvalds <torvalds@g5.osdl.org>2006-01-10 19:32:35 +0300
commitc8d52465f95c4187871f8e65666c07806ca06d41 (patch)
tree873a77cf0b47c92fbdc5cb8dd8baa7583c26bbfd /include/linux
parent115b2ce1c3b974e43e45fa6c9e20cd7271a01dff (diff)
downloadlinux-c8d52465f95c4187871f8e65666c07806ca06d41.tar.xz
[PATCH] Work around ppc64 compiler bug
In the process of optimising our per cpu data code, I found a ppc64 compiler bug that has been around forever. Basically the current RELOC_HIDE can end up trashing r30. Details of the bug can be found at http://gcc.gnu.org/bugzilla/show_bug.cgi?id=25572 This bug is present in all compilers before 4.1. It is masked by the fact that our current per cpu data code is inefficient and causes other loads that end up marking r30 as used. A workaround identified by Alan Modra is to use the =r asm constraint instead of =g. Signed-off-by: Anton Blanchard <anton@samba.org> [ Verified that this makes no real difference on x86[-64] */ Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'include/linux')
-rw-r--r--include/linux/compiler-gcc.h8
1 files changed, 7 insertions, 1 deletions
diff --git a/include/linux/compiler-gcc.h b/include/linux/compiler-gcc.h
index 2e05e1e6b0e6..6e1c44a935d4 100644
--- a/include/linux/compiler-gcc.h
+++ b/include/linux/compiler-gcc.h
@@ -11,9 +11,15 @@
/* This macro obfuscates arithmetic on a variable address so that gcc
shouldn't recognize the original var, and make assumptions about it */
+/*
+ * Versions of the ppc64 compiler before 4.1 had a bug where use of
+ * RELOC_HIDE could trash r30. The bug can be worked around by changing
+ * the inline assembly constraint from =g to =r, in this particular
+ * case either is valid.
+ */
#define RELOC_HIDE(ptr, off) \
({ unsigned long __ptr; \
- __asm__ ("" : "=g"(__ptr) : "0"(ptr)); \
+ __asm__ ("" : "=r"(__ptr) : "0"(ptr)); \
(typeof(ptr)) (__ptr + (off)); })