i386/cpu: make -cpu host support monitor/mwait

When guest CPU PM is enabled, and with -cpu host, expose the host CPU
MWAIT leaf in the CPUID so guest can make good PM decisions.

Note: the result is 100% CPU utilization reported by host as host
no longer knows that the CPU is halted.

Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Reviewed-by: Eduardo Habkost <ehabkost@redhat.com>
Message-Id: <20180622192148.178309-3-mst@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
Michael S. Tsirkin 2018-06-22 22:22:05 +03:00 committed by Paolo Bonzini
parent 6f131f13e6
commit 2266d44311
4 changed files with 43 additions and 10 deletions

View File

@ -2,6 +2,9 @@
#include "qemu-common.h"
#include "qom/cpu.h"
#include "sysemu/replay.h"
#include "sysemu/sysemu.h"
bool enable_cpu_pm = false;
void cpu_resume(CPUState *cpu)
{

View File

@ -3959,11 +3959,11 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
}
break;
case 5:
/* mwait info: needed for Core compatibility */
*eax = 0; /* Smallest monitor-line size in bytes */
*ebx = 0; /* Largest monitor-line size in bytes */
*ecx = CPUID_MWAIT_EMX | CPUID_MWAIT_IBE;
*edx = 0;
/* MONITOR/MWAIT Leaf */
*eax = cpu->mwait.eax; /* Smallest monitor-line size in bytes */
*ebx = cpu->mwait.ebx; /* Largest monitor-line size in bytes */
*ecx = cpu->mwait.ecx; /* flags */
*edx = cpu->mwait.edx; /* mwait substates */
break;
case 6:
/* Thermal and Power Leaf */
@ -4804,13 +4804,25 @@ static void x86_cpu_realizefn(DeviceState *dev, Error **errp)
Error *local_err = NULL;
static bool ht_warned;
if (xcc->host_cpuid_required && !accel_uses_host_cpuid()) {
char *name = x86_cpu_class_get_model_name(xcc);
error_setg(&local_err, "CPU model '%s' requires KVM", name);
g_free(name);
goto out;
if (xcc->host_cpuid_required) {
if (!accel_uses_host_cpuid()) {
char *name = x86_cpu_class_get_model_name(xcc);
error_setg(&local_err, "CPU model '%s' requires KVM", name);
g_free(name);
goto out;
}
if (enable_cpu_pm) {
host_cpuid(5, 0, &cpu->mwait.eax, &cpu->mwait.ebx,
&cpu->mwait.ecx, &cpu->mwait.edx);
env->features[FEAT_1_ECX] |= CPUID_EXT_MONITOR;
}
}
/* mwait extended info: needed for Core compatibility */
/* We always wake on interrupt even if host does not have the capability */
cpu->mwait.ecx |= CPUID_MWAIT_EMX | CPUID_MWAIT_IBE;
if (cpu->apic_id == UNASSIGNED_APIC_ID) {
error_setg(errp, "apic-id property was not initialized properly");
return;

View File

@ -1382,6 +1382,15 @@ struct X86CPU {
/* if true the CPUID code directly forward host cache leaves to the guest */
bool cache_info_passthrough;
/* if true the CPUID code directly forwards
* host monitor/mwait leaves to the guest */
struct {
uint32_t eax;
uint32_t ebx;
uint32_t ecx;
uint32_t edx;
} mwait;
/* Features that were filtered out because of missing host capabilities */
uint32_t filtered_features[FEATURE_WORDS];

View File

@ -366,6 +366,15 @@ uint32_t kvm_arch_get_supported_cpuid(KVMState *s, uint32_t function,
if (!kvm_irqchip_in_kernel()) {
ret &= ~CPUID_EXT_X2APIC;
}
if (enable_cpu_pm) {
int disable_exits = kvm_check_extension(s,
KVM_CAP_X86_DISABLE_EXITS);
if (disable_exits & KVM_X86_DISABLE_EXITS_MWAIT) {
ret |= CPUID_EXT_MONITOR;
}
}
} else if (function == 6 && reg == R_EAX) {
ret |= CPUID_6_EAX_ARAT; /* safe to allow because of emulated APIC */
} else if (function == 7 && index == 0 && reg == R_EBX) {