aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorAvi Kivity <avi@redhat.com>2012-06-07 07:10:16 -0400
committerAvi Kivity <avi@redhat.com>2012-07-09 07:19:00 -0400
commit0017f93a2776597b798ec1a9594e41dfd96d3c11 (patch)
treeef0a1e1a409f6d9a5d48894b0256a723c1b1183b /arch
parent62046e5a867cbff35e0beff42718dda41ff5d74b (diff)
KVM: x86 emulator: change ->get_cpuid() accessor to use the x86 semantics
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>
Diffstat (limited to 'arch')
-rw-r--r--arch/x86/include/asm/kvm_emulate.h4
-rw-r--r--arch/x86/kvm/emulate.c53
-rw-r--r--arch/x86/kvm/x86.c20
3 files changed, 30 insertions, 47 deletions
diff --git a/arch/x86/include/asm/kvm_emulate.h b/arch/x86/include/asm/kvm_emulate.h
index 1ac46c22dd50..cd5c96b2496e 100644
--- a/arch/x86/include/asm/kvm_emulate.h
+++ b/arch/x86/include/asm/kvm_emulate.h
@@ -192,8 +192,8 @@ struct x86_emulate_ops {
192 struct x86_instruction_info *info, 192 struct x86_instruction_info *info,
193 enum x86_intercept_stage stage); 193 enum x86_intercept_stage stage);
194 194
195 bool (*get_cpuid)(struct x86_emulate_ctxt *ctxt, 195 void (*get_cpuid)(struct x86_emulate_ctxt *ctxt,
196 u32 *eax, u32 *ebx, u32 *ecx, u32 *edx); 196 u32 *eax, u32 *ebx, u32 *ecx, u32 *edx);
197}; 197};
198 198
199typedef u32 __attribute__((vector_size(16))) sse128_t; 199typedef u32 __attribute__((vector_size(16))) sse128_t;
diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c
index f95d242ee9f7..ba1f8ecaab52 100644
--- a/arch/x86/kvm/emulate.c
+++ b/arch/x86/kvm/emulate.c
@@ -1993,8 +1993,8 @@ static bool vendor_intel(struct x86_emulate_ctxt *ctxt)
1993 u32 eax, ebx, ecx, edx; 1993 u32 eax, ebx, ecx, edx;
1994 1994
1995 eax = ecx = 0; 1995 eax = ecx = 0;
1996 return ctxt->ops->get_cpuid(ctxt, &eax, &ebx, &ecx, &edx) 1996 ctxt->ops->get_cpuid(ctxt, &eax, &ebx, &ecx, &edx);
1997 && ebx == X86EMUL_CPUID_VENDOR_GenuineIntel_ebx 1997 return ebx == X86EMUL_CPUID_VENDOR_GenuineIntel_ebx
1998 && ecx == X86EMUL_CPUID_VENDOR_GenuineIntel_ecx 1998 && ecx == X86EMUL_CPUID_VENDOR_GenuineIntel_ecx
1999 && edx == X86EMUL_CPUID_VENDOR_GenuineIntel_edx; 1999 && edx == X86EMUL_CPUID_VENDOR_GenuineIntel_edx;
2000} 2000}
@@ -2013,32 +2013,31 @@ static bool em_syscall_is_enabled(struct x86_emulate_ctxt *ctxt)
2013 2013
2014 eax = 0x00000000; 2014 eax = 0x00000000;
2015 ecx = 0x00000000; 2015 ecx = 0x00000000;
2016 if (ops->get_cpuid(ctxt, &eax, &ebx, &ecx, &edx)) { 2016 ops->get_cpuid(ctxt, &eax, &ebx, &ecx, &edx);
2017 /* 2017 /*
2018 * Intel ("GenuineIntel") 2018 * Intel ("GenuineIntel")
2019 * remark: Intel CPUs only support "syscall" in 64bit 2019 * remark: Intel CPUs only support "syscall" in 64bit
2020 * longmode. Also an 64bit guest with a 2020 * longmode. Also an 64bit guest with a
2021 * 32bit compat-app running will #UD !! While this 2021 * 32bit compat-app running will #UD !! While this
2022 * behaviour can be fixed (by emulating) into AMD 2022 * behaviour can be fixed (by emulating) into AMD
2023 * response - CPUs of AMD can't behave like Intel. 2023 * response - CPUs of AMD can't behave like Intel.
2024 */ 2024 */
2025 if (ebx == X86EMUL_CPUID_VENDOR_GenuineIntel_ebx && 2025 if (ebx == X86EMUL_CPUID_VENDOR_GenuineIntel_ebx &&
2026 ecx == X86EMUL_CPUID_VENDOR_GenuineIntel_ecx && 2026 ecx == X86EMUL_CPUID_VENDOR_GenuineIntel_ecx &&
2027 edx == X86EMUL_CPUID_VENDOR_GenuineIntel_edx) 2027 edx == X86EMUL_CPUID_VENDOR_GenuineIntel_edx)
2028 return false; 2028 return false;
2029 2029
2030 /* AMD ("AuthenticAMD") */ 2030 /* AMD ("AuthenticAMD") */
2031 if (ebx == X86EMUL_CPUID_VENDOR_AuthenticAMD_ebx && 2031 if (ebx == X86EMUL_CPUID_VENDOR_AuthenticAMD_ebx &&
2032 ecx == X86EMUL_CPUID_VENDOR_AuthenticAMD_ecx && 2032 ecx == X86EMUL_CPUID_VENDOR_AuthenticAMD_ecx &&
2033 edx == X86EMUL_CPUID_VENDOR_AuthenticAMD_edx) 2033 edx == X86EMUL_CPUID_VENDOR_AuthenticAMD_edx)
2034 return true; 2034 return true;
2035 2035
2036 /* AMD ("AMDisbetter!") */ 2036 /* AMD ("AMDisbetter!") */
2037 if (ebx == X86EMUL_CPUID_VENDOR_AMDisbetterI_ebx && 2037 if (ebx == X86EMUL_CPUID_VENDOR_AMDisbetterI_ebx &&
2038 ecx == X86EMUL_CPUID_VENDOR_AMDisbetterI_ecx && 2038 ecx == X86EMUL_CPUID_VENDOR_AMDisbetterI_ecx &&
2039 edx == X86EMUL_CPUID_VENDOR_AMDisbetterI_edx) 2039 edx == X86EMUL_CPUID_VENDOR_AMDisbetterI_edx)
2040 return true; 2040 return true;
2041 }
2042 2041
2043 /* default: (not Intel, not AMD), apply Intel's stricter rules... */ 2042 /* default: (not Intel, not AMD), apply Intel's stricter rules... */
2044 return false; 2043 return false;
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 8eacb2e64560..ff0b487e7254 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -4302,26 +4302,10 @@ static int emulator_intercept(struct x86_emulate_ctxt *ctxt,
4302 return kvm_x86_ops->check_intercept(emul_to_vcpu(ctxt), info, stage); 4302 return kvm_x86_ops->check_intercept(emul_to_vcpu(ctxt), info, stage);
4303} 4303}
4304 4304
4305static bool emulator_get_cpuid(struct x86_emulate_ctxt *ctxt, 4305static void emulator_get_cpuid(struct x86_emulate_ctxt *ctxt,
4306 u32 *eax, u32 *ebx, u32 *ecx, u32 *edx) 4306 u32 *eax, u32 *ebx, u32 *ecx, u32 *edx)
4307{ 4307{
4308 struct kvm_cpuid_entry2 *cpuid = NULL; 4308 kvm_cpuid(emul_to_vcpu(ctxt), eax, ebx, ecx, edx);
4309
4310 if (eax && ecx)
4311 cpuid = kvm_find_cpuid_entry(emul_to_vcpu(ctxt),
4312 *eax, *ecx);
4313
4314 if (cpuid) {
4315 *eax = cpuid->eax;
4316 *ecx = cpuid->ecx;
4317 if (ebx)
4318 *ebx = cpuid->ebx;
4319 if (edx)
4320 *edx = cpuid->edx;
4321 return true;
4322 }
4323
4324 return false;
4325} 4309}
4326 4310
4327static struct x86_emulate_ops emulate_ops = { 4311static struct x86_emulate_ops emulate_ops = {