@@ -1544,6 +1544,32 @@ static int kvm_arm_handle_hypercall(ARMCPU *cpu,
return 0;
}
+/*
+ * It would be perfectly fine to immediately return from any WFE/WFI
+ * trap however that would mean we spend a lot of time bouncing
+ * between the hypervisor and QEMU when things are idle.
+ */
+
+static const char * wfx_insn[] = {
+ "WFI",
+ "WFE",
+ "WFIT",
+ "WFET"
+};
+
+static int kvm_arm_handle_wfx(CPUState *cs, int esr_iss)
+{
+ int ti = extract32(esr_iss, 0, 2);
+ ARMCPU *cpu = ARM_CPU(cs);
+ CPUARMState *env = &cpu->env;
+
+ trace_kvm_wfx_trap(cs->cpu_index, wfx_insn[ti], env->pc);
+
+ /* stop the CPU, return to the top of the loop */
+ cs->stop = true;
+ return EXCP_YIELD;
+}
+
/**
* kvm_arm_handle_hard_trap:
* @cpu: ARMCPU
@@ -1582,6 +1608,8 @@ static int kvm_arm_handle_hard_trap(ARMCPU *cpu,
case EC_AA64_HVC:
case EC_AA64_SMC:
return kvm_arm_handle_hypercall(cpu, esr_ec);
+ case EC_WFX_TRAP:
+ return kvm_arm_handle_wfx(cs, esr_iss);
default:
qemu_log_mask(LOG_UNIMP, "%s: unhandled EC: %x/%x/%x/%d\n",
__func__, esr_ec, esr_iss, esr_iss2, esr_il);
@@ -16,3 +16,4 @@ kvm_arm_fixup_msi_route(uint64_t iova, uint64_t gpa) "MSI iova = 0x%"PRIx64" is
kvm_sysreg_read(const char *name, uint64_t val) "%s => 0x%" PRIx64
kvm_sysreg_write(const char *name, uint64_t val) "%s <= 0x%" PRIx64
kvm_hypercall(int ec, uint64_t arg0) "%d: %"PRIx64
+kvm_wfx_trap(int vcpu, const char *insn, uint64_t vaddr) "%d: %s @ 0x%" PRIx64
This allows the vCPU guest core to go to sleep on a WFx instruction. Signed-off-by: Alex Bennée <alex.bennee@linaro.org> --- target/arm/kvm.c | 28 ++++++++++++++++++++++++++++ target/arm/trace-events | 1 + 2 files changed, 29 insertions(+)