29
#include "hw/core/irq.h"
30
#include "hw/arm/virt.h"
31
#include "qemu/main-loop.h"
32
+#include "qemu/timer.h"
33
#include "system/cpus.h"
34
#include "arm-powerctl.h"
35
#include "target/arm/cpu.h"
309
#define TMR_CTL_IMASK (1 << 1)
310
#define TMR_CTL_ISTATUS (1 << 2)
311
312
+static void hvf_wfi_timer_cb(void *opaque);
313
+
314
static uint32_t chosen_ipa_bit_size;
315
316
typedef struct HVFVTimer {
1299
{
1300
hv_return_t ret;
1301
1302
+ if (!hvf_irqchip_in_kernel()) {
1303
+ timer_free(cpu->accel->wfi_timer);
1304
+ cpu->accel->wfi_timer = NULL;
1305
+ }
1306
+
1307
ret = hv_vcpu_destroy(cpu->accel->fd);
1308
assert_hvf_ok(ret);
1309
}
1495
arm_cpu->isar.idregs[ID_AA64MMFR0_EL1_IDX]);
1496
assert_hvf_ok(ret);
1497
1498
+ if (!hvf_irqchip_in_kernel()) {
1499
+ cpu->accel->wfi_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL,
1500
+ hvf_wfi_timer_cb, cpu);
1501
+ }
1502
+
1503
aarch64_add_sme_properties(OBJECT(cpu));
1504
return 0;
1505
}
2207
return mach_absolute_time() - hvf_state->vtimer_offset;
2208
}
2209
2210
+static void hvf_wfi_timer_cb(void *opaque)
2211
+{
2212
+ CPUState *cpu = opaque;
2213
+ ARMCPU *arm_cpu = ARM_CPU(cpu);
2214
+
2215
+ /*
2216
+ * vtimer expired while the CPU was halted for WFI.
2217
+ * Mirror HV_EXIT_REASON_VTIMER_ACTIVATED: raise the vtimer
2218
+ * interrupt and mark as masked so hvf_sync_vtimer() will
2219
+ * check and unmask when the guest handles it.
2220
+ *
2221
+ * The interrupt delivery chain (GIC -> cpu_interrupt ->
2222
+ * qemu_cpu_kick) wakes the vCPU thread from halt_cond.
2223
+ */
2224
+ qemu_set_irq(arm_cpu->gt_timer_outputs[GTIMER_VIRT], 1);
2225
+ cpu->accel->vtimer_masked = true;
2226
+}
2227
+
2228
+/*
2229
+ * Arm a host-side QEMU_CLOCK_VIRTUAL timer to fire when the guest's
2230
+ * vtimer (CNTV_CVAL_EL0) is scheduled to expire. HVF only delivers
2231
+ * HV_EXIT_REASON_VTIMER_ACTIVATED during hv_vcpu_run(), which we won't
2232
+ * call while the vCPU is halted, so we need this to wake the vCPU.
2233
+ *
2234
+ * QEMU_CLOCK_VIRTUAL pauses while the VM is stopped, which keeps the
2235
+ * timer in lockstep with the guest's view of vtime across pause/resume.
2236
+ *
2237
+ * Caller must supply the current CNTV_CTL_EL0 and CNTV_CVAL_EL0 values,
2238
+ * since the appropriate source (HVF vs. env) depends on context.
2239
+ *
2240
+ * Returns 0 if the timer was armed (or if the vtimer is disabled/masked
2241
+ * and the vCPU should still halt waiting on another event), or -1 if
2242
+ * the vtimer has already expired.
2243
+ */
2244
+static int hvf_arm_wfi_timer(CPUState *cpu, uint64_t ctl, uint64_t cval)
2245
+{
2246
+ ARMCPU *arm_cpu = ARM_CPU(cpu);
2247
+ uint64_t now;
2248
+ int64_t delta_ns;
2249
+
2250
+ if (!(ctl & TMR_CTL_ENABLE) || (ctl & TMR_CTL_IMASK)) {
2251
+ return 0;
2252
+ }
2253
+
2254
+ now = hvf_vtimer_val_raw();
2255
+ if (cval <= now) {
2256
+ return -1;
2257
+ }
2258
+
2259
+ delta_ns = muldiv64(cval - now, NANOSECONDS_PER_SECOND,
2260
+ arm_cpu->gt_cntfrq_hz);
2261
+ timer_mod(cpu->accel->wfi_timer,
2262
+ qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + delta_ns);
2263
+ return 0;
2264
+}
2265
+
2266
static int hvf_wfi(CPUState *cpu)
2267
{
2268
if (cpu_has_work(cpu)) {
2273
return 0;
2274
}
2275
2276
+ if (!hvf_irqchip_in_kernel()) {
2277
+ uint64_t ctl, cval;
2278
+ hv_return_t r;
2279
+
2280
+ /*
2281
+ * Read the vtimer state directly from HVF. We're on the vCPU
2282
+ * thread, just exited from hv_vcpu_run(), so HVF holds the
2283
+ * authoritative values and env may be stale.
2284
+ */
2285
+ r = hv_vcpu_get_sys_reg(cpu->accel->fd, HV_SYS_REG_CNTV_CTL_EL0,
2286
+ &ctl);
2287
+ assert_hvf_ok(r);
2288
+ r = hv_vcpu_get_sys_reg(cpu->accel->fd, HV_SYS_REG_CNTV_CVAL_EL0,
2289
+ &cval);
2290
+ assert_hvf_ok(r);
2291
+
2292
+ if (hvf_arm_wfi_timer(cpu, ctl, cval) < 0) {
2293
+ /* vtimer already expired, don't halt */
2294
+ return 0;
2295
+ }
2296
+ }
2297
+
2298
+ cpu->halted = 1;
2299
return EXCP_HLT;
2300
}
2301
2594
hv_return_t r;
2595
2596
if (cpu->halted) {
2505
- return EXCP_HLT;
2597
+ if (!cpu_has_work(cpu)) {
2598
+ return EXCP_HLT;
2599
+ }
2600
+ cpu->halted = 0;
2601
+ if (!hvf_irqchip_in_kernel()) {
2602
+ timer_del(cpu->accel->wfi_timer);
2603
+ }
2604
}
2605
2606
flush_cpu_state(cpu);
2649
/* Update vtimer offset on all CPUs */
2650
hvf_state->vtimer_offset = mach_absolute_time() - s->vtimer_val;
2651
cpu_synchronize_all_states();
2652
+
2653
+ /*
2654
+ * After migration restore (or any resume), the wfi_timer is not
2655
+ * scheduled on this QEMU instance, so re-arm it for any halted
2656
+ * vCPU with a pending vtimer. For a non-migration resume the
2657
+ * QEMU_CLOCK_VIRTUAL timer was already scheduled; recomputing the
2658
+ * deadline produces the same value and is a harmless no-op.
2659
+ *
2660
+ * cpu_synchronize_all_states() above ensures env mirrors the
2661
+ * authoritative vtimer state (whether that came from HVF or from
2662
+ * the migration stream), so we can safely read it here from the
2663
+ * iothread.
2664
+ *
2665
+ * Only applies when we own the wfi_timer; with an in-kernel vGIC
2666
+ * the timer is never allocated and HVF handles vtimer wake-ups.
2667
+ */
2668
+ if (!hvf_irqchip_in_kernel()) {
2669
+ CPUState *cpu;
2670
+
2671
+ CPU_FOREACH(cpu) {
2672
+ ARMCPU *arm_cpu;
2673
+ uint64_t ctl, cval;
2674
+
2675
+ if (!cpu->accel || !cpu->halted) {
2676
+ continue;
2677
+ }
2678
+
2679
+ arm_cpu = ARM_CPU(cpu);
2680
+ ctl = arm_cpu->env.cp15.c14_timer[GTIMER_VIRT].ctl;
2681
+ cval = arm_cpu->env.cp15.c14_timer[GTIMER_VIRT].cval;
2682
+
2683
+ if (hvf_arm_wfi_timer(cpu, ctl, cval) < 0) {
2684
+ /*
2685
+ * vtimer already expired while we were paused; raise
2686
+ * the IRQ now so the halted vCPU wakes up.
2687
+ */
2688
+ hvf_wfi_timer_cb(cpu);
2689
+ }
2690
+ }
2691
+ }
2692
} else {
2693
/* Remember vtimer value on every pause */
2694
s->vtimer_val = hvf_vtimer_val_raw();