mirror of
https://github.com/yuzu-emu/unicorn.git
synced 2025-01-22 18:11:02 +00:00
target-i386: Set physical address bits based on host
Add the host-phys-bits boolean property, if true, take phys-bits from the hosts physical bits value, overriding either the default or the user specified value. We can also use the value we read from the host to check the users explicitly set value and warn them if it doesn't match. Note: a) We only read the hosts value in KVM mode (because on non-x86 we get an abort if we try) b) We don't warn about trying to use host-phys-bits in TCG mode, we just fall back to the TCG default. This allows the machine type to set the host-phys-bits flag if it wants and then to work in both TCG and KVM. Backports commit 11f6fee576680a2d482123535da920f8ceb33eb5 from qemu
This commit is contained in:
parent
95cced34fb
commit
9ee1a82185
|
@ -2982,6 +2982,31 @@ static void x86_cpu_apic_realize(X86CPU *cpu, Error **errp)
|
|||
}
|
||||
#endif
|
||||
|
||||
/* Note: Only safe for use on x86(-64) hosts */
|
||||
static QEMU_UNUSED_FUNC uint32_t x86_host_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;
|
||||
}
|
||||
|
||||
#define IS_INTEL_CPU(env) ((env)->cpuid_vendor1 == CPUID_VENDOR_INTEL_1 && \
|
||||
(env)->cpuid_vendor2 == CPUID_VENDOR_INTEL_2 && \
|
||||
|
@ -3033,20 +3058,26 @@ static int x86_cpu_realizefn(struct uc_struct *uc, DeviceState *dev, Error **err
|
|||
& 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).
|
||||
/* For 64bit systems think about the number of physical bits to present.
|
||||
* ideally this should be the same as the host; anything other than matching
|
||||
* the host can cause incorrect guest behaviour.
|
||||
* QEMU used to pick the magic value of 40 bits that corresponds to
|
||||
* consumer AMD devices but nothing else.
|
||||
*/
|
||||
if (cpu->phys_bits == 0) {
|
||||
cpu->phys_bits = TCG_PHYS_ADDR_BITS;
|
||||
}
|
||||
if (env->features[FEAT_8000_0001_EDX] & CPUID_EXT2_LM) {
|
||||
// Unicorn: removed KVM checks
|
||||
if (cpu->phys_bits != TCG_PHYS_ADDR_BITS) {
|
||||
if (cpu->phys_bits && cpu->phys_bits != TCG_PHYS_ADDR_BITS) {
|
||||
error_setg(errp, "TCG only supports phys-bits=%u",
|
||||
TCG_PHYS_ADDR_BITS);
|
||||
return -1;
|
||||
}
|
||||
/* 0 means it was not explicitly set by the user (or by machine
|
||||
* compat_props or by the host code above). In this case, the default
|
||||
* is the value used by TCG (40).
|
||||
*/
|
||||
if (cpu->phys_bits == 0) {
|
||||
cpu->phys_bits = TCG_PHYS_ADDR_BITS;
|
||||
}
|
||||
} else {
|
||||
/* For 32 bit systems don't use the user set value, but keep
|
||||
* phys_bits consistent with what we tell the guest.
|
||||
|
|
|
@ -1190,6 +1190,9 @@ typedef struct X86CPU {
|
|||
/* Compatibility bits for old machine types: */
|
||||
bool enable_cpuid_0xb;
|
||||
|
||||
/* if true override the phys_bits value with a value read from the host */
|
||||
bool host_phys_bits;
|
||||
|
||||
/* Number of physical address bits supported */
|
||||
uint32_t phys_bits;
|
||||
|
||||
|
|
Loading…
Reference in a new issue