fix i8k inline asm to workaround miscompilation with newer gcc
This commit is contained in:
parent
51157289c8
commit
cc7fb594a9
|
@ -0,0 +1,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
|
11
kernel.spec
11
kernel.spec
|
@ -656,8 +656,6 @@ Patch800: linux-2.6-crash-driver.patch
|
|||
|
||||
# virt + ksm patches
|
||||
Patch1555: fix_xen_guest_on_old_EC2.patch
|
||||
# Already upstream (commit 16518d5ada690643453eb0aef3cc7841d3623c2d)
|
||||
Patch1556: kvm-fix-regression-with-cmpxchg8b-on-i386-hosts.patch
|
||||
|
||||
# DRM
|
||||
Patch1801: drm-polling-fixes.patch
|
||||
|
@ -777,6 +775,8 @@ Patch13645: tpm-autodetect-itpm-devices.patch
|
|||
|
||||
Patch13651: kvm-fix-fs-gs-reload-oops-with-invalid-ldt.patch
|
||||
|
||||
Patch13652: fix-i8k-inline-asm.patch
|
||||
|
||||
%endif
|
||||
|
||||
BuildRoot: %{_tmppath}/kernel-%{KVERREL}-root
|
||||
|
@ -1322,7 +1322,6 @@ ApplyPatch linux-2.6-e1000-ich9-montevina.patch
|
|||
|
||||
# Assorted Virt Fixes
|
||||
ApplyPatch fix_xen_guest_on_old_EC2.patch
|
||||
#ApplyPatch kvm-fix-regression-with-cmpxchg8b-on-i386-hosts.patch
|
||||
|
||||
ApplyPatch drm-polling-fixes.patch
|
||||
ApplyPatch drm-edid-invalid.patch
|
||||
|
@ -1450,6 +1449,8 @@ ApplyPatch tpm-autodetect-itpm-devices.patch
|
|||
# CVE-2010-3698
|
||||
ApplyPatch kvm-fix-fs-gs-reload-oops-with-invalid-ldt.patch
|
||||
|
||||
ApplyPatch fix-i8k-inline-asm.patch
|
||||
|
||||
# END OF PATCH APPLICATIONS
|
||||
|
||||
%endif
|
||||
|
@ -2036,6 +2037,10 @@ fi
|
|||
# and build.
|
||||
|
||||
%changelog
|
||||
* Tue Nov 23 2010 Kyle McMartin <kyle@redhat.com>
|
||||
- fix-i8k-inline-asm.patch: backport gcc miscompilation fix from git
|
||||
[22d3243d, 6b4e81db] (rhbz#647677)
|
||||
|
||||
* Mon Nov 22 2010 Jarod Wilson <jarod@redhat.com> 2.6.35.9-62
|
||||
- Linux 2.6.35.9
|
||||
- IR driver fixes from upstream
|
||||
|
|
|
@ -1,70 +0,0 @@
|
|||
commit 16518d5ada690643453eb0aef3cc7841d3623c2d
|
||||
Author: Avi Kivity <avi@redhat.com>
|
||||
Date: Thu Aug 26 14:31:30 2010 +0300
|
||||
|
||||
KVM: x86 emulator: fix regression with cmpxchg8b on i386 hosts
|
||||
|
||||
operand::val and operand::orig_val are 32-bit on i386, whereas cmpxchg8b
|
||||
operands are 64-bit.
|
||||
|
||||
Fix by adding val64 and orig_val64 union members to struct operand, and
|
||||
using them where needed.
|
||||
|
||||
Signed-off-by: Avi Kivity <avi@redhat.com>
|
||||
Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
|
||||
|
||||
@@ -, +, @@
|
||||
arch/x86/include/asm/kvm_emulate.h | 10 +++++++++-
|
||||
arch/x86/kvm/emulate.c | 9 ++++-----
|
||||
2 files changed, 13 insertions(+), 6 deletions(-)
|
||||
--- a/arch/x86/include/asm/kvm_emulate.h
|
||||
+++ a/arch/x86/include/asm/kvm_emulate.h
|
||||
@@ -143,7 +143,15 @@ struct x86_emulate_ops {
|
||||
struct operand {
|
||||
enum { OP_REG, OP_MEM, OP_IMM, OP_NONE } type;
|
||||
unsigned int bytes;
|
||||
- unsigned long val, orig_val, *ptr;
|
||||
+ union {
|
||||
+ unsigned long orig_val;
|
||||
+ u64 orig_val64;
|
||||
+ };
|
||||
+ unsigned long *ptr;
|
||||
+ union {
|
||||
+ unsigned long val;
|
||||
+ u64 val64;
|
||||
+ };
|
||||
};
|
||||
|
||||
struct fetch_cache {
|
||||
--- a/arch/x86/kvm/emulate.c
|
||||
+++ a/arch/x86/kvm/emulate.c
|
||||
@@ -1712,17 +1712,16 @@ static inline int emulate_grp9(struct x86_emulate_ctxt *ctxt,
|
||||
struct x86_emulate_ops *ops)
|
||||
{
|
||||
struct decode_cache *c = &ctxt->decode;
|
||||
- u64 old = c->dst.orig_val;
|
||||
+ u64 old = c->dst.orig_val64;
|
||||
|
||||
if (((u32) (old >> 0) != (u32) c->regs[VCPU_REGS_RAX]) ||
|
||||
((u32) (old >> 32) != (u32) c->regs[VCPU_REGS_RDX])) {
|
||||
-
|
||||
c->regs[VCPU_REGS_RAX] = (u32) (old >> 0);
|
||||
c->regs[VCPU_REGS_RDX] = (u32) (old >> 32);
|
||||
ctxt->eflags &= ~EFLG_ZF;
|
||||
} else {
|
||||
- c->dst.val = ((u64)c->regs[VCPU_REGS_RCX] << 32) |
|
||||
- (u32) c->regs[VCPU_REGS_RBX];
|
||||
+ c->dst.val64 = ((u64)c->regs[VCPU_REGS_RCX] << 32) |
|
||||
+ (u32) c->regs[VCPU_REGS_RBX];
|
||||
|
||||
ctxt->eflags |= EFLG_ZF;
|
||||
}
|
||||
@@ -2535,7 +2534,7 @@ x86_emulate_insn(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops)
|
||||
ctxt->vcpu);
|
||||
if (rc != X86EMUL_CONTINUE)
|
||||
goto done;
|
||||
- c->src.orig_val = c->src.val;
|
||||
+ c->src.orig_val64 = c->src.val64;
|
||||
}
|
||||
|
||||
if (c->src2.type == OP_MEM) {
|
Loading…
Reference in New Issue