Hardware support for faulting on the cpuid instruction is not required to emulate it, because cpuid triggers a VM exit anyways. KVM handles the relevant MSRs (MSR_PLATFORM_INFO and MSR_MISC_FEATURES_ENABLE) and upon a cpuid-induced VM exit checks the cpuid faulting state and the CPL. kvm_require_cpl is even kind enough to inject the GP fault for us.
Unified · Split
| @@ -611,6 +611,8 @@ struct kvm_vcpu_arch { · 610 unmodified lines | |||
| 611 | unsigned long dr7; | 611 | unsigned long dr7; |
| 612 | unsigned long eff_db[KVM_NR_DB_REGS]; | 612 | unsigned long eff_db[KVM_NR_DB_REGS]; |
| 613 | unsigned long guest_debug_dr7; | 613 | unsigned long guest_debug_dr7; |
| 614 | u64 msr_platform_info; | ||
| 615 | u64 msr_misc_features_enables; | ||
| 614 | 616 | ||
| 615 | u64 mcg_cap; | 617 | u64 mcg_cap; |
| 616 | u64 mcg_status; | 618 | u64 mcg_status; |
| @@ -876,6 +876,9 @@ int kvm_emulate_cpuid(struct kvm_vcpu *vcpu) · 875 unmodified lines | |||
| 876 | { | 876 | { |
| 877 | u32 eax, ebx, ecx, edx; | 877 | u32 eax, ebx, ecx, edx; |
| 878 | 878 | ||
| 879 | if (cpuid_fault_enabled(vcpu) && !kvm_require_cpl(vcpu, 0)) | ||
| 880 | return 1; | ||
| 881 | |||
| 879 | eax = kvm_register_read(vcpu, VCPU_REGS_RAX); | 882 | eax = kvm_register_read(vcpu, VCPU_REGS_RAX); |
| 880 | ecx = kvm_register_read(vcpu, VCPU_REGS_RCX); | 883 | ecx = kvm_register_read(vcpu, VCPU_REGS_RCX); |
| 881 | kvm_cpuid(vcpu, &eax, &ebx, &ecx, &edx); | 884 | kvm_cpuid(vcpu, &eax, &ebx, &ecx, &edx); |
| @@ -205,4 +205,15 @@ static inline int guest_cpuid_stepping(struct kvm_vcpu *vcpu) · 204 unmodified lines | |||
| 205 | return x86_stepping(best->eax); | 205 | return x86_stepping(best->eax); |
| 206 | } | 206 | } |
| 207 | 207 | ||
| 208 | static inline bool supports_cpuid_fault(struct kvm_vcpu *vcpu) | ||
| 209 | { | ||
| 210 | return vcpu->arch.msr_platform_info & MSR_PLATFORM_INFO_CPUID_FAULT; | ||
| 211 | } | ||
| 212 | |||
| 213 | static inline bool cpuid_fault_enabled(struct kvm_vcpu *vcpu) | ||
| 214 | { | ||
| 215 | return vcpu->arch.msr_misc_features_enables & | ||
| 216 | MSR_MISC_FEATURES_ENABLES_CPUID_FAULT; | ||
| 217 | } | ||
| 218 | |||
| 208 | #endif | 219 | #endif |
| @@ -3854,6 +3854,13 @@ static int em_sti(struct x86_emulate_ctxt *ctxt) · 3853 unmodified lines | |||
| 3854 | static int em_cpuid(struct x86_emulate_ctxt *ctxt) | 3854 | static int em_cpuid(struct x86_emulate_ctxt *ctxt) |
| 3855 | { | 3855 | { |
| 3856 | u32 eax, ebx, ecx, edx; | 3856 | u32 eax, ebx, ecx, edx; |
| 3857 | u64 msr = 0; | ||
| 3858 | |||
| 3859 | ctxt->ops->get_msr(ctxt, MSR_MISC_FEATURES_ENABLES, &msr); | ||
| 3860 | if (msr & MSR_MISC_FEATURES_ENABLES_CPUID_FAULT && | ||
| 3861 | ctxt->ops->cpl(ctxt)) { | ||
| 3862 | return emulate_gp(ctxt, 0); | ||
| 3863 | } | ||
| 3857 | 3864 | ||
| 3858 | eax = reg_read(ctxt, VCPU_REGS_RAX); | 3865 | eax = reg_read(ctxt, VCPU_REGS_RAX); |
| 3859 | ecx = reg_read(ctxt, VCPU_REGS_RCX); | 3866 | ecx = reg_read(ctxt, VCPU_REGS_RCX); |
| @@ -1007,6 +1007,8 @@ static u32 emulated_msrs[] = { · 1006 unmodified lines | |||
| 1007 | MSR_IA32_MCG_CTL, | 1007 | MSR_IA32_MCG_CTL, |
| 1008 | MSR_IA32_MCG_EXT_CTL, | 1008 | MSR_IA32_MCG_EXT_CTL, |
| 1009 | MSR_IA32_SMBASE, | 1009 | MSR_IA32_SMBASE, |
| 1010 | MSR_PLATFORM_INFO, | ||
| 1011 | MSR_MISC_FEATURES_ENABLES, | ||
| 1010 | }; | 1012 | }; |
| 1011 | 1013 | ||
| 1012 | static unsigned num_emulated_msrs; | 1014 | static unsigned num_emulated_msrs; |
| @@ -2314,6 +2316,21 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info) · 1301 unmodified lines | |||
| 2314 | return 1; | 2316 | return 1; |
| 2315 | vcpu->arch.osvw.status = data; | 2317 | vcpu->arch.osvw.status = data; |
| 2316 | break; | 2318 | break; |
| 2319 | case MSR_PLATFORM_INFO: | ||
| 2320 | if (!msr_info->host_initiated || | ||
| 2321 | data & ~MSR_PLATFORM_INFO_CPUID_FAULT || | ||
| 2322 | (!(data & MSR_PLATFORM_INFO_CPUID_FAULT) && | ||
| 2323 | cpuid_fault_enabled(vcpu))) | ||
| 2324 | return 1; | ||
| 2325 | vcpu->arch.msr_platform_info = data; | ||
| 2326 | break; | ||
| 2327 | case MSR_MISC_FEATURES_ENABLES: | ||
| 2328 | if (data & ~MSR_MISC_FEATURES_ENABLES_CPUID_FAULT || | ||
| 2329 | (data & MSR_MISC_FEATURES_ENABLES_CPUID_FAULT && | ||
| 2330 | !supports_cpuid_fault(vcpu))) | ||
| 2331 | return 1; | ||
| 2332 | vcpu->arch.msr_misc_features_enables = data; | ||
| 2333 | break; | ||
| 2317 | default: | 2334 | default: |
| 2318 | if (msr && (msr == vcpu->kvm->arch.xen_hvm_config.msr)) | 2335 | if (msr && (msr == vcpu->kvm->arch.xen_hvm_config.msr)) |
| 2319 | return xen_hvm_config(vcpu, data); | 2336 | return xen_hvm_config(vcpu, data); |
| @@ -2529,6 +2546,12 @@ int kvm_get_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info) · 209 unmodified lines | |||
| 2529 | return 1; | 2546 | return 1; |
| 2530 | msr_info->data = vcpu->arch.osvw.status; | 2547 | msr_info->data = vcpu->arch.osvw.status; |
| 2531 | break; | 2548 | break; |
| 2549 | case MSR_PLATFORM_INFO: | ||
| 2550 | msr_info->data = vcpu->arch.msr_platform_info; | ||
| 2551 | break; | ||
| 2552 | case MSR_MISC_FEATURES_ENABLES: | ||
| 2553 | msr_info->data = vcpu->arch.msr_misc_features_enables; | ||
| 2554 | break; | ||
| 2532 | default: | 2555 | default: |
| 2533 | if (kvm_pmu_is_valid_msr(vcpu, msr_info->index)) | 2556 | if (kvm_pmu_is_valid_msr(vcpu, msr_info->index)) |
| 2534 | return kvm_pmu_get_msr(vcpu, msr_info->index, &msr_info->data); | 2557 | return kvm_pmu_get_msr(vcpu, msr_info->index, &msr_info->data); |
| @@ -7710,6 +7733,9 @@ void kvm_vcpu_reset(struct kvm_vcpu *vcpu, bool init_event) · 5175 unmodified lines | |||
| 7710 | if (!init_event) { | 7733 | if (!init_event) { |
| 7711 | kvm_pmu_reset(vcpu); | 7734 | kvm_pmu_reset(vcpu); |
| 7712 | vcpu->arch.smbase = 0x30000; | 7735 | vcpu->arch.smbase = 0x30000; |
| 7736 | |||
| 7737 | vcpu->arch.msr_platform_info = MSR_PLATFORM_INFO_CPUID_FAULT; | ||
| 7738 | vcpu->arch.msr_misc_features_enables = 0; | ||
| 7713 | } | 7739 | } |
| 7714 | 7740 | ||
| 7715 | memset(vcpu->arch.regs, 0, sizeof(vcpu->arch.regs)); | 7741 | memset(vcpu->arch.regs, 0, sizeof(vcpu->arch.regs)); |