KVM: x86: Add return value to kvm_cpuid().
authorYu Zhang <yu.c.zhang@linux.intel.com>
Thu, 24 Aug 2017 12:27:52 +0000 (20:27 +0800)
committerPaolo Bonzini <pbonzini@redhat.com>
Thu, 24 Aug 2017 16:09:15 +0000 (18:09 +0200)
Return false in kvm_cpuid() when it fails to find the cpuid
entry. Also, this routine(and its caller) is optimized with
a new argument - check_limit, so that the check_cpuid_limit()
fall back can be avoided.

Signed-off-by: Yu Zhang <yu.c.zhang@linux.intel.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
arch/x86/include/asm/kvm_emulate.h
arch/x86/kvm/cpuid.c
arch/x86/kvm/cpuid.h
arch/x86/kvm/emulate.c
arch/x86/kvm/svm.c
arch/x86/kvm/trace.h
arch/x86/kvm/x86.c

index fde36f189836db83af655652f44eec92820072b8..fa2558e120249e6c36e368e396d2c9e188c57056 100644 (file)
@@ -219,8 +219,8 @@ struct x86_emulate_ops {
                         struct x86_instruction_info *info,
                         enum x86_intercept_stage stage);
 
-       void (*get_cpuid)(struct x86_emulate_ctxt *ctxt,
-                         u32 *eax, u32 *ebx, u32 *ecx, u32 *edx);
+       bool (*get_cpuid)(struct x86_emulate_ctxt *ctxt, u32 *eax, u32 *ebx,
+                         u32 *ecx, u32 *edx, bool check_limit);
        void (*set_nmi_mask)(struct x86_emulate_ctxt *ctxt, bool masked);
 
        unsigned (*get_hflags)(struct x86_emulate_ctxt *ctxt);
index 59ca2eea522c466937287c3e660b8f38e49c12aa..14505473fb21c77ee43ad6ffbeb8bbfd2ae543e0 100644 (file)
@@ -853,16 +853,24 @@ static struct kvm_cpuid_entry2* check_cpuid_limit(struct kvm_vcpu *vcpu,
        return kvm_find_cpuid_entry(vcpu, maxlevel->eax, index);
 }
 
-void kvm_cpuid(struct kvm_vcpu *vcpu, u32 *eax, u32 *ebx, u32 *ecx, u32 *edx)
+bool kvm_cpuid(struct kvm_vcpu *vcpu, u32 *eax, u32 *ebx,
+              u32 *ecx, u32 *edx, bool check_limit)
 {
        u32 function = *eax, index = *ecx;
        struct kvm_cpuid_entry2 *best;
+       bool entry_found = true;
 
        best = kvm_find_cpuid_entry(vcpu, function, index);
 
-       if (!best)
+       if (!best) {
+               entry_found = false;
+               if (!check_limit)
+                       goto out;
+
                best = check_cpuid_limit(vcpu, function, index);
+       }
 
+out:
        if (best) {
                *eax = best->eax;
                *ebx = best->ebx;
@@ -870,7 +878,8 @@ void kvm_cpuid(struct kvm_vcpu *vcpu, u32 *eax, u32 *ebx, u32 *ecx, u32 *edx)
                *edx = best->edx;
        } else
                *eax = *ebx = *ecx = *edx = 0;
-       trace_kvm_cpuid(function, *eax, *ebx, *ecx, *edx);
+       trace_kvm_cpuid(function, *eax, *ebx, *ecx, *edx, entry_found);
+       return entry_found;
 }
 EXPORT_SYMBOL_GPL(kvm_cpuid);
 
@@ -883,7 +892,7 @@ int kvm_emulate_cpuid(struct kvm_vcpu *vcpu)
 
        eax = kvm_register_read(vcpu, VCPU_REGS_RAX);
        ecx = kvm_register_read(vcpu, VCPU_REGS_RCX);
-       kvm_cpuid(vcpu, &eax, &ebx, &ecx, &edx);
+       kvm_cpuid(vcpu, &eax, &ebx, &ecx, &edx, true);
        kvm_register_write(vcpu, VCPU_REGS_RAX, eax);
        kvm_register_write(vcpu, VCPU_REGS_RBX, ebx);
        kvm_register_write(vcpu, VCPU_REGS_RCX, ecx);
