From 8bca9a03ec60d63b2ee6a959fe85dda4206811e0 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Wed, 30 May 2018 11:58:36 +0200 Subject: move public invalidate APIs out of translate-all.{c,h}, clean up Place them in exec.c, exec-all.h and ram_addr.h. This removes knowledge of translate-all.h (which is an internal header) from several files outside accel/tcg and removes knowledge of AddressSpace from translate-all.c (as it only operates on ram_addr_t). Signed-off-by: Paolo Bonzini --- target/xtensa/op_helper.c | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) (limited to 'target') diff --git a/target/xtensa/op_helper.c b/target/xtensa/op_helper.c index 8a8c763c63..bbbbb33f3c 100644 --- a/target/xtensa/op_helper.c +++ b/target/xtensa/op_helper.c @@ -36,11 +36,6 @@ #include "qemu/timer.h" #include "fpu/softfloat.h" -#ifdef CONFIG_USER_ONLY -/* tb_invalidate_phys_range */ -#include "accel/tcg/translate-all.h" -#endif - #ifndef CONFIG_USER_ONLY void xtensa_cpu_do_unaligned_access(CPUState *cs, @@ -114,9 +109,7 @@ static void tb_invalidate_virtual_addr(CPUXtensaState *env, uint32_t vaddr) static void tb_invalidate_virtual_addr(CPUXtensaState *env, uint32_t vaddr) { - mmap_lock(); - tb_invalidate_phys_range(vaddr, vaddr + 1); - mmap_unlock(); + tb_invalidate_phys_addr(vaddr); } #endif -- cgit v1.2.3 From 13672386a93fef64cfd33bd72fbf3d80f2c00e94 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Wed, 12 Jul 2017 09:29:02 -1000 Subject: target/i386: Fix BLSR and BLSI The implementation of these two instructions was swapped. At the same time, unify the setup of eflags for the insn group. Reported-by: Ricardo Ribalda Delgado Signed-off-by: Richard Henderson Message-Id: <20170712192902.15493-1-rth@twiddle.net> Signed-off-by: Paolo Bonzini --- target/i386/translate.c | 26 +++++++++----------------- 1 file changed, 9 insertions(+), 17 deletions(-) (limited to 'target') diff --git a/target/i386/translate.c b/target/i386/translate.c index 697a918c11..c91849417b 100644 --- a/target/i386/translate.c +++ b/target/i386/translate.c @@ -4059,34 +4059,26 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b, ot = mo_64_32(s->dflag); gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0); + tcg_gen_mov_tl(cpu_cc_src, cpu_T0); switch (reg & 7) { case 1: /* blsr By,Ey */ - tcg_gen_neg_tl(cpu_T1, cpu_T0); + tcg_gen_subi_tl(cpu_T1, cpu_T0, 1); tcg_gen_and_tl(cpu_T0, cpu_T0, cpu_T1); - gen_op_mov_reg_v(ot, s->vex_v, cpu_T0); - gen_op_update2_cc(); - set_cc_op(s, CC_OP_BMILGB + ot); break; - case 2: /* blsmsk By,Ey */ - tcg_gen_mov_tl(cpu_cc_src, cpu_T0); - tcg_gen_subi_tl(cpu_T0, cpu_T0, 1); - tcg_gen_xor_tl(cpu_T0, cpu_T0, cpu_cc_src); - tcg_gen_mov_tl(cpu_cc_dst, cpu_T0); - set_cc_op(s, CC_OP_BMILGB + ot); + tcg_gen_subi_tl(cpu_T1, cpu_T0, 1); + tcg_gen_xor_tl(cpu_T0, cpu_T0, cpu_T1); break; - case 3: /* blsi By, Ey */ - tcg_gen_mov_tl(cpu_cc_src, cpu_T0); - tcg_gen_subi_tl(cpu_T0, cpu_T0, 1); - tcg_gen_and_tl(cpu_T0, cpu_T0, cpu_cc_src); - tcg_gen_mov_tl(cpu_cc_dst, cpu_T0); - set_cc_op(s, CC_OP_BMILGB + ot); + tcg_gen_neg_tl(cpu_T1, cpu_T0); + tcg_gen_and_tl(cpu_T0, cpu_T0, cpu_T1); break; - default: goto unknown_op; } + tcg_gen_mov_tl(cpu_cc_dst, cpu_T0); + gen_op_mov_reg_v(ot, s->vex_v, cpu_T0); + set_cc_op(s, CC_OP_BMILGB + ot); break; default: -- cgit v1.2.3 From 93d1499c8119989e3eb9a6936c5a18aaaaca6330 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Wed, 6 Jun 2018 15:41:58 +0200 Subject: whpx: commit missing file Not included by mistake in commit 327fccb288976f95808efa968082fc9d4a9ced84. Signed-off-by: Paolo Bonzini --- target/i386/whp-dispatch.h | 56 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) create mode 100644 target/i386/whp-dispatch.h (limited to 'target') diff --git a/target/i386/whp-dispatch.h b/target/i386/whp-dispatch.h new file mode 100644 index 0000000000..d8d3485976 --- /dev/null +++ b/target/i386/whp-dispatch.h @@ -0,0 +1,56 @@ +#include "windows.h" +#include + +#include +#include + +#ifndef WHP_DISPATCH_H +#define WHP_DISPATCH_H + + +#define LIST_WINHVPLATFORM_FUNCTIONS(X) \ + X(HRESULT, WHvGetCapability, (WHV_CAPABILITY_CODE CapabilityCode, VOID* CapabilityBuffer, UINT32 CapabilityBufferSizeInBytes, UINT32* WrittenSizeInBytes)) \ + X(HRESULT, WHvCreatePartition, (WHV_PARTITION_HANDLE* Partition)) \ + X(HRESULT, WHvSetupPartition, (WHV_PARTITION_HANDLE Partition)) \ + X(HRESULT, WHvDeletePartition, (WHV_PARTITION_HANDLE Partition)) \ + X(HRESULT, WHvGetPartitionProperty, (WHV_PARTITION_HANDLE Partition, WHV_PARTITION_PROPERTY_CODE PropertyCode, VOID* PropertyBuffer, UINT32 PropertyBufferSizeInBytes, UINT32* WrittenSizeInBytes)) \ + X(HRESULT, WHvSetPartitionProperty, (WHV_PARTITION_HANDLE Partition, WHV_PARTITION_PROPERTY_CODE PropertyCode, const VOID* PropertyBuffer, UINT32 PropertyBufferSizeInBytes)) \ + X(HRESULT, WHvMapGpaRange, (WHV_PARTITION_HANDLE Partition, VOID* SourceAddress, WHV_GUEST_PHYSICAL_ADDRESS GuestAddress, UINT64 SizeInBytes, WHV_MAP_GPA_RANGE_FLAGS Flags)) \ + X(HRESULT, WHvUnmapGpaRange, (WHV_PARTITION_HANDLE Partition, WHV_GUEST_PHYSICAL_ADDRESS GuestAddress, UINT64 SizeInBytes)) \ + X(HRESULT, WHvTranslateGva, (WHV_PARTITION_HANDLE Partition, UINT32 VpIndex, WHV_GUEST_VIRTUAL_ADDRESS Gva, WHV_TRANSLATE_GVA_FLAGS TranslateFlags, WHV_TRANSLATE_GVA_RESULT* TranslationResult, WHV_GUEST_PHYSICAL_ADDRESS* Gpa)) \ + X(HRESULT, WHvCreateVirtualProcessor, (WHV_PARTITION_HANDLE Partition, UINT32 VpIndex, UINT32 Flags)) \ + X(HRESULT, WHvDeleteVirtualProcessor, (WHV_PARTITION_HANDLE Partition, UINT32 VpIndex)) \ + X(HRESULT, WHvRunVirtualProcessor, (WHV_PARTITION_HANDLE Partition, UINT32 VpIndex, VOID* ExitContext, UINT32 ExitContextSizeInBytes)) \ + X(HRESULT, WHvCancelRunVirtualProcessor, (WHV_PARTITION_HANDLE Partition, UINT32 VpIndex, UINT32 Flags)) \ + X(HRESULT, WHvGetVirtualProcessorRegisters, (WHV_PARTITION_HANDLE Partition, UINT32 VpIndex, const WHV_REGISTER_NAME* RegisterNames, UINT32 RegisterCount, WHV_REGISTER_VALUE* RegisterValues)) \ + X(HRESULT, WHvSetVirtualProcessorRegisters, (WHV_PARTITION_HANDLE Partition, UINT32 VpIndex, const WHV_REGISTER_NAME* RegisterNames, UINT32 RegisterCount, const WHV_REGISTER_VALUE* RegisterValues)) \ + + +#define LIST_WINHVEMULATION_FUNCTIONS(X) \ + X(HRESULT, WHvEmulatorCreateEmulator, (const WHV_EMULATOR_CALLBACKS* Callbacks, WHV_EMULATOR_HANDLE* Emulator)) \ + X(HRESULT, WHvEmulatorDestroyEmulator, (WHV_EMULATOR_HANDLE Emulator)) \ + X(HRESULT, WHvEmulatorTryIoEmulation, (WHV_EMULATOR_HANDLE Emulator, VOID* Context, const WHV_VP_EXIT_CONTEXT* VpContext, const WHV_X64_IO_PORT_ACCESS_CONTEXT* IoInstructionContext, WHV_EMULATOR_STATUS* EmulatorReturnStatus)) \ + X(HRESULT, WHvEmulatorTryMmioEmulation, (WHV_EMULATOR_HANDLE Emulator, VOID* Context, const WHV_VP_EXIT_CONTEXT* VpContext, const WHV_MEMORY_ACCESS_CONTEXT* MmioInstructionContext, WHV_EMULATOR_STATUS* EmulatorReturnStatus)) \ + + +#define WHP_DEFINE_TYPE(return_type, function_name, signature) \ + typedef return_type (WINAPI *function_name ## _t) signature; + +#define WHP_DECLARE_MEMBER(return_type, function_name, signature) \ + function_name ## _t function_name; + +/* Define function typedef */ +LIST_WINHVPLATFORM_FUNCTIONS(WHP_DEFINE_TYPE) +LIST_WINHVEMULATION_FUNCTIONS(WHP_DEFINE_TYPE) + +struct WHPDispatch { + LIST_WINHVPLATFORM_FUNCTIONS(WHP_DECLARE_MEMBER) + LIST_WINHVEMULATION_FUNCTIONS(WHP_DECLARE_MEMBER) +}; + +extern struct WHPDispatch whp_dispatch; + +bool init_whp_dispatch(void); + + +#endif /* WHP_DISPATCH_H */ -- cgit v1.2.3 From e1753a7e1d8174f5861367504c5cea5fbcd85953 Mon Sep 17 00:00:00 2001 From: "Justin Terry (VM)" Date: Tue, 5 Jun 2018 22:15:27 +0000 Subject: WHPX workaround bug in OSVW handling Adds a workaround to an incorrect value setting CPUID Fn8000_0001_ECX[bit 9 OSVW] = 1. This can cause a guest linux kernel to panic when an issue to rdmsr C001_0140h returns 0. Disabling this feature correctly allows the guest to boot without accessing the osv workarounds. Signed-off-by: Justin Terry (VM) Message-Id: <20180605221500.21674-1-juterry@microsoft.com> Signed-off-by: Paolo Bonzini --- target/i386/whpx-all.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) (limited to 'target') diff --git a/target/i386/whpx-all.c b/target/i386/whpx-all.c index 6b42096698..99501bac57 100644 --- a/target/i386/whpx-all.c +++ b/target/i386/whpx-all.c @@ -961,6 +961,16 @@ static int whpx_vcpu_run(CPUState *cpu) vcpu->exit_ctx.CpuidAccess.DefaultResultRcx | CPUID_EXT_HYPERVISOR; + rdx = vcpu->exit_ctx.CpuidAccess.DefaultResultRdx; + rbx = vcpu->exit_ctx.CpuidAccess.DefaultResultRbx; + break; + case 0x80000001: + rax = vcpu->exit_ctx.CpuidAccess.DefaultResultRax; + /* Remove any support of OSVW */ + rcx = + vcpu->exit_ctx.CpuidAccess.DefaultResultRcx & + ~CPUID_EXT3_OSVW; + rdx = vcpu->exit_ctx.CpuidAccess.DefaultResultRdx; rbx = vcpu->exit_ctx.CpuidAccess.DefaultResultRbx; break; @@ -1382,12 +1392,13 @@ static int whpx_accel_init(MachineState *ms) goto error; } - UINT32 cpuidExitList[] = {1}; + UINT32 cpuidExitList[] = {1, 0x80000001}; hr = whp_dispatch.WHvSetPartitionProperty( whpx->partition, WHvPartitionPropertyCodeCpuidExitList, cpuidExitList, RTL_NUMBER_OF(cpuidExitList) * sizeof(UINT32)); + if (FAILED(hr)) { error_report("WHPX: Failed to set partition CpuidExitList hr=%08lx", hr); -- cgit v1.2.3 From e7ca549fc8caf9b1c79814f3854622448815f2bf Mon Sep 17 00:00:00 2001 From: "Justin Terry (VM)" Date: Tue, 5 Jun 2018 22:15:28 +0000 Subject: WHPX: register for unrecognized MSR exits Some variations of Linux kernels end up accessing MSR's that the Windows Hypervisor doesn't implement which causes a GP to be returned to the guest. This fix registers QEMU for unimplemented MSR access and globally returns 0 on reads and ignores writes. This behavior is allows the Linux kernel to probe the MSR with a write/read/check sequence it does often without failing the access. Signed-off-by: Justin Terry (VM) Message-Id: <20180605221500.21674-2-juterry@microsoft.com> Signed-off-by: Paolo Bonzini --- target/i386/whpx-all.c | 41 ++++++++++++++++++++++++++++++++++++++--- 1 file changed, 38 insertions(+), 3 deletions(-) (limited to 'target') diff --git a/target/i386/whpx-all.c b/target/i386/whpx-all.c index 99501bac57..57e53e1f1f 100644 --- a/target/i386/whpx-all.c +++ b/target/i386/whpx-all.c @@ -932,6 +932,7 @@ static int whpx_vcpu_run(CPUState *cpu) case WHvRunVpExitReasonX64InterruptWindow: vcpu->window_registered = 0; + ret = 0; break; case WHvRunVpExitReasonX64Halt: @@ -943,6 +944,40 @@ static int whpx_vcpu_run(CPUState *cpu) ret = 1; break; + case WHvRunVpExitReasonX64MsrAccess: { + WHV_REGISTER_VALUE reg_values[3] = {0}; + WHV_REGISTER_NAME reg_names[3]; + UINT32 reg_count; + + reg_names[0] = WHvX64RegisterRip; + reg_names[1] = WHvX64RegisterRax; + reg_names[2] = WHvX64RegisterRdx; + + reg_values[0].Reg64 = + vcpu->exit_ctx.VpContext.Rip + + vcpu->exit_ctx.VpContext.InstructionLength; + + /* + * For all unsupported MSR access we: + * ignore writes + * return 0 on read. + */ + reg_count = vcpu->exit_ctx.MsrAccess.AccessInfo.IsWrite ? + 1 : 3; + + hr = whp_dispatch.WHvSetVirtualProcessorRegisters( + whpx->partition, + cpu->cpu_index, + reg_names, reg_count, + reg_values); + + if (FAILED(hr)) { + error_report("WHPX: Failed to set MsrAccess state " + " registers, hr=%08lx", hr); + } + ret = 0; + break; + } case WHvRunVpExitReasonX64Cpuid: { WHV_REGISTER_VALUE reg_values[5]; WHV_REGISTER_NAME reg_names[5]; @@ -1010,7 +1045,6 @@ static int whpx_vcpu_run(CPUState *cpu) case WHvRunVpExitReasonUnrecoverableException: case WHvRunVpExitReasonInvalidVpRegisterValue: case WHvRunVpExitReasonUnsupportedFeature: - case WHvRunVpExitReasonX64MsrAccess: case WHvRunVpExitReasonException: default: error_report("WHPX: Unexpected VP exit code %d", @@ -1378,6 +1412,7 @@ static int whpx_accel_init(MachineState *ms) } memset(&prop, 0, sizeof(WHV_PARTITION_PROPERTY)); + prop.ExtendedVmExits.X64MsrExit = 1; prop.ExtendedVmExits.X64CpuidExit = 1; hr = whp_dispatch.WHvSetPartitionProperty( whpx->partition, @@ -1386,8 +1421,8 @@ static int whpx_accel_init(MachineState *ms) sizeof(WHV_PARTITION_PROPERTY)); if (FAILED(hr)) { - error_report("WHPX: Failed to enable partition extended X64CpuidExit" - " hr=%08lx", hr); + error_report("WHPX: Failed to enable partition extended X64MsrExit and" + " X64CpuidExit hr=%08lx", hr); ret = -EINVAL; goto error; } -- cgit v1.2.3 From 02f7fd25a446a220905c2e5cb0fc3655d7f63b29 Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Tue, 3 Apr 2018 17:36:11 +0200 Subject: target-i386: Add NMI interception to SVM Check for SVM interception prior to injecting an NMI. Tested via the Jailhouse hypervisor. Signed-off-by: Jan Kiszka Message-Id: Signed-off-by: Paolo Bonzini --- target/i386/seg_helper.c | 1 + 1 file changed, 1 insertion(+) (limited to 'target') diff --git a/target/i386/seg_helper.c b/target/i386/seg_helper.c index 600a4d7586..00301a0c04 100644 --- a/target/i386/seg_helper.c +++ b/target/i386/seg_helper.c @@ -1337,6 +1337,7 @@ bool x86_cpu_exec_interrupt(CPUState *cs, int interrupt_request) ret = true; } else if ((interrupt_request & CPU_INTERRUPT_NMI) && !(env->hflags2 & HF2_NMI_MASK)) { + cpu_svm_check_intercept_param(env, SVM_EXIT_NMI, 0, 0); cs->interrupt_request &= ~CPU_INTERRUPT_NMI; env->hflags2 |= HF2_NMI_MASK; do_interrupt_x86_hardirq(env, EXCP02_NMI, 1); -- cgit v1.2.3 From df2518aa587a0157bbfbc635fe47295629d9914a Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Tue, 3 Apr 2018 17:36:12 +0200 Subject: target-i386: Allow interrupt injection after STGI We need to terminate the translation block after STGI so that pending interrupts can be injected. This fixes pending NMI injection for Jailhouse which uses "stgi; clgi" to open a brief injection window. Signed-off-by: Jan Kiszka Message-Id: <37939b244dda0e9cccf96ce50f2b15df1e48315d.1522769774.git.jan.kiszka@web.de> Signed-off-by: Paolo Bonzini --- target/i386/translate.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'target') diff --git a/target/i386/translate.c b/target/i386/translate.c index c91849417b..07d185e7b6 100644 --- a/target/i386/translate.c +++ b/target/i386/translate.c @@ -7444,8 +7444,9 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu) break; } gen_update_cc_op(s); - gen_jmp_im(pc_start - s->cs_base); gen_helper_stgi(cpu_env); + gen_jmp_im(s->pc - s->cs_base); + gen_eob(s); break; case 0xdd: /* CLGI */ -- cgit v1.2.3 From 50b3de6e5cd464dcc20e3a48f5a09e0299a184ac Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Tue, 3 Apr 2018 17:36:13 +0200 Subject: target-i386: Mark cpu_vmexit noreturn It calls cpu_loop_exit in system emulation mode (and should never be called in user emulation mode). Signed-off-by: Jan Kiszka Message-Id: <6f4d44ffde55d074cbceb48309c1678600abad2f.1522769774.git.jan.kiszka@web.de> Signed-off-by: Paolo Bonzini --- target/i386/cpu.h | 4 ++-- target/i386/svm_helper.c | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) (limited to 'target') diff --git a/target/i386/cpu.h b/target/i386/cpu.h index 89c82be8d2..16c59b7099 100644 --- a/target/i386/cpu.h +++ b/target/i386/cpu.h @@ -1840,8 +1840,8 @@ void helper_lock_init(void); /* svm_helper.c */ void cpu_svm_check_intercept_param(CPUX86State *env1, uint32_t type, uint64_t param, uintptr_t retaddr); -void cpu_vmexit(CPUX86State *nenv, uint32_t exit_code, uint64_t exit_info_1, - uintptr_t retaddr); +void QEMU_NORETURN cpu_vmexit(CPUX86State *nenv, uint32_t exit_code, + uint64_t exit_info_1, uintptr_t retaddr); void do_vmexit(CPUX86State *env, uint32_t exit_code, uint64_t exit_info_1); /* seg_helper.c */ diff --git a/target/i386/svm_helper.c b/target/i386/svm_helper.c index 350492359c..f245aec310 100644 --- a/target/i386/svm_helper.c +++ b/target/i386/svm_helper.c @@ -62,6 +62,7 @@ void helper_invlpga(CPUX86State *env, int aflag) void cpu_vmexit(CPUX86State *nenv, uint32_t exit_code, uint64_t exit_info_1, uintptr_t retaddr) { + assert(0); } void helper_svm_check_intercept_param(CPUX86State *env, uint32_t type, -- cgit v1.2.3 From 0c8465440d50c18a7bb13d0a866748f0593e193a Mon Sep 17 00:00:00 2001 From: Peter Xu Date: Fri, 29 Dec 2017 15:31:04 +0800 Subject: hmp: obsolete "info ioapic" Let's start to use "info pic" just like other platforms. For now we keep the command for a while so that old users can know what is the new command to use. Signed-off-by: Peter Xu Message-Id: <20171229073104.3810-6-peterx@redhat.com> Signed-off-by: Paolo Bonzini --- target/i386/monitor.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) (limited to 'target') diff --git a/target/i386/monitor.c b/target/i386/monitor.c index a890b3c2ab..6bbb3a96cd 100644 --- a/target/i386/monitor.c +++ b/target/i386/monitor.c @@ -658,12 +658,8 @@ void hmp_info_local_apic(Monitor *mon, const QDict *qdict) void hmp_info_io_apic(Monitor *mon, const QDict *qdict) { - if (kvm_irqchip_in_kernel() && - !kvm_irqchip_is_split()) { - kvm_ioapic_dump_state(mon, qdict); - } else { - ioapic_dump_state(mon, qdict); - } + monitor_printf(mon, "This command is obsolete and will be " + "removed soon. Please use 'info pic' instead.\n"); } SevInfo *qmp_query_sev(Error **errp) -- cgit v1.2.3 From 6f131f13e68d648a8e4f083c667ab1acd88ce4cd Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Fri, 22 Jun 2018 22:22:05 +0300 Subject: kvm: support -overcommit cpu-pm=on|off With this flag, kvm allows guest to control host CPU power state. This increases latency for other processes using same host CPU in an unpredictable way, but if decreases idle entry/exit times for the running VCPU, so to use it QEMU needs a hint about whether host CPU is overcommitted, hence the flag name. Follow-up patches will expose this capability to guest (using mwait leaf). Based on a patch by Wanpeng Li . Signed-off-by: Michael S. Tsirkin Message-Id: <20180622192148.178309-2-mst@redhat.com> Signed-off-by: Paolo Bonzini --- target/i386/kvm.c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) (limited to 'target') diff --git a/target/i386/kvm.c b/target/i386/kvm.c index 2d174f3a91..dc991f6aca 100644 --- a/target/i386/kvm.c +++ b/target/i386/kvm.c @@ -1387,6 +1387,29 @@ int kvm_arch_init(MachineState *ms, KVMState *s) smram_machine_done.notify = register_smram_listener; qemu_add_machine_init_done_notifier(&smram_machine_done); } + + if (enable_cpu_pm) { + int disable_exits = kvm_check_extension(s, KVM_CAP_X86_DISABLE_EXITS); + int ret; + +/* Work around for kernel header with a typo. TODO: fix header and drop. */ +#if defined(KVM_X86_DISABLE_EXITS_HTL) && !defined(KVM_X86_DISABLE_EXITS_HLT) +#define KVM_X86_DISABLE_EXITS_HLT KVM_X86_DISABLE_EXITS_HTL +#endif + if (disable_exits) { + disable_exits &= (KVM_X86_DISABLE_EXITS_MWAIT | + KVM_X86_DISABLE_EXITS_HLT | + KVM_X86_DISABLE_EXITS_PAUSE); + } + + ret = kvm_vm_enable_cap(s, KVM_CAP_X86_DISABLE_EXITS, 0, + disable_exits); + if (ret < 0) { + error_report("kvm: guest stopping CPU not supported: %s", + strerror(-ret)); + } + } + return 0; } -- cgit v1.2.3 From 2266d44311321a833d569cd4deb46cca6021d0e7 Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Fri, 22 Jun 2018 22:22:05 +0300 Subject: 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 Reviewed-by: Eduardo Habkost Message-Id: <20180622192148.178309-3-mst@redhat.com> Signed-off-by: Paolo Bonzini --- target/i386/cpu.c | 32 ++++++++++++++++++++++---------- target/i386/cpu.h | 9 +++++++++ target/i386/kvm.c | 9 +++++++++ 3 files changed, 40 insertions(+), 10 deletions(-) (limited to 'target') diff --git a/target/i386/cpu.c b/target/i386/cpu.c index e6c2f8a22a..1e6a7d0a75 100644 --- a/target/i386/cpu.c +++ b/target/i386/cpu.c @@ -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; diff --git a/target/i386/cpu.h b/target/i386/cpu.h index 16c59b7099..8eaefeee3e 100644 --- a/target/i386/cpu.h +++ b/target/i386/cpu.h @@ -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]; diff --git a/target/i386/kvm.c b/target/i386/kvm.c index dc991f6aca..c5f72d645b 100644 --- a/target/i386/kvm.c +++ b/target/i386/kvm.c @@ -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) { -- cgit v1.2.3