diff options
-rw-r--r-- | target-i386/cpu.c | 52 | ||||
-rw-r--r-- | target-i386/cpu.h | 3 |
2 files changed, 46 insertions, 9 deletions
diff --git a/target-i386/cpu.c b/target-i386/cpu.c index 6e49e4ca82..669180e3fe 100644 --- a/target-i386/cpu.c +++ b/target-i386/cpu.c @@ -2641,17 +2641,13 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count, break; case 0x80000008: /* virtual & phys address size in low 2 bytes. */ -/* XXX: This value must match the one used in the MMU code. */ if (env->features[FEAT_8000_0001_EDX] & CPUID_EXT2_LM) { - /* 64 bit processor */ -/* XXX: The physical address space is limited to 42 bits in exec.c. */ - *eax = 0x00003028; /* 48 bits virtual, 40 bits physical */ + /* 64 bit processor, 48 bits virtual, configurable + * physical bits. + */ + *eax = 0x00003000 + cpu->phys_bits; } else { - if (env->features[FEAT_1_EDX] & CPUID_PSE36) { - *eax = 0x00000024; /* 36 bits physical */ - } else { - *eax = 0x00000020; /* 32 bits physical */ - } + *eax = cpu->phys_bits; } *ebx = 0; *ecx = 0; @@ -2993,7 +2989,44 @@ static void x86_cpu_realizefn(DeviceState *dev, Error **errp) & CPUID_EXT2_AMD_ALIASES); } + if (env->features[FEAT_8000_0001_EDX] & CPUID_EXT2_LM) { + /* 0 means it was not explicitly set by the user (or by machine + * compat_props). In this case, the default is the value used by + * TCG (40). + */ + if (cpu->phys_bits == 0) { + cpu->phys_bits = TCG_PHYS_ADDR_BITS; + } + if (kvm_enabled()) { + if (cpu->phys_bits > TARGET_PHYS_ADDR_SPACE_BITS || + cpu->phys_bits < 32) { + error_setg(errp, "phys-bits should be between 32 and %u " + " (but is %u)", + TARGET_PHYS_ADDR_SPACE_BITS, cpu->phys_bits); + return; + } + } else { + if (cpu->phys_bits != TCG_PHYS_ADDR_BITS) { + error_setg(errp, "TCG only supports phys-bits=%u", + TCG_PHYS_ADDR_BITS); + return; + } + } + } else { + /* For 32 bit systems don't use the user set value, but keep + * phys_bits consistent with what we tell the guest. + */ + if (cpu->phys_bits != 0) { + error_setg(errp, "phys-bits is not user-configurable in 32 bit"); + return; + } + if (env->features[FEAT_1_EDX] & CPUID_PSE36) { + cpu->phys_bits = 36; + } else { + cpu->phys_bits = 32; + } + } cpu_exec_init(cs, &error_abort); if (tcg_enabled()) { @@ -3294,6 +3327,7 @@ static Property x86_cpu_properties[] = { DEFINE_PROP_BOOL("check", X86CPU, check_cpuid, true), DEFINE_PROP_BOOL("enforce", X86CPU, enforce_cpuid, false), DEFINE_PROP_BOOL("kvm", X86CPU, expose_kvm, true), + DEFINE_PROP_UINT32("phys-bits", X86CPU, phys_bits, 0), DEFINE_PROP_UINT32("level", X86CPU, env.cpuid_level, 0), DEFINE_PROP_UINT32("xlevel", X86CPU, env.cpuid_xlevel, 0), DEFINE_PROP_UINT32("xlevel2", X86CPU, env.cpuid_xlevel2, 0), diff --git a/target-i386/cpu.h b/target-i386/cpu.h index 8b6bd0be2a..b2ddcb8085 100644 --- a/target-i386/cpu.h +++ b/target-i386/cpu.h @@ -1198,6 +1198,9 @@ struct X86CPU { /* Compatibility bits for old machine types: */ bool enable_cpuid_0xb; + /* Number of physical address bits supported */ + uint32_t phys_bits; + /* in order to simplify APIC support, we leave this pointer to the user */ struct DeviceState *apic_state; |