|
@@ -64,10 +64,10 @@ static void kvm_timer_inject_irq(struct kvm_vcpu *vcpu)
|
|
|
int ret;
|
|
|
struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu;
|
|
|
|
|
|
- timer->cntv_ctl |= ARCH_TIMER_CTRL_IT_MASK;
|
|
|
- ret = kvm_vgic_inject_irq(vcpu->kvm, vcpu->vcpu_id,
|
|
|
- timer->irq->irq,
|
|
|
- timer->irq->level);
|
|
|
+ kvm_vgic_set_phys_irq_active(timer->map, true);
|
|
|
+ ret = kvm_vgic_inject_mapped_irq(vcpu->kvm, vcpu->vcpu_id,
|
|
|
+ timer->map,
|
|
|
+ timer->irq->level);
|
|
|
WARN_ON(ret);
|
|
|
}
|
|
|
|
|
@@ -117,7 +117,8 @@ bool kvm_timer_should_fire(struct kvm_vcpu *vcpu)
|
|
|
cycle_t cval, now;
|
|
|
|
|
|
if ((timer->cntv_ctl & ARCH_TIMER_CTRL_IT_MASK) ||
|
|
|
- !(timer->cntv_ctl & ARCH_TIMER_CTRL_ENABLE))
|
|
|
+ !(timer->cntv_ctl & ARCH_TIMER_CTRL_ENABLE) ||
|
|
|
+ kvm_vgic_get_phys_irq_active(timer->map))
|
|
|
return false;
|
|
|
|
|
|
cval = timer->cntv_cval;
|
|
@@ -184,10 +185,11 @@ void kvm_timer_sync_hwstate(struct kvm_vcpu *vcpu)
|
|
|
timer_arm(timer, ns);
|
|
|
}
|
|
|
|
|
|
-void kvm_timer_vcpu_reset(struct kvm_vcpu *vcpu,
|
|
|
- const struct kvm_irq_level *irq)
|
|
|
+int kvm_timer_vcpu_reset(struct kvm_vcpu *vcpu,
|
|
|
+ const struct kvm_irq_level *irq)
|
|
|
{
|
|
|
struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu;
|
|
|
+ struct irq_phys_map *map;
|
|
|
|
|
|
/*
|
|
|
* The vcpu timer irq number cannot be determined in
|
|
@@ -196,6 +198,17 @@ void kvm_timer_vcpu_reset(struct kvm_vcpu *vcpu,
|
|
|
* vcpu timer irq number when the vcpu is reset.
|
|
|
*/
|
|
|
timer->irq = irq;
|
|
|
+
|
|
|
+ /*
|
|
|
+ * Tell the VGIC that the virtual interrupt is tied to a
|
|
|
+ * physical interrupt. We do that once per VCPU.
|
|
|
+ */
|
|
|
+ map = kvm_vgic_map_phys_irq(vcpu, irq->irq, host_vtimer_irq);
|
|
|
+ if (WARN_ON(IS_ERR(map)))
|
|
|
+ return PTR_ERR(map);
|
|
|
+
|
|
|
+ timer->map = map;
|
|
|
+ return 0;
|
|
|
}
|
|
|
|
|
|
void kvm_timer_vcpu_init(struct kvm_vcpu *vcpu)
|
|
@@ -335,6 +348,8 @@ void kvm_timer_vcpu_terminate(struct kvm_vcpu *vcpu)
|
|
|
struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu;
|
|
|
|
|
|
timer_disarm(timer);
|
|
|
+ if (timer->map)
|
|
|
+ kvm_vgic_unmap_phys_irq(vcpu, timer->map);
|
|
|
}
|
|
|
|
|
|
void kvm_timer_enable(struct kvm *kvm)
|