diff options
Diffstat (limited to 'arch/x86/kvm/cpuid.c')
-rw-r--r-- | arch/x86/kvm/cpuid.c | 46 |
1 files changed, 26 insertions, 20 deletions
diff --git a/arch/x86/kvm/cpuid.c b/arch/x86/kvm/cpuid.c index 7df1c6d839fb..0595f1397b7c 100644 --- a/arch/x86/kvm/cpuid.c +++ b/arch/x86/kvm/cpuid.c | |||
@@ -201,6 +201,7 @@ static int do_cpuid_ent(struct kvm_cpuid_entry2 *entry, u32 function, | |||
201 | unsigned f_lm = 0; | 201 | unsigned f_lm = 0; |
202 | #endif | 202 | #endif |
203 | unsigned f_rdtscp = kvm_x86_ops->rdtscp_supported() ? F(RDTSCP) : 0; | 203 | unsigned f_rdtscp = kvm_x86_ops->rdtscp_supported() ? F(RDTSCP) : 0; |
204 | unsigned f_invpcid = kvm_x86_ops->invpcid_supported() ? F(INVPCID) : 0; | ||
204 | 205 | ||
205 | /* cpuid 1.edx */ | 206 | /* cpuid 1.edx */ |
206 | const u32 kvm_supported_word0_x86_features = | 207 | const u32 kvm_supported_word0_x86_features = |
@@ -228,7 +229,7 @@ static int do_cpuid_ent(struct kvm_cpuid_entry2 *entry, u32 function, | |||
228 | 0 /* DS-CPL, VMX, SMX, EST */ | | 229 | 0 /* DS-CPL, VMX, SMX, EST */ | |
229 | 0 /* TM2 */ | F(SSSE3) | 0 /* CNXT-ID */ | 0 /* Reserved */ | | 230 | 0 /* TM2 */ | F(SSSE3) | 0 /* CNXT-ID */ | 0 /* Reserved */ | |
230 | F(FMA) | F(CX16) | 0 /* xTPR Update, PDCM */ | | 231 | F(FMA) | F(CX16) | 0 /* xTPR Update, PDCM */ | |
231 | 0 /* Reserved, DCA */ | F(XMM4_1) | | 232 | F(PCID) | 0 /* Reserved, DCA */ | F(XMM4_1) | |
232 | F(XMM4_2) | F(X2APIC) | F(MOVBE) | F(POPCNT) | | 233 | F(XMM4_2) | F(X2APIC) | F(MOVBE) | F(POPCNT) | |
233 | 0 /* Reserved*/ | F(AES) | F(XSAVE) | 0 /* OSXSAVE */ | F(AVX) | | 234 | 0 /* Reserved*/ | F(AES) | F(XSAVE) | 0 /* OSXSAVE */ | F(AVX) | |
234 | F(F16C) | F(RDRAND); | 235 | F(F16C) | F(RDRAND); |
@@ -248,7 +249,7 @@ static int do_cpuid_ent(struct kvm_cpuid_entry2 *entry, u32 function, | |||
248 | /* cpuid 7.0.ebx */ | 249 | /* cpuid 7.0.ebx */ |
249 | const u32 kvm_supported_word9_x86_features = | 250 | const u32 kvm_supported_word9_x86_features = |
250 | F(FSGSBASE) | F(BMI1) | F(HLE) | F(AVX2) | F(SMEP) | | 251 | F(FSGSBASE) | F(BMI1) | F(HLE) | F(AVX2) | F(SMEP) | |
251 | F(BMI2) | F(ERMS) | F(RTM); | 252 | F(BMI2) | F(ERMS) | f_invpcid | F(RTM); |
252 | 253 | ||
253 | /* all calls to cpuid_count() should be made on the same cpu */ | 254 | /* all calls to cpuid_count() should be made on the same cpu */ |
254 | get_cpu(); | 255 | get_cpu(); |
@@ -409,6 +410,7 @@ static int do_cpuid_ent(struct kvm_cpuid_entry2 *entry, u32 function, | |||
409 | (1 << KVM_FEATURE_NOP_IO_DELAY) | | 410 | (1 << KVM_FEATURE_NOP_IO_DELAY) | |
410 | (1 << KVM_FEATURE_CLOCKSOURCE2) | | 411 | (1 << KVM_FEATURE_CLOCKSOURCE2) | |
411 | (1 << KVM_FEATURE_ASYNC_PF) | | 412 | (1 << KVM_FEATURE_ASYNC_PF) | |
413 | (1 << KVM_FEATURE_PV_EOI) | | ||
412 | (1 << KVM_FEATURE_CLOCKSOURCE_STABLE_BIT); | 414 | (1 << KVM_FEATURE_CLOCKSOURCE_STABLE_BIT); |
413 | 415 | ||
414 | if (sched_info_on()) | 416 | if (sched_info_on()) |
@@ -639,33 +641,37 @@ static struct kvm_cpuid_entry2* check_cpuid_limit(struct kvm_vcpu *vcpu, | |||
639 | return kvm_find_cpuid_entry(vcpu, maxlevel->eax, index); | 641 | return kvm_find_cpuid_entry(vcpu, maxlevel->eax, index); |
640 | } | 642 | } |
641 | 643 | ||
642 | void kvm_emulate_cpuid(struct kvm_vcpu *vcpu) | 644 | void kvm_cpuid(struct kvm_vcpu *vcpu, u32 *eax, u32 *ebx, u32 *ecx, u32 *edx) |
643 | { | 645 | { |
644 | u32 function, index; | 646 | u32 function = *eax, index = *ecx; |
645 | struct kvm_cpuid_entry2 *best; | 647 | struct kvm_cpuid_entry2 *best; |
646 | 648 | ||
647 | function = kvm_register_read(vcpu, VCPU_REGS_RAX); | ||
648 | index = kvm_register_read(vcpu, VCPU_REGS_RCX); | ||
649 | kvm_register_write(vcpu, VCPU_REGS_RAX, 0); | ||
650 | kvm_register_write(vcpu, VCPU_REGS_RBX, 0); | ||
651 | kvm_register_write(vcpu, VCPU_REGS_RCX, 0); | ||
652 | kvm_register_write(vcpu, VCPU_REGS_RDX, 0); | ||
653 | best = kvm_find_cpuid_entry(vcpu, function, index); | 649 | best = kvm_find_cpuid_entry(vcpu, function, index); |
654 | 650 | ||
655 | if (!best) | 651 | if (!best) |
656 | best = check_cpuid_limit(vcpu, function, index); | 652 | best = check_cpuid_limit(vcpu, function, index); |
657 | 653 | ||
658 | if (best) { | 654 | if (best) { |
659 | kvm_register_write(vcpu, VCPU_REGS_RAX, best->eax); | 655 | *eax = best->eax; |
660 | kvm_register_write(vcpu, VCPU_REGS_RBX, best->ebx); | 656 | *ebx = best->ebx; |
661 | kvm_register_write(vcpu, VCPU_REGS_RCX, best->ecx); | 657 | *ecx = best->ecx; |
662 | kvm_register_write(vcpu, VCPU_REGS_RDX, best->edx); | 658 | *edx = best->edx; |
663 | } | 659 | } else |
660 | *eax = *ebx = *ecx = *edx = 0; | ||
661 | } | ||
662 | |||
663 | void kvm_emulate_cpuid(struct kvm_vcpu *vcpu) | ||
664 | { | ||
665 | u32 function, eax, ebx, ecx, edx; | ||
666 | |||
667 | function = eax = kvm_register_read(vcpu, VCPU_REGS_RAX); | ||
668 | ecx = kvm_register_read(vcpu, VCPU_REGS_RCX); | ||
669 | kvm_cpuid(vcpu, &eax, &ebx, &ecx, &edx); | ||
670 | kvm_register_write(vcpu, VCPU_REGS_RAX, eax); | ||
671 | kvm_register_write(vcpu, VCPU_REGS_RBX, ebx); | ||
672 | kvm_register_write(vcpu, VCPU_REGS_RCX, ecx); | ||
673 | kvm_register_write(vcpu, VCPU_REGS_RDX, edx); | ||
664 | kvm_x86_ops->skip_emulated_instruction(vcpu); | 674 | kvm_x86_ops->skip_emulated_instruction(vcpu); |
665 | trace_kvm_cpuid(function, | 675 | trace_kvm_cpuid(function, eax, ebx, ecx, edx); |
666 | kvm_register_read(vcpu, VCPU_REGS_RAX), | ||
667 | kvm_register_read(vcpu, VCPU_REGS_RBX), | ||
668 | kvm_register_read(vcpu, VCPU_REGS_RCX), | ||
669 | kvm_register_read(vcpu, VCPU_REGS_RDX)); | ||
670 | } | 676 | } |
671 | EXPORT_SYMBOL_GPL(kvm_emulate_cpuid); | 677 | EXPORT_SYMBOL_GPL(kvm_emulate_cpuid); |