aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--target-i386/cpu.c52
-rw-r--r--target-i386/cpu.h3
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;