index ac15193e5e5275509bd2db6dd764701bbbfee881..1ea3c0e1e3a9a3df6d6061e1e367abf632c50b79 100644 (file)
@@ -21,7 +21,8 @@ int kvm_vcpu_ioctl_set_cpuid2(struct kvm_vcpu *vcpu,
 int kvm_vcpu_ioctl_get_cpuid2(struct kvm_vcpu *vcpu,
                              struct kvm_cpuid2 *cpuid,
                              struct kvm_cpuid_entry2 __user *entries);
-void kvm_cpuid(struct kvm_vcpu *vcpu, u32 *eax, u32 *ebx, u32 *ecx, u32 *edx);
+bool kvm_cpuid(struct kvm_vcpu *vcpu, u32 *eax, u32 *ebx,
+              u32 *ecx, u32 *edx, bool check_limit);
 
 int cpuid_query_maxphyaddr(struct kvm_vcpu *vcpu);
 
index fb0055953fbc9d6e6a3263e1d0bc4fc3ba900a8e..319d91f6f3c46bf45d41bbb10789d263ad0577ef 100644 (file)
@@ -2333,7 +2333,7 @@ static int emulator_has_longmode(struct x86_emulate_ctxt *ctxt)
 
        eax = 0x80000001;
        ecx = 0;
-       ctxt->ops->get_cpuid(ctxt, &eax, &ebx, &ecx, &edx);
+       ctxt->ops->get_cpuid(ctxt, &eax, &ebx, &ecx, &edx, false);
        return edx & bit(X86_FEATURE_LM);
 }
 
@@ -2636,7 +2636,7 @@ static bool vendor_intel(struct x86_emulate_ctxt *ctxt)
        u32 eax, ebx, ecx, edx;
 
        eax = ecx = 0;
-       ctxt->ops->get_cpuid(ctxt, &eax, &ebx, &ecx, &edx);
+       ctxt->ops->get_cpuid(ctxt, &eax, &ebx, &ecx, &edx, false);
        return ebx == X86EMUL_CPUID_VENDOR_GenuineIntel_ebx
                && ecx == X86EMUL_CPUID_VENDOR_GenuineIntel_ecx
                && edx == X86EMUL_CPUID_VENDOR_GenuineIntel_edx;
@@ -2656,7 +2656,7 @@ static bool em_syscall_is_enabled(struct x86_emulate_ctxt *ctxt)
 
        eax = 0x00000000;
        ecx = 0x00000000;
-       ops->get_cpuid(ctxt, &eax, &ebx, &ecx, &edx);
+       ops->get_cpuid(ctxt, &eax, &ebx, &ecx, &edx, false);
        /*
         * Intel ("GenuineIntel")
         * remark: Intel CPUs only support "syscall" in 64bit
@@ -3551,7 +3551,7 @@ static int em_movbe(struct x86_emulate_ctxt *ctxt)
        /*
         * Check MOVBE is set in the guest-visible CPUID leaf.
         */
-       ctxt->ops->get_cpuid(ctxt, &eax, &ebx, &ecx, &edx);
+       ctxt->ops->get_cpuid(ctxt, &eax, &ebx, &ecx, &edx, false);
        if (!(ecx & FFL(MOVBE)))
                return emulate_ud(ctxt);
 
@@ -3865,7 +3865,7 @@ static int em_cpuid(struct x86_emulate_ctxt *ctxt)
 
        eax = reg_read(ctxt, VCPU_REGS_RAX);
        ecx = reg_read(ctxt, VCPU_REGS_RCX);
-       ctxt->ops->get_cpuid(ctxt, &eax, &ebx, &ecx, &edx);
+       ctxt->ops->get_cpuid(ctxt, &eax, &ebx, &ecx, &edx, true);
        *reg_write(ctxt, VCPU_REGS_RAX) = eax;
        *reg_write(ctxt, VCPU_REGS_RBX) = ebx;
        *reg_write(ctxt, VCPU_REGS_RCX) = ecx;
