diff options
-rw-r--r-- | src/fw/paravirt.c | 57 | ||||
-rw-r--r-- | src/fw/paravirt.h | 2 |
2 files changed, 59 insertions, 0 deletions
diff --git a/src/fw/paravirt.c b/src/fw/paravirt.c index 42abac84..3aee4c0d 100644 --- a/src/fw/paravirt.c +++ b/src/fw/paravirt.c @@ -32,6 +32,10 @@ u32 RamSize; // Amount of continuous ram >4Gig u64 RamSizeOver4G; +// physical address space bits +u8 CPUPhysBits; +// 64bit processor +u8 CPULongMode; // Type of emulator platform. int PlatformRunningOn VARFSEG; // cfg enabled @@ -130,6 +134,58 @@ static void kvmclock_init(void) tsctimer_setfreq(MHz * 1000, "kvmclock"); } +static void physbits(int qemu_quirk) +{ + unsigned int max, eax, ebx, ecx, edx; + unsigned int physbits; + char signature[13]; + int pae = 0, valid = 0; + + cpuid(0, &eax, &ebx, &ecx, &edx); + memcpy(signature + 0, &ebx, 4); + memcpy(signature + 4, &edx, 4); + memcpy(signature + 8, &ecx, 4); + signature[12] = 0; + if (eax >= 1) { + cpuid(1, &eax, &ebx, &ecx, &edx); + pae = (edx & (1 << 6)); + } + + cpuid(0x80000000, &eax, &ebx, &ecx, &edx); + max = eax; + + if (max >= 0x80000001) { + cpuid(0x80000001, &eax, &ebx, &ecx, &edx); + CPULongMode = !!(edx & (1 << 29)); + } + + if (pae && CPULongMode && max >= 0x80000008) { + cpuid(0x80000008, &eax, &ebx, &ecx, &edx); + physbits = (u8)eax; + if (!qemu_quirk) { + valid = 1; + } else if (physbits >= 41) { + valid = 1; + } else if (strcmp(signature, "GenuineIntel") == 0) { + if ((physbits == 36) || (physbits == 39)) + valid = 1; + } else if (strcmp(signature, "AuthenticAMD") == 0) { + if (physbits == 40) + valid = 1; + } + } else { + physbits = pae ? 36 : 32; + valid = 1; + } + + dprintf(1, "%s: signature=\"%s\", pae=%s, lm=%s, phys-bits=%d, valid=%s\n", + __func__, signature, pae ? "yes" : "no", CPULongMode ? "yes" : "no", + physbits, valid ? "yes" : "no"); + + if (valid) + CPUPhysBits = physbits; +} + static void qemu_detect(void) { if (!CONFIG_QEMU_HARDWARE) @@ -162,6 +218,7 @@ static void qemu_detect(void) dprintf(1, "Running on QEMU (unknown nb: %04x:%04x)\n", v, d); break; } + physbits(1); } static int qemu_early_e820(void); diff --git a/src/fw/paravirt.h b/src/fw/paravirt.h index 4e2e993b..62a2cd07 100644 --- a/src/fw/paravirt.h +++ b/src/fw/paravirt.h @@ -31,6 +31,8 @@ typedef struct QemuCfgDmaAccess { extern u32 RamSize; extern u64 RamSizeOver4G; extern int PlatformRunningOn; +extern u8 CPUPhysBits; +extern u8 CPULongMode; static inline int runningOnQEMU(void) { return CONFIG_QEMU || ( |