mirror of https://gitee.com/openkylin/qemu.git
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:
parent
6f131f13e6
commit
2266d44311
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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];
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
Loading…
Reference in New Issue