KVM: x86 emulator: change ->get_cpuid() accessor to use the x86 semantics
authorAvi Kivity <avi@redhat.com>
Thu, 7 Jun 2012 11:10:16 +0000 (14:10 +0300)
committerAvi Kivity <avi@redhat.com>
Mon, 9 Jul 2012 11:19:00 +0000 (14:19 +0300)
Instead of getting an exact leaf, follow the spec and fall back to the last
main leaf instead.  This lets us easily emulate the cpuid instruction in the
emulator.

Signed-off-by: Avi Kivity <avi@redhat.com>
arch/x86/include/asm/kvm_emulate.h
arch/x86/kvm/emulate.c
arch/x86/kvm/x86.c

index 1ac46c22dd5003d90fd253497be9378d8fd3da8a..cd5c96b2496e726c429ea0d27b27540934a91aef 100644 (file)
@@ -192,8 +192,8 @@ struct x86_emulate_ops {
                         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);
+       void (*get_cpuid)(struct x86_emulate_ctxt *ctxt,
+                         u32 *eax, u32 *ebx, u32 *ecx, u32 *edx);
 };
 
 typedef u32 __attribute__((vector_size(16))) sse128_t;
index f95d242ee9f72a8f30bf912cf81dd172745dadd9..ba1f8ecaab52c447e3bccd5ebc2cf44ecab7eda0 100644 (file)
@@ -1993,8 +1993,8 @@ static bool vendor_intel(struct x86_emulate_ctxt *ctxt)
        u32 eax, ebx, ecx, edx;
 
        eax = ecx = 0;
-       return ctxt->ops->get_cpuid(ctxt, &eax, &ebx, &ecx, &edx)
-               && ebx == X86EMUL_CPUID_VENDOR_GenuineIntel_ebx
+       ctxt->ops->get_cpuid(ctxt, &eax, &ebx, &ecx, &edx);
+       return ebx == X86EMUL_CPUID_VENDOR_GenuineIntel_ebx
                && ecx == X86EMUL_CPUID_VENDOR_GenuineIntel_ecx
                && edx == X86EMUL_CPUID_VENDOR_GenuineIntel_edx;
 }
@@ -2013,32 +2013,31 @@ static bool em_syscall_is_enabled(struct x86_emulate_ctxt *ctxt)
 
        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;
+       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;
-       }
+       /* 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;
index 8eacb2e645608ee79ca9826072c68929888b9d96..ff0b487e725400fc939321498853ebe45200c9d2 100644 (file)
@@ -4302,26 +4302,10 @@ static int emulator_intercept(struct x86_emulate_ctxt *ctxt,
        return kvm_x86_ops->check_intercept(emul_to_vcpu(ctxt), info, stage);
 }
 
-static bool emulator_get_cpuid(struct x86_emulate_ctxt *ctxt,
+static void 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;
+       kvm_cpuid(emul_to_vcpu(ctxt), eax, ebx, ecx, edx);
 }
 
 static struct x86_emulate_ops emulate_ops = {