/** * kvm_timer_sync_hwstate - sync timer state from cpu * @vcpu: The vcpu pointer * * Check if the virtual timer was armed and either schedule a corresponding * soft timer or inject directly if already expired. */ void kvm_timer_sync_hwstate(struct kvm_vcpu *vcpu) { struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu; cycle_t cval, now; u64 ns; if ((timer->cntv_ctl & ARCH_TIMER_CTRL_IT_MASK) || !(timer->cntv_ctl & ARCH_TIMER_CTRL_ENABLE)) return; cval = timer->cntv_cval; now = kvm_phys_timer_read() - vcpu->kvm->arch.timer.cntvoff; BUG_ON(timer_is_armed(timer)); if (cval <= now) { /* * Timer has already expired while we were not * looking. Inject the interrupt and carry on. */ kvm_timer_inject_irq(vcpu); return; } ns = cyclecounter_cyc2ns(timecounter->cc, cval - now); timer_arm(timer, ns); }
/* * Schedule the background timer before calling kvm_vcpu_block, so that this * thread is removed from its waitqueue and made runnable when there's a timer * interrupt to handle. */ void kvm_timer_schedule(struct kvm_vcpu *vcpu) { struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu; u64 ns; cycle_t cval, now; BUG_ON(timer_is_armed(timer)); /* * No need to schedule a background timer if the guest timer has * already expired, because kvm_vcpu_block will return before putting * the thread to sleep. */ if (kvm_timer_should_fire(vcpu)) return; /* * If the timer is not capable of raising interrupts (disabled or * masked), then there's no more work for us to do. */ if (!kvm_timer_irq_can_fire(vcpu)) return; /* The timer has not yet expired, schedule a background timer */ cval = timer->cntv_cval; now = kvm_phys_timer_read() - vcpu->kvm->arch.timer.cntvoff; ns = cyclecounter_cyc2ns(timecounter->cc, cval - now, timecounter->mask, &timecounter->frac); timer_arm(timer, ns); }
static void timer_disarm(struct arch_timer_cpu *timer) { if (timer_is_armed(timer)) { hrtimer_cancel(&timer->timer); cancel_work_sync(&timer->expired); timer->armed = false; } }
/** * kvm_timer_sync_hwstate - sync timer state from cpu * @vcpu: The vcpu pointer * * Check if the virtual timer has expired while we were running in the guest, * and inject an interrupt if that was the case. */ void kvm_timer_sync_hwstate(struct kvm_vcpu *vcpu) { struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu; BUG_ON(timer_is_armed(timer)); /* * The guest could have modified the timer registers or the timer * could have expired, update the timer state. */ kvm_timer_update_state(vcpu); }