diff mbox

[2/2] kvm/x86: move and fix substitue search for missing CPUID entries

Message ID 1301577181-10767-1-git-send-email-andre.przywara@amd.com (mailing list archive)
State New, archived
Headers show

Commit Message

Andre Przywara March 31, 2011, 1:13 p.m. UTC
None
diff mbox

Patch

diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 6e86cec..552b8f8 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -4959,12 +4959,6 @@  struct kvm_cpuid_entry2 *kvm_find_cpuid_entry(struct kvm_vcpu *vcpu,
 			best = e;
 			break;
 		}
-		/*
-		 * Both basic or both extended?
-		 */
-		if (((e->function ^ function) & 0x80000000) == 0)
-			if (!best || e->function > best->function)
-				best = e;
 	}
 	return best;
 }
@@ -4996,6 +4990,19 @@  void kvm_emulate_cpuid(struct kvm_vcpu *vcpu)
 	kvm_register_write(vcpu, VCPU_REGS_RCX, 0);
 	kvm_register_write(vcpu, VCPU_REGS_RDX, 0);
 	best = kvm_find_cpuid_entry(vcpu, function, index);
+
+	/* if no match is found, check whether we exceed the vCPU's limit
+	 * and return the content of the highest valid standard leaf instead.
+	 * This is to satisfy the CPUID specification.
+	 */
+	if (!best) {
+		best = kvm_find_cpuid_entry(vcpu, function & 0x80000000, 0);
+		if (best && best->eax < function)
+			best = kvm_find_cpuid_entry(vcpu, best->eax, index);
+		else
+			best = NULL;
+	}
+
 	if (best) {
 		kvm_register_write(vcpu, VCPU_REGS_RAX, best->eax);
 		kvm_register_write(vcpu, VCPU_REGS_RBX, best->ebx);