]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
3.0-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 23 Mar 2012 17:25:01 +0000 (10:25 -0700)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 23 Mar 2012 17:25:01 +0000 (10:25 -0700)
added patches:
kvm-x86-extend-struct-x86_emulate_ops-with-get_cpuid.patch
kvm-x86-fix-missing-checks-in-syscall-emulation.patch

queue-3.0/kvm-x86-extend-struct-x86_emulate_ops-with-get_cpuid.patch [new file with mode: 0644]
queue-3.0/kvm-x86-fix-missing-checks-in-syscall-emulation.patch [new file with mode: 0644]
queue-3.0/series

diff --git a/queue-3.0/kvm-x86-extend-struct-x86_emulate_ops-with-get_cpuid.patch b/queue-3.0/kvm-x86-extend-struct-x86_emulate_ops-with-get_cpuid.patch
new file mode 100644 (file)
index 0000000..887f4de
--- /dev/null
@@ -0,0 +1,77 @@
+From bdb42f5afebe208eae90406959383856ae2caf2b Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Stephan=20B=C3=A4rwolf?= <stephan.baerwolf@tu-ilmenau.de>
+Date: Thu, 12 Jan 2012 16:43:03 +0100
+Subject: KVM: x86: extend "struct x86_emulate_ops" with "get_cpuid"
+
+From: =?UTF-8?q?Stephan=20B=C3=A4rwolf?= <stephan.baerwolf@tu-ilmenau.de>
+
+commit bdb42f5afebe208eae90406959383856ae2caf2b upstream.
+
+In order to be able to proceed checks on CPU-specific properties
+within the emulator, function "get_cpuid" is introduced.
+With "get_cpuid" it is possible to virtually call the guests
+"cpuid"-opcode without changing the VM's context.
+
+[mtosatti: cleanup/beautify code]
+
+Signed-off-by: Stephan Baerwolf <stephan.baerwolf@tu-ilmenau.de>
+Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
+Signed-off-by: Stefan Bader <stefan.bader@canonical.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ arch/x86/include/asm/kvm_emulate.h |    3 +++
+ arch/x86/kvm/x86.c                 |   23 +++++++++++++++++++++++
+ 2 files changed, 26 insertions(+)
+
+--- a/arch/x86/include/asm/kvm_emulate.h
++++ b/arch/x86/include/asm/kvm_emulate.h
+@@ -189,6 +189,9 @@ struct x86_emulate_ops {
+       int (*intercept)(struct x86_emulate_ctxt *ctxt,
+                        struct x86_instruction_info *info,
+                        enum x86_intercept_stage stage);
++
++      bool (*get_cpuid)(struct x86_emulate_ctxt *ctxt,
++                       u32 *eax, u32 *ebx, u32 *ecx, u32 *edx);
+ };
+ typedef u32 __attribute__((vector_size(16))) sse128_t;
+--- a/arch/x86/kvm/x86.c
++++ b/arch/x86/kvm/x86.c
+@@ -4407,6 +4407,28 @@ static int emulator_intercept(struct x86
+       return kvm_x86_ops->check_intercept(emul_to_vcpu(ctxt), info, stage);
+ }
++static bool emulator_get_cpuid(struct x86_emulate_ctxt *ctxt,
++                             u32 *eax, u32 *ebx, u32 *ecx, u32 *edx)
++{
++      struct kvm_cpuid_entry2 *cpuid = NULL;
++
++      if (eax && ecx)
++              cpuid = kvm_find_cpuid_entry(emul_to_vcpu(ctxt),
++                                          *eax, *ecx);
++
++      if (cpuid) {
++              *eax = cpuid->eax;
++              *ecx = cpuid->ecx;
++              if (ebx)
++                      *ebx = cpuid->ebx;
++              if (edx)
++                      *edx = cpuid->edx;
++              return true;
++      }
++
++      return false;
++}
++
+ static struct x86_emulate_ops emulate_ops = {
+       .read_std            = kvm_read_guest_virt_system,
+       .write_std           = kvm_write_guest_virt_system,
+@@ -4437,6 +4459,7 @@ static struct x86_emulate_ops emulate_op
+       .get_fpu             = emulator_get_fpu,
+       .put_fpu             = emulator_put_fpu,
+       .intercept           = emulator_intercept,
++      .get_cpuid           = emulator_get_cpuid,
+ };
+ static void cache_all_regs(struct kvm_vcpu *vcpu)
diff --git a/queue-3.0/kvm-x86-fix-missing-checks-in-syscall-emulation.patch b/queue-3.0/kvm-x86-fix-missing-checks-in-syscall-emulation.patch
new file mode 100644 (file)
index 0000000..8b7abad
--- /dev/null
@@ -0,0 +1,144 @@
+From c2226fc9e87ba3da060e47333657cd6616652b84 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Stephan=20B=C3=A4rwolf?= <stephan.baerwolf@tu-ilmenau.de>
+Date: Thu, 12 Jan 2012 16:43:04 +0100
+Subject: KVM: x86: fix missing checks in syscall emulation
+
+From: =?UTF-8?q?Stephan=20B=C3=A4rwolf?= <stephan.baerwolf@tu-ilmenau.de>
+
+commit c2226fc9e87ba3da060e47333657cd6616652b84 upstream.
+
+On hosts without this patch, 32bit guests will crash (and 64bit guests
+may behave in a wrong way) for example by simply executing following
+nasm-demo-application:
+
+    [bits 32]
+    global _start
+    SECTION .text
+    _start: syscall
+
+(I tested it with winxp and linux - both always crashed)
+
+    Disassembly of section .text:
+
+    00000000 <_start>:
+       0:   0f 05                   syscall
+
+The reason seems a missing "invalid opcode"-trap (int6) for the
+syscall opcode "0f05", which is not available on Intel CPUs
+within non-longmodes, as also on some AMD CPUs within legacy-mode.
+(depending on CPU vendor, MSR_EFER and cpuid)
+
+Because previous mentioned OSs may not engage corresponding
+syscall target-registers (STAR, LSTAR, CSTAR), they remain
+NULL and (non trapping) syscalls are leading to multiple
+faults and finally crashs.
+
+Depending on the architecture (AMD or Intel) pretended by
+guests, various checks according to vendor's documentation
+are implemented to overcome the current issue and behave
+like the CPUs physical counterparts.
+
+[mtosatti: cleanup/beautify code]
+
+Signed-off-by: Stephan Baerwolf <stephan.baerwolf@tu-ilmenau.de>
+Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
+Signed-off-by: Stefan Bader <stefan.bader@canonical.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ arch/x86/include/asm/kvm_emulate.h |   13 +++++++++
+ arch/x86/kvm/emulate.c             |   51 +++++++++++++++++++++++++++++++++++++
+ 2 files changed, 64 insertions(+)
+
+--- a/arch/x86/include/asm/kvm_emulate.h
++++ b/arch/x86/include/asm/kvm_emulate.h
+@@ -301,6 +301,19 @@ struct x86_emulate_ctxt {
+ #define X86EMUL_MODE_PROT     (X86EMUL_MODE_PROT16|X86EMUL_MODE_PROT32| \
+                              X86EMUL_MODE_PROT64)
++/* CPUID vendors */
++#define X86EMUL_CPUID_VENDOR_AuthenticAMD_ebx 0x68747541
++#define X86EMUL_CPUID_VENDOR_AuthenticAMD_ecx 0x444d4163
++#define X86EMUL_CPUID_VENDOR_AuthenticAMD_edx 0x69746e65
++
++#define X86EMUL_CPUID_VENDOR_AMDisbetterI_ebx 0x69444d41
++#define X86EMUL_CPUID_VENDOR_AMDisbetterI_ecx 0x21726574
++#define X86EMUL_CPUID_VENDOR_AMDisbetterI_edx 0x74656273
++
++#define X86EMUL_CPUID_VENDOR_GenuineIntel_ebx 0x756e6547
++#define X86EMUL_CPUID_VENDOR_GenuineIntel_ecx 0x6c65746e
++#define X86EMUL_CPUID_VENDOR_GenuineIntel_edx 0x49656e69
++
+ enum x86_intercept_stage {
+       X86_ICTP_NONE = 0,   /* Allow zero-init to not match anything */
+       X86_ICPT_PRE_EXCEPT,
+--- a/arch/x86/kvm/emulate.c
++++ b/arch/x86/kvm/emulate.c
+@@ -1901,6 +1901,51 @@ setup_syscalls_segments(struct x86_emula
+       ss->p = 1;
+ }
++static bool em_syscall_is_enabled(struct x86_emulate_ctxt *ctxt)
++{
++      struct x86_emulate_ops *ops = ctxt->ops;
++      u32 eax, ebx, ecx, edx;
++
++      /*
++       * syscall should always be enabled in longmode - so only become
++       * vendor specific (cpuid) if other modes are active...
++       */
++      if (ctxt->mode == X86EMUL_MODE_PROT64)
++              return true;
++
++      eax = 0x00000000;
++      ecx = 0x00000000;
++      if (ops->get_cpuid(ctxt, &eax, &ebx, &ecx, &edx)) {
++              /*
++               * Intel ("GenuineIntel")
++               * remark: Intel CPUs only support "syscall" in 64bit
++               * longmode. Also an 64bit guest with a
++               * 32bit compat-app running will #UD !! While this
++               * behaviour can be fixed (by emulating) into AMD
++               * response - CPUs of AMD can't behave like Intel.
++               */
++              if (ebx == X86EMUL_CPUID_VENDOR_GenuineIntel_ebx &&
++                  ecx == X86EMUL_CPUID_VENDOR_GenuineIntel_ecx &&
++                  edx == X86EMUL_CPUID_VENDOR_GenuineIntel_edx)
++                      return false;
++
++              /* AMD ("AuthenticAMD") */
++              if (ebx == X86EMUL_CPUID_VENDOR_AuthenticAMD_ebx &&
++                  ecx == X86EMUL_CPUID_VENDOR_AuthenticAMD_ecx &&
++                  edx == X86EMUL_CPUID_VENDOR_AuthenticAMD_edx)
++                      return true;
++
++              /* AMD ("AMDisbetter!") */
++              if (ebx == X86EMUL_CPUID_VENDOR_AMDisbetterI_ebx &&
++                  ecx == X86EMUL_CPUID_VENDOR_AMDisbetterI_ecx &&
++                  edx == X86EMUL_CPUID_VENDOR_AMDisbetterI_edx)
++                      return true;
++      }
++
++      /* default: (not Intel, not AMD), apply Intel's stricter rules... */
++      return false;
++}
++
+ static int
+ emulate_syscall(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops)
+ {
+@@ -1915,9 +1960,15 @@ emulate_syscall(struct x86_emulate_ctxt
+           ctxt->mode == X86EMUL_MODE_VM86)
+               return emulate_ud(ctxt);
++      if (!(em_syscall_is_enabled(ctxt)))
++              return emulate_ud(ctxt);
++
+       ops->get_msr(ctxt, MSR_EFER, &efer);
+       setup_syscalls_segments(ctxt, ops, &cs, &ss);
++      if (!(efer & EFER_SCE))
++              return emulate_ud(ctxt);
++
+       ops->get_msr(ctxt, MSR_STAR, &msr_data);
+       msr_data >>= 32;
+       cs_sel = (u16)(msr_data & 0xfffc);
index 09d5c2a25dbc31a1d1f1f07833569a3763452940..807f00f37d93f1db699588d5080e3566a27e32a5 100644 (file)
@@ -62,3 +62,5 @@ ahci-move-ahci_hflags-macro-to-ahci.h.patch
 pata_legacy-correctly-mask-recovery-field-for-ht6560b.patch
 firewire-ohci-fix-too-early-completion-of-ir-multichannel-buffers.patch
 video-uvesafb-fix-oops-that-uvesafb-try-to-execute-nx-protected-page.patch
+kvm-x86-extend-struct-x86_emulate_ops-with-get_cpuid.patch
+kvm-x86-fix-missing-checks-in-syscall-emulation.patch