#include "kvm_i386.h"
#include "hw/core/accel-cpu.h"
+static void kvm_set_guest_phys_bits(CPUState *cs)
+{
+ X86CPU *cpu = X86_CPU(cs);
+ uint32_t eax, guest_phys_bits;
+
+ eax = kvm_arch_get_supported_cpuid(cs->kvm_state, 0x80000008, 0, R_EAX);
+ guest_phys_bits = (eax >> 16) & 0xff;
+ if (!guest_phys_bits) {
+ return;
+ }
+ cpu->guest_phys_bits = guest_phys_bits;
+ if (cpu->guest_phys_bits > cpu->phys_bits) {
+ cpu->guest_phys_bits = cpu->phys_bits;
+ }
+
+ if (cpu->host_phys_bits && cpu->host_phys_bits_limit &&
+ cpu->guest_phys_bits > cpu->host_phys_bits_limit) {
+ cpu->guest_phys_bits = cpu->host_phys_bits_limit;
+ }
+}
+
static bool kvm_cpu_realizefn(CPUState *cs, Error **errp)
{
X86CPU *cpu = X86_CPU(cs);
CPUX86State *env = &cpu->env;
+ bool ret;
/*
* The realize order is important, since x86_cpu_realize() checks if
*
* realize order:
*
- * x86_cpu_realize():
- * -> x86_cpu_expand_features()
- * -> cpu_exec_realizefn():
- * -> accel_cpu_common_realize()
- * kvm_cpu_realizefn() -> host_cpu_realizefn()
- * -> cpu_common_realizefn()
- * -> check/update ucode_rev, phys_bits, mwait
+ * x86_cpu_realizefn():
+ * x86_cpu_expand_features()
+ * cpu_exec_realizefn():
+ * accel_cpu_common_realize()
+ * kvm_cpu_realizefn()
+ * host_cpu_realizefn()
+ * kvm_set_guest_phys_bits()
+ * check/update ucode_rev, phys_bits, guest_phys_bits, mwait
+ * cpu_common_realizefn() (via xcc->parent_realize)
*/
if (cpu->max_features) {
if (enable_cpu_pm && kvm_has_waitpkg()) {
MSR_IA32_UCODE_REV);
}
}
- return host_cpu_realizefn(cs, errp);
+ ret = host_cpu_realizefn(cs, errp);
+ if (!ret) {
+ return ret;
+ }
+
+ if ((env->features[FEAT_8000_0001_EDX] & CPUID_EXT2_LM) &&
+ cpu->guest_phys_bits == -1) {
+ kvm_set_guest_phys_bits(cs);
+ }
+
+ return true;
}
static bool lmce_supported(void)