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>
This commit is contained in:
Родитель
62046e5a86
Коммит
0017f93a27
|
@ -192,7 +192,7 @@ struct x86_emulate_ops {
|
||||||
struct x86_instruction_info *info,
|
struct x86_instruction_info *info,
|
||||||
enum x86_intercept_stage stage);
|
enum x86_intercept_stage stage);
|
||||||
|
|
||||||
bool (*get_cpuid)(struct x86_emulate_ctxt *ctxt,
|
void (*get_cpuid)(struct x86_emulate_ctxt *ctxt,
|
||||||
u32 *eax, u32 *ebx, u32 *ecx, u32 *edx);
|
u32 *eax, u32 *ebx, u32 *ecx, u32 *edx);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1993,8 +1993,8 @@ static bool vendor_intel(struct x86_emulate_ctxt *ctxt)
|
||||||
u32 eax, ebx, ecx, edx;
|
u32 eax, ebx, ecx, edx;
|
||||||
|
|
||||||
eax = ecx = 0;
|
eax = ecx = 0;
|
||||||
return ctxt->ops->get_cpuid(ctxt, &eax, &ebx, &ecx, &edx)
|
ctxt->ops->get_cpuid(ctxt, &eax, &ebx, &ecx, &edx);
|
||||||
&& ebx == X86EMUL_CPUID_VENDOR_GenuineIntel_ebx
|
return ebx == X86EMUL_CPUID_VENDOR_GenuineIntel_ebx
|
||||||
&& ecx == X86EMUL_CPUID_VENDOR_GenuineIntel_ecx
|
&& ecx == X86EMUL_CPUID_VENDOR_GenuineIntel_ecx
|
||||||
&& edx == X86EMUL_CPUID_VENDOR_GenuineIntel_edx;
|
&& edx == X86EMUL_CPUID_VENDOR_GenuineIntel_edx;
|
||||||
}
|
}
|
||||||
|
@ -2013,7 +2013,7 @@ static bool em_syscall_is_enabled(struct x86_emulate_ctxt *ctxt)
|
||||||
|
|
||||||
eax = 0x00000000;
|
eax = 0x00000000;
|
||||||
ecx = 0x00000000;
|
ecx = 0x00000000;
|
||||||
if (ops->get_cpuid(ctxt, &eax, &ebx, &ecx, &edx)) {
|
ops->get_cpuid(ctxt, &eax, &ebx, &ecx, &edx);
|
||||||
/*
|
/*
|
||||||
* Intel ("GenuineIntel")
|
* Intel ("GenuineIntel")
|
||||||
* remark: Intel CPUs only support "syscall" in 64bit
|
* remark: Intel CPUs only support "syscall" in 64bit
|
||||||
|
@ -2038,7 +2038,6 @@ static bool em_syscall_is_enabled(struct x86_emulate_ctxt *ctxt)
|
||||||
ecx == X86EMUL_CPUID_VENDOR_AMDisbetterI_ecx &&
|
ecx == X86EMUL_CPUID_VENDOR_AMDisbetterI_ecx &&
|
||||||
edx == X86EMUL_CPUID_VENDOR_AMDisbetterI_edx)
|
edx == X86EMUL_CPUID_VENDOR_AMDisbetterI_edx)
|
||||||
return true;
|
return true;
|
||||||
}
|
|
||||||
|
|
||||||
/* default: (not Intel, not AMD), apply Intel's stricter rules... */
|
/* default: (not Intel, not AMD), apply Intel's stricter rules... */
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -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);
|
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)
|
u32 *eax, u32 *ebx, u32 *ecx, u32 *edx)
|
||||||
{
|
{
|
||||||
struct kvm_cpuid_entry2 *cpuid = NULL;
|
kvm_cpuid(emul_to_vcpu(ctxt), eax, ebx, ecx, edx);
|
||||||
|
|
||||||
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 = {
|
static struct x86_emulate_ops emulate_ops = {
|
||||||
|
|
Загрузка…
Ссылка в новой задаче