| From d919b8b86ef0bde9fa4f3dc8fd53766f06dc0010 Mon Sep 17 00:00:00 2001 |
| From: Jim Bos <jim876@xs4all.nl> |
| Date: Mon, 15 Nov 2010 21:22:37 +0100 |
| Subject: [PATCH] Fix gcc 4.5.1 miscompiling drivers/char/i8k.c (again) |
| |
| commit 22d3243de86bc92d874abb7c5b185d5c47aba323 upstream. |
| |
| 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> |
| Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> |
| |
| diff --git a/drivers/char/i8k.c b/drivers/char/i8k.c |
| index 828fd24..4365717 100644 |
| --- a/drivers/char/i8k.c |
| +++ b/drivers/char/i8k.c |
| @@ -119,7 +119,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" |
| @@ -141,11 +141,11 @@ static int i8k_smm(struct smm_regs *regs) |
| "lahf\n\t" |
| "shrl $8,%%eax\n\t" |
| "andl $1,%%eax\n" |
| - :"=a"(rc), "+m" (*regs) |
| + :"=a"(rc) |
| : "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,7 @@ static int i8k_smm(struct smm_regs *regs) |
| "lahf\n\t" |
| "shrl $8,%%eax\n\t" |
| "andl $1,%%eax\n" |
| - :"=a"(rc), "+m" (*regs) |
| + :"=a"(rc) |
| : "a"(regs) |
| : "%ebx", "%ecx", "%edx", "%esi", "%edi", "memory"); |
| #endif |
| -- |
| 1.7.7 |
| |