diff options
author | Yu Zhang <yu.c.zhang@linux.intel.com> | 2017-08-24 08:27:52 -0400 |
---|---|---|
committer | Paolo Bonzini <pbonzini@redhat.com> | 2017-08-24 12:09:15 -0400 |
commit | e911eb3b3414e62cbd9853e0a91c124f4a545c0f (patch) | |
tree | e8ac1e3c35b9d452ef099cd3b04f2c1f40fe5c25 | |
parent | 3db134805c69aae16ba6193946aa8deccd393ead (diff) |
KVM: x86: Add return value to kvm_cpuid().
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>
-rw-r--r-- | arch/x86/include/asm/kvm_emulate.h | 4 | ||||
-rw-r--r-- | arch/x86/kvm/cpuid.c | 17 | ||||
-rw-r--r-- | arch/x86/kvm/cpuid.h | 3 | ||||
-rw-r--r-- | arch/x86/kvm/emulate.c | 12 | ||||
-rw-r--r-- | arch/x86/kvm/svm.c | 2 | ||||
-rw-r--r-- | arch/x86/kvm/trace.h | 11 | ||||
-rw-r--r-- | arch/x86/kvm/x86.c | 6 |
7 files changed, 34 insertions, 21 deletions
diff --git a/arch/x86/include/asm/kvm_emulate.h b/arch/x86/include/asm/kvm_emulate.h index fde36f189836..fa2558e12024 100644 --- a/arch/x86/include/asm/kvm_emulate.h +++ b/arch/x86/include/asm/kvm_emulate.h | |||
@@ -219,8 +219,8 @@ struct x86_emulate_ops { | |||
219 | struct x86_instruction_info *info, | 219 | struct x86_instruction_info *info, |
220 | enum x86_intercept_stage stage); | 220 | enum x86_intercept_stage stage); |
221 | 221 | ||
222 | void (*get_cpuid)(struct x86_emulate_ctxt *ctxt, | 222 | bool (*get_cpuid)(struct x86_emulate_ctxt *ctxt, u32 *eax, u32 *ebx, |
223 | u32 *eax, u32 *ebx, u32 *ecx, u32 *edx); | 223 | u32 *ecx, u32 *edx, bool check_limit); |
224 | void (*set_nmi_mask)(struct x86_emulate_ctxt *ctxt, bool masked); | 224 | void (*set_nmi_mask)(struct x86_emulate_ctxt *ctxt, bool masked); |
225 | 225 | ||
226 | unsigned (*get_hflags)(struct x86_emulate_ctxt *ctxt); | 226 | unsigned (*get_hflags)(struct x86_emulate_ctxt *ctxt); |
diff --git a/arch/x86/kvm/cpuid.c b/arch/x86/kvm/cpuid.c index 59ca2eea522c..14505473fb21 100644 --- a/arch/x86/kvm/cpuid.c +++ b/arch/x86/kvm/cpuid.c | |||
@@ -853,16 +853,24 @@ static struct kvm_cpuid_entry2* check_cpuid_limit(struct kvm_vcpu *vcpu, | |||
853 | return kvm_find_cpuid_entry(vcpu, maxlevel->eax, index); | 853 | return kvm_find_cpuid_entry(vcpu, maxlevel->eax, index); |
854 | } | 854 | } |
855 | 855 | ||
856 | void kvm_cpuid(struct kvm_vcpu *vcpu, u32 *eax, u32 *ebx, u32 *ecx, u32 *edx) | 856 | bool kvm_cpuid(struct kvm_vcpu *vcpu, u32 *eax, u32 *ebx, |
857 | u32 *ecx, u32 *edx, bool check_limit) | ||
857 | { | 858 | { |
858 | u32 function = *eax, index = *ecx; | 859 | u32 function = *eax, index = *ecx; |
859 | struct kvm_cpuid_entry2 *best; | 860 | struct kvm_cpuid_entry2 *best; |
861 | bool entry_found = true; | ||
860 | 862 | ||
861 | best = kvm_find_cpuid_entry(vcpu, function, index); | 863 | best = kvm_find_cpuid_entry(vcpu, function, index); |
862 | 864 | ||
863 | if (!best) | 865 | if (!best) { |
866 | entry_found = false; | ||
867 | if (!check_limit) | ||
868 | goto out; | ||
869 | |||
864 | best = check_cpuid_limit(vcpu, function, index); | 870 | best = check_cpuid_limit(vcpu, function, index); |
871 | } | ||
865 | 872 | ||
873 | out: | ||
866 | if (best) { | 874 | if (best) { |
867 | *eax = best->eax; | 875 | *eax = best->eax; |
868 | *ebx = best->ebx; | 876 | *ebx = best->ebx; |
@@ -870,7 +878,8 @@ void kvm_cpuid(struct kvm_vcpu *vcpu, u32 *eax, u32 *ebx, u32 *ecx, u32 *edx) | |||
870 | *edx = best->edx; | 878 | *edx = best->edx; |
871 | } else | 879 | } else |
872 | *eax = *ebx = *ecx = *edx = 0; | 880 | *eax = *ebx = *ecx = *edx = 0; |
873 | trace_kvm_cpuid(function, *eax, *ebx, *ecx, *edx); | 881 | trace_kvm_cpuid(function, *eax, *ebx, *ecx, *edx, entry_found); |
882 | return entry_found; | ||
874 | } | 883 | } |
875 | EXPORT_SYMBOL_GPL(kvm_cpuid); | 884 | EXPORT_SYMBOL_GPL(kvm_cpuid); |
876 | 885 | ||
@@ -883,7 +892,7 @@ int kvm_emulate_cpuid(struct kvm_vcpu *vcpu) | |||
883 | 892 | ||
884 | eax = kvm_register_read(vcpu, VCPU_REGS_RAX); | 893 | eax = kvm_register_read(vcpu, VCPU_REGS_RAX); |
885 | ecx = kvm_register_read(vcpu, VCPU_REGS_RCX); | 894 | ecx = kvm_register_read(vcpu, VCPU_REGS_RCX); |
886 | kvm_cpuid(vcpu, &eax, &ebx, &ecx, &edx); | 895 | kvm_cpuid(vcpu, &eax, &ebx, &ecx, &edx, true); |
887 | kvm_register_write(vcpu, VCPU_REGS_RAX, eax); | 896 | kvm_register_write(vcpu, VCPU_REGS_RAX, eax); |
888 | kvm_register_write(vcpu, VCPU_REGS_RBX, ebx); | 897 | kvm_register_write(vcpu, VCPU_REGS_RBX, ebx); |
889 | kvm_register_write(vcpu, VCPU_REGS_RCX, ecx); | 898 | kvm_register_write(vcpu, VCPU_REGS_RCX, ecx); |
diff --git a/arch/x86/kvm/cpuid.h b/arch/x86/kvm/cpuid.h index ac15193e5e52..1ea3c0e1e3a9 100644 --- a/arch/x86/kvm/cpuid.h +++ b/arch/x86/kvm/cpuid.h | |||
@@ -21,7 +21,8 @@ int kvm_vcpu_ioctl_set_cpuid2(struct kvm_vcpu *vcpu, | |||
21 | int kvm_vcpu_ioctl_get_cpuid2(struct kvm_vcpu *vcpu, | 21 | int kvm_vcpu_ioctl_get_cpuid2(struct kvm_vcpu *vcpu, |
22 | struct kvm_cpuid2 *cpuid, | 22 | struct kvm_cpuid2 *cpuid, |
23 | struct kvm_cpuid_entry2 __user *entries); | 23 | struct kvm_cpuid_entry2 __user *entries); |
24 | void kvm_cpuid(struct kvm_vcpu *vcpu, u32 *eax, u32 *ebx, u32 *ecx, u32 *edx); | 24 | bool kvm_cpuid(struct kvm_vcpu *vcpu, u32 *eax, u32 *ebx, |
25 | u32 *ecx, u32 *edx, bool check_limit); | ||
25 | 26 | ||
26 | int cpuid_query_maxphyaddr(struct kvm_vcpu *vcpu); | 27 | int cpuid_query_maxphyaddr(struct kvm_vcpu *vcpu); |
27 | 28 | ||
diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c index fb0055953fbc..319d91f6f3c4 100644 --- a/arch/x86/kvm/emulate.c +++ b/arch/x86/kvm/emulate.c | |||
@@ -2333,7 +2333,7 @@ static int emulator_has_longmode(struct x86_emulate_ctxt *ctxt) | |||
2333 | 2333 | ||
2334 | eax = 0x80000001; | 2334 | eax = 0x80000001; |
2335 | ecx = 0; | 2335 | ecx = 0; |
2336 | ctxt->ops->get_cpuid(ctxt, &eax, &ebx, &ecx, &edx); | 2336 | ctxt->ops->get_cpuid(ctxt, &eax, &ebx, &ecx, &edx, false); |
2337 | return edx & bit(X86_FEATURE_LM); | 2337 | return edx & bit(X86_FEATURE_LM); |
2338 | } | 2338 | } |
2339 | 2339 | ||
@@ -2636,7 +2636,7 @@ static bool vendor_intel(struct x86_emulate_ctxt *ctxt) | |||
2636 | u32 eax, ebx, ecx, edx; | 2636 | u32 eax, ebx, ecx, edx; |
2637 | 2637 | ||
2638 | eax = ecx = 0; | 2638 | eax = ecx = 0; |
2639 | ctxt->ops->get_cpuid(ctxt, &eax, &ebx, &ecx, &edx); | 2639 | ctxt->ops->get_cpuid(ctxt, &eax, &ebx, &ecx, &edx, false); |
2640 | return ebx == X86EMUL_CPUID_VENDOR_GenuineIntel_ebx | 2640 | return ebx == X86EMUL_CPUID_VENDOR_GenuineIntel_ebx |
2641 | && ecx == X86EMUL_CPUID_VENDOR_GenuineIntel_ecx | 2641 | && ecx == X86EMUL_CPUID_VENDOR_GenuineIntel_ecx |
2642 | && edx == X86EMUL_CPUID_VENDOR_GenuineIntel_edx; | 2642 | && edx == X86EMUL_CPUID_VENDOR_GenuineIntel_edx; |
@@ -2656,7 +2656,7 @@ static bool em_syscall_is_enabled(struct x86_emulate_ctxt *ctxt) | |||
2656 | 2656 | ||
2657 | eax = 0x00000000; | 2657 | eax = 0x00000000; |
2658 | ecx = 0x00000000; | 2658 | ecx = 0x00000000; |
2659 | ops->get_cpuid(ctxt, &eax, &ebx, &ecx, &edx); | 2659 | ops->get_cpuid(ctxt, &eax, &ebx, &ecx, &edx, false); |
2660 | /* | 2660 | /* |
2661 | * Intel ("GenuineIntel") | 2661 | * Intel ("GenuineIntel") |
2662 | * remark: Intel CPUs only support "syscall" in 64bit | 2662 | * remark: Intel CPUs only support "syscall" in 64bit |
@@ -3551,7 +3551,7 @@ static int em_movbe(struct x86_emulate_ctxt *ctxt) | |||
3551 | /* | 3551 | /* |
3552 | * Check MOVBE is set in the guest-visible CPUID leaf. | 3552 | * Check MOVBE is set in the guest-visible CPUID leaf. |
3553 | */ | 3553 | */ |
3554 | ctxt->ops->get_cpuid(ctxt, &eax, &ebx, &ecx, &edx); | 3554 | ctxt->ops->get_cpuid(ctxt, &eax, &ebx, &ecx, &edx, false); |
3555 | if (!(ecx & FFL(MOVBE))) | 3555 | if (!(ecx & FFL(MOVBE))) |
3556 | return emulate_ud(ctxt); | 3556 | return emulate_ud(ctxt); |
3557 | 3557 | ||
@@ -3865,7 +3865,7 @@ static int em_cpuid(struct x86_emulate_ctxt *ctxt) | |||
3865 | 3865 | ||
3866 | eax = reg_read(ctxt, VCPU_REGS_RAX); | 3866 | eax = reg_read(ctxt, VCPU_REGS_RAX); |
3867 | ecx = reg_read(ctxt, VCPU_REGS_RCX); | 3867 | ecx = reg_read(ctxt, VCPU_REGS_RCX); |
3868 | ctxt->ops->get_cpuid(ctxt, &eax, &ebx, &ecx, &edx); | 3868 | ctxt->ops->get_cpuid(ctxt, &eax, &ebx, &ecx, &edx, true); |
3869 | *reg_write(ctxt, VCPU_REGS_RAX) = eax; | 3869 | *reg_write(ctxt, VCPU_REGS_RAX) = eax; |
3870 | *reg_write(ctxt, VCPU_REGS_RBX) = ebx; | 3870 | *reg_write(ctxt, VCPU_REGS_RBX) = ebx; |
3871 | *reg_write(ctxt, VCPU_REGS_RCX) = ecx; | 3871 | *reg_write(ctxt, VCPU_REGS_RCX) = ecx; |
@@ -3924,7 +3924,7 @@ static int check_fxsr(struct x86_emulate_ctxt *ctxt) | |||
3924 | { | 3924 | { |
3925 | u32 eax = 1, ebx, ecx = 0, edx; | 3925 | u32 eax = 1, ebx, ecx = 0, edx; |
3926 | 3926 | ||
3927 | ctxt->ops->get_cpuid(ctxt, &eax, &ebx, &ecx, &edx); | 3927 | ctxt->ops->get_cpuid(ctxt, &eax, &ebx, &ecx, &edx, false); |
3928 | if (!(edx & FFL(FXSR))) | 3928 | if (!(edx & FFL(FXSR))) |
3929 | return emulate_ud(ctxt); | 3929 | return emulate_ud(ctxt); |
3930 | 3930 | ||
diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c index 7e190b21a30b..c5b9705186d6 100644 --- a/arch/x86/kvm/svm.c +++ b/arch/x86/kvm/svm.c | |||
@@ -1593,7 +1593,7 @@ static void svm_vcpu_reset(struct kvm_vcpu *vcpu, bool init_event) | |||
1593 | } | 1593 | } |
1594 | init_vmcb(svm); | 1594 | init_vmcb(svm); |
1595 | 1595 | ||
1596 | kvm_cpuid(vcpu, &eax, &dummy, &dummy, &dummy); | 1596 | kvm_cpuid(vcpu, &eax, &dummy, &dummy, &dummy, true); |
1597 | kvm_register_write(vcpu, VCPU_REGS_RDX, eax); | 1597 | kvm_register_write(vcpu, VCPU_REGS_RDX, eax); |
1598 | 1598 | ||
1599 | if (kvm_vcpu_apicv_active(vcpu) && !init_event) | 1599 | if (kvm_vcpu_apicv_active(vcpu) && !init_event) |
diff --git a/arch/x86/kvm/trace.h b/arch/x86/kvm/trace.h index 0a6cc6754ec5..8a202c49e2a0 100644 --- a/arch/x86/kvm/trace.h +++ b/arch/x86/kvm/trace.h | |||
@@ -151,8 +151,8 @@ TRACE_EVENT(kvm_fast_mmio, | |||
151 | */ | 151 | */ |
152 | TRACE_EVENT(kvm_cpuid, | 152 | TRACE_EVENT(kvm_cpuid, |
153 | TP_PROTO(unsigned int function, unsigned long rax, unsigned long rbx, | 153 | TP_PROTO(unsigned int function, unsigned long rax, unsigned long rbx, |
154 | unsigned long rcx, unsigned long rdx), | 154 | unsigned long rcx, unsigned long rdx, bool found), |
155 | TP_ARGS(function, rax, rbx, rcx, rdx), | 155 | TP_ARGS(function, rax, rbx, rcx, rdx, found), |
156 | 156 | ||
157 | TP_STRUCT__entry( | 157 | TP_STRUCT__entry( |
158 | __field( unsigned int, function ) | 158 | __field( unsigned int, function ) |
@@ -160,6 +160,7 @@ TRACE_EVENT(kvm_cpuid, | |||
160 | __field( unsigned long, rbx ) | 160 | __field( unsigned long, rbx ) |
161 | __field( unsigned long, rcx ) | 161 | __field( unsigned long, rcx ) |
162 | __field( unsigned long, rdx ) | 162 | __field( unsigned long, rdx ) |
163 | __field( bool, found ) | ||
163 | ), | 164 | ), |
164 | 165 | ||
165 | TP_fast_assign( | 166 | TP_fast_assign( |
@@ -168,11 +169,13 @@ TRACE_EVENT(kvm_cpuid, | |||
168 | __entry->rbx = rbx; | 169 | __entry->rbx = rbx; |
169 | __entry->rcx = rcx; | 170 | __entry->rcx = rcx; |
170 | __entry->rdx = rdx; | 171 | __entry->rdx = rdx; |
172 | __entry->found = found; | ||
171 | ), | 173 | ), |
172 | 174 | ||
173 | TP_printk("func %x rax %lx rbx %lx rcx %lx rdx %lx", | 175 | TP_printk("func %x rax %lx rbx %lx rcx %lx rdx %lx, cpuid entry %s", |
174 | __entry->function, __entry->rax, | 176 | __entry->function, __entry->rax, |
175 | __entry->rbx, __entry->rcx, __entry->rdx) | 177 | __entry->rbx, __entry->rcx, __entry->rdx, |
178 | __entry->found ? "found" : "not found") | ||
176 | ); | 179 | ); |
177 | 180 | ||
178 | #define AREG(x) { APIC_##x, "APIC_" #x } | 181 | #define AREG(x) { APIC_##x, "APIC_" #x } |
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 4e699238a113..cc2c7e413e9c 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c | |||
@@ -5206,10 +5206,10 @@ static int emulator_intercept(struct x86_emulate_ctxt *ctxt, | |||
5206 | return kvm_x86_ops->check_intercept(emul_to_vcpu(ctxt), info, stage); | 5206 | return kvm_x86_ops->check_intercept(emul_to_vcpu(ctxt), info, stage); |
5207 | } | 5207 | } |
5208 | 5208 | ||
5209 | static void emulator_get_cpuid(struct x86_emulate_ctxt *ctxt, | 5209 | static bool emulator_get_cpuid(struct x86_emulate_ctxt *ctxt, |
5210 | u32 *eax, u32 *ebx, u32 *ecx, u32 *edx) | 5210 | u32 *eax, u32 *ebx, u32 *ecx, u32 *edx, bool check_limit) |
5211 | { | 5211 | { |
5212 | kvm_cpuid(emul_to_vcpu(ctxt), eax, ebx, ecx, edx); | 5212 | return kvm_cpuid(emul_to_vcpu(ctxt), eax, ebx, ecx, edx, check_limit); |
5213 | } | 5213 | } |
5214 | 5214 | ||
5215 | static ulong emulator_read_gpr(struct x86_emulate_ctxt *ctxt, unsigned reg) | 5215 | static ulong emulator_read_gpr(struct x86_emulate_ctxt *ctxt, unsigned reg) |