diff --git a/target/i386/cpu.c b/target/i386/cpu.c index a66e5a357b..8958d4b23d 100644 --- a/target/i386/cpu.c +++ b/target/i386/cpu.c @@ -7368,7 +7368,15 @@ static void x86_cpu_realizefn(DeviceState *dev, Error **errp) * In this case, the default is the value used by TCG (40). */ if (cpu->phys_bits == 0) { - cpu->phys_bits = TCG_PHYS_ADDR_BITS; + /* SUSE Downstream patch: TCG_PHYS_ADDR_BITS is 40. We, instead + * need the phys_bits to be 42 (only if the host supports that, of + * course), because we did set it to 42 (unconditionally!) a while + * ago, and now we need to stay compatible with that. However, + * instead of messing with the macro, just use the value here, + * to avoid messing with other places where the macro is used + * (namely, for TCG). + */ + cpu->phys_bits = (MIN(42, host_cpu_phys_bits())); } } else { /* For 32 bit systems don't use the user set value, but keep diff --git a/target/i386/cpu.h b/target/i386/cpu.h index 705d925e6c..64345de9fd 100644 --- a/target/i386/cpu.h +++ b/target/i386/cpu.h @@ -2238,6 +2238,41 @@ void cpu_clear_apic_feature(CPUX86State *env); void host_cpuid(uint32_t function, uint32_t count, uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx); +/* Note: Only safe for use on x86(-64) hosts */ +#ifdef __x86_64__ +static inline uint32_t host_cpu_phys_bits(void) +{ + uint32_t eax; + uint32_t host_phys_bits; + + host_cpuid(0x80000000, 0, &eax, NULL, NULL, NULL); + if (eax >= 0x80000008) { + host_cpuid(0x80000008, 0, &eax, NULL, NULL, NULL); + /* + * Note: According to AMD doc 25481 rev 2.34 they have a field + * at 23:16 that can specify a maximum physical address bits for + * the guest that can override this value; but I've not seen + * anything with that set. + */ + host_phys_bits = eax & 0xff; + } else { + /* + * It's an odd 64 bit machine that doesn't have the leaf for + * physical address bits; fall back to 36 that's most older + * Intel. + */ + host_phys_bits = 36; + } + + return host_phys_bits; +} +#else +static inline uint32_t host_cpu_phys_bits(void) +{ + return 40; // TCG_PHYS_ADDR_BITS +} +#endif + /* helper.c */ void x86_cpu_set_a20(X86CPU *cpu, int a20_state); void cpu_sync_avx_hflag(CPUX86State *env); diff --git a/target/i386/host-cpu.c b/target/i386/host-cpu.c index 92ecb7254b..5ca037dd59 100644 --- a/target/i386/host-cpu.c +++ b/target/i386/host-cpu.c @@ -14,34 +14,6 @@ #include "qemu/error-report.h" #include "sysemu/sysemu.h" -/* Note: Only safe for use on x86(-64) hosts */ -static uint32_t host_cpu_phys_bits(void) -{ - uint32_t eax; - uint32_t host_phys_bits; - - host_cpuid(0x80000000, 0, &eax, NULL, NULL, NULL); - if (eax >= 0x80000008) { - host_cpuid(0x80000008, 0, &eax, NULL, NULL, NULL); - /* - * Note: According to AMD doc 25481 rev 2.34 they have a field - * at 23:16 that can specify a maximum physical address bits for - * the guest that can override this value; but I've not seen - * anything with that set. - */ - host_phys_bits = eax & 0xff; - } else { - /* - * It's an odd 64 bit machine that doesn't have the leaf for - * physical address bits; fall back to 36 that's most older - * Intel. - */ - host_phys_bits = 36; - } - - return host_phys_bits; -} - static void host_cpu_enable_cpu_pm(X86CPU *cpu) { CPUX86State *env = &cpu->env;