85 lines
3.1 KiB
Diff
85 lines
3.1 KiB
Diff
|
commit 22d3243de86bc92d874abb7c5b185d5c47aba323
|
||
|
Author: Jim Bos <jim876@xs4all.nl>
|
||
|
Date: Mon Nov 15 21:22:37 2010 +0100
|
||
|
|
||
|
Fix gcc 4.5.1 miscompiling drivers/char/i8k.c (again)
|
||
|
|
||
|
The fix in commit 6b4e81db2552 ("i8k: Tell gcc that *regs gets
|
||
|
clobbered") to work around the gcc miscompiling i8k.c to add "+m
|
||
|
(*regs)" caused register pressure problems and a build failure.
|
||
|
|
||
|
Changing the 'asm' statement to 'asm volatile' instead should prevent
|
||
|
that and works around the gcc bug as well, so we can remove the "+m".
|
||
|
|
||
|
[ Background on the gcc bug: a memory clobber fails to mark the function
|
||
|
the asm resides in as non-pure (aka "__attribute__((const))"), so if
|
||
|
the function does nothing else that triggers the non-pure logic, gcc
|
||
|
will think that that function has no side effects at all. As a result,
|
||
|
callers will be mis-compiled.
|
||
|
|
||
|
Adding the "+m" made gcc see that it's not a pure function, and so
|
||
|
does "asm volatile". The problem was never really the need to mark
|
||
|
"*regs" as changed, since the memory clobber did that part - the
|
||
|
problem was just a bug in the gcc "pure" function analysis - Linus ]
|
||
|
|
||
|
Signed-off-by: Jim Bos <jim876@xs4all.nl>
|
||
|
Acked-by: Jakub Jelinek <jakub@redhat.com>
|
||
|
Cc: Andi Kleen <andi@firstfloor.org>
|
||
|
Cc: Andreas Schwab <schwab@linux-m68k.org>
|
||
|
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
|
||
|
|
||
|
commit 6b4e81db2552bad04100e7d5ddeed7e848f53b48
|
||
|
Author: Jim Bos <jim876@xs4all.nl>
|
||
|
Date: Sat Nov 13 12:13:53 2010 +0100
|
||
|
|
||
|
i8k: Tell gcc that *regs gets clobbered
|
||
|
|
||
|
More recent GCC caused the i8k driver to stop working, on Slackware
|
||
|
compiler was upgraded from gcc-4.4.4 to gcc-4.5.1 after which it didn't
|
||
|
work anymore, meaning the driver didn't load or gave total nonsensical
|
||
|
output.
|
||
|
|
||
|
As it turned out the asm(..) statement forgot to mention it modifies the
|
||
|
*regs variable.
|
||
|
|
||
|
Credits to Andi Kleen and Andreas Schwab for providing the fix.
|
||
|
|
||
|
Signed-off-by: Jim Bos <jim876@xs4all.nl>
|
||
|
Cc: Andi Kleen <andi@firstfloor.org>
|
||
|
Cc: Andreas Schwab <schwab@linux-m68k.org>
|
||
|
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
|
||
|
|
||
|
---
|
||
|
diff --git a/drivers/char/i8k.c b/drivers/char/i8k.c
|
||
|
index 3bc0eef..d72433f 100644
|
||
|
--- a/drivers/char/i8k.c
|
||
|
+++ b/drivers/char/i8k.c
|
||
|
@@ -120,7 +120,7 @@ static int i8k_smm(struct smm_regs *regs)
|
||
|
int eax = regs->eax;
|
||
|
|
||
|
#if defined(CONFIG_X86_64)
|
||
|
- asm("pushq %%rax\n\t"
|
||
|
+ asm volatile("pushq %%rax\n\t"
|
||
|
"movl 0(%%rax),%%edx\n\t"
|
||
|
"pushq %%rdx\n\t"
|
||
|
"movl 4(%%rax),%%ebx\n\t"
|
||
|
@@ -146,7 +146,7 @@ static int i8k_smm(struct smm_regs *regs)
|
||
|
: "a"(regs)
|
||
|
: "%ebx", "%ecx", "%edx", "%esi", "%edi", "memory");
|
||
|
#else
|
||
|
- asm("pushl %%eax\n\t"
|
||
|
+ asm volatile("pushl %%eax\n\t"
|
||
|
"movl 0(%%eax),%%edx\n\t"
|
||
|
"push %%edx\n\t"
|
||
|
"movl 4(%%eax),%%ebx\n\t"
|
||
|
@@ -167,7 +167,8 @@ static int i8k_smm(struct smm_regs *regs)
|
||
|
"movl %%edx,0(%%eax)\n\t"
|
||
|
"lahf\n\t"
|
||
|
"shrl $8,%%eax\n\t"
|
||
|
- "andl $1,%%eax\n":"=a"(rc)
|
||
|
+ "andl $1,%%eax\n"
|
||
|
+ :"=a"(rc)
|
||
|
: "a"(regs)
|
||
|
: "%ebx", "%ecx", "%edx", "%esi", "%edi", "memory");
|
||
|
#endif
|