summaryrefslogtreecommitdiffstats
path: root/fix-i8k-inline-asm.patch
blob: 87fadc01490aa8c5310cf101d8987ab40dd50f09 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
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