@@ -3924,7 +3924,7 @@ static int check_fxsr(struct x86_emulate_ctxt *ctxt)
 {
        u32 eax = 1, ebx, ecx = 0, edx;
 
-       ctxt->ops->get_cpuid(ctxt, &eax, &ebx, &ecx, &edx);
+       ctxt->ops->get_cpuid(ctxt, &eax, &ebx, &ecx, &edx, false);
        if (!(edx & FFL(FXSR)))
                return emulate_ud(ctxt);
 
index 7e190b21a30b0ba58819e59ee039c42b94f14973..c5b9705186d6ce18596d4363f59577633b5667d0 100644 (file)
@@ -1593,7 +1593,7 @@ static void svm_vcpu_reset(struct kvm_vcpu *vcpu, bool init_event)
        }
        init_vmcb(svm);
 
-       kvm_cpuid(vcpu, &eax, &dummy, &dummy, &dummy);
+       kvm_cpuid(vcpu, &eax, &dummy, &dummy, &dummy, true);
        kvm_register_write(vcpu, VCPU_REGS_RDX, eax);
 
        if (kvm_vcpu_apicv_active(vcpu) && !init_event)
index 0a6cc6754ec5a805302b1d328a2bfc1d4bec8c00..8a202c49e2a01852c7a8f734c5e0a24c94c39093 100644 (file)
@@ -151,8 +151,8 @@ TRACE_EVENT(kvm_fast_mmio,
  */
 TRACE_EVENT(kvm_cpuid,
        TP_PROTO(unsigned int function, unsigned long rax, unsigned long rbx,
-                unsigned long rcx, unsigned long rdx),
-       TP_ARGS(function, rax, rbx, rcx, rdx),
+                unsigned long rcx, unsigned long rdx, bool found),
+       TP_ARGS(function, rax, rbx, rcx, rdx, found),
 
        TP_STRUCT__entry(
                __field(        unsigned int,   function        )
@@ -160,6 +160,7 @@ TRACE_EVENT(kvm_cpuid,
                __field(        unsigned long,  rbx             )
                __field(        unsigned long,  rcx             )
                __field(        unsigned long,  rdx             )
+               __field(        bool,           found           )
        ),
 
        TP_fast_assign(
@@ -168,11 +169,13 @@ TRACE_EVENT(kvm_cpuid,
                __entry->rbx            = rbx;
                __entry->rcx            = rcx;
                __entry->rdx            = rdx;
+               __entry->found          = found;
        ),
 
-       TP_printk("func %x rax %lx rbx %lx rcx %lx rdx %lx",
+       TP_printk("func %x rax %lx rbx %lx rcx %lx rdx %lx, cpuid entry %s",
                  __entry->function, __entry->rax,
-                 __entry->rbx, __entry->rcx, __entry->rdx)
+                 __entry->rbx, __entry->rcx, __entry->rdx,
+                 __entry->found ? "found" : "not found")
 );
 
 #define AREG(x) { APIC_##x, "APIC_" #x }
index 4e699238a113dd02fd50709c9c14bc9b5f550b52..cc2c7e413e9c64054ce48a03d92625efd38b79b8 100644 (file)
@@ -5206,10 +5206,10 @@ static int emulator_intercept(struct x86_emulate_ctxt *ctxt,
        return kvm_x86_ops->check_intercept(emul_to_vcpu(ctxt), info, stage);
 }
 
-static void emulator_get_cpuid(struct x86_emulate_ctxt *ctxt,
-                              u32 *eax, u32 *ebx, u32 *ecx, u32 *edx)
+static bool emulator_get_cpuid(struct x86_emulate_ctxt *ctxt,
+                       u32 *eax, u32 *ebx, u32 *ecx, u32 *edx, bool check_limit)
 {
-       kvm_cpuid(emul_to_vcpu(ctxt), eax, ebx, ecx, edx);
+       return kvm_cpuid(emul_to_vcpu(ctxt), eax, ebx, ecx, edx, check_limit);
 }
 
 static ulong emulator_read_gpr(struct x86_emulate_ctxt *ctxt, unsigned reg)