aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/fw/paravirt.c30
1 files changed, 21 insertions, 9 deletions
diff --git a/src/fw/paravirt.c b/src/fw/paravirt.c
index fba4e52d..42abac84 100644
--- a/src/fw/paravirt.c
+++ b/src/fw/paravirt.c
@@ -53,23 +53,35 @@ inline int qemu_cfg_dma_enabled(void)
* should be used to determine that a VM is running under KVM.
*/
#define KVM_CPUID_SIGNATURE 0x40000000
+static unsigned int kvm_cpuid_base = 0;
static void kvm_detect(void)
{
+ unsigned int i, max = 0;
unsigned int eax, ebx, ecx, edx;
char signature[13];
- cpuid(KVM_CPUID_SIGNATURE, &eax, &ebx, &ecx, &edx);
- memcpy(signature + 0, &ebx, 4);
- memcpy(signature + 4, &ecx, 4);
- memcpy(signature + 8, &edx, 4);
- signature[12] = 0;
+ for (i = KVM_CPUID_SIGNATURE;; i += 0x100) {
+ eax = 0;
+ cpuid(i, &eax, &ebx, &ecx, &edx);
+ if (eax < i)
+ break;
+ memcpy(signature + 0, &ebx, 4);
+ memcpy(signature + 4, &ecx, 4);
+ memcpy(signature + 8, &edx, 4);
+ signature[12] = 0;
+ dprintf(1, "cpuid 0x%x: eax %x, signature '%s'\n", i, eax, signature);
+ if (strcmp(signature, "KVMKVMKVM") == 0) {
+ kvm_cpuid_base = i;
+ max = eax;
+ }
+ }
- if (strcmp(signature, "KVMKVMKVM") == 0) {
+ if (kvm_cpuid_base) {
dprintf(1, "Running on KVM\n");
PlatformRunningOn |= PF_KVM;
- if (eax >= KVM_CPUID_SIGNATURE + 0x10) {
- cpuid(KVM_CPUID_SIGNATURE + 0x10, &eax, &ebx, &ecx, &edx);
+ if (max >= kvm_cpuid_base + 0x10) {
+ cpuid(kvm_cpuid_base + 0x10, &eax, &ebx, &ecx, &edx);
dprintf(1, "kvm: have invtsc, freq %u kHz\n", eax);
tsctimer_setfreq(eax, "invtsc");
}
@@ -93,7 +105,7 @@ static void kvmclock_init(void)
if (!runningOnKVM())
return;
- cpuid(KVM_CPUID_SIGNATURE + 0x01, &eax, &ebx, &ecx, &edx);
+ cpuid(kvm_cpuid_base + 0x01, &eax, &ebx, &ecx, &edx);
if (eax & (1 << KVM_FEATURE_CLOCKSOURCE2))
msr = MSR_KVM_SYSTEM_TIME_NEW;
else if (eax & (1 << KVM_FEATURE_CLOCKSOURCE))