mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-11 12:28:41 +08:00
KVM: arm/arm64: timer: Allow the timer to control the active state
In order to remove the crude hack where we sneak the masked bit into the timer's control register, make use of the phys_irq_map API control the active state of the interrupt. This causes some limited changes to allow for potential error propagation. Reviewed-by: Christoffer Dall <christoffer.dall@linaro.org> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
This commit is contained in:
parent
773299a570
commit
f120cd6533
@ -77,7 +77,5 @@ int kvm_reset_vcpu(struct kvm_vcpu *vcpu)
|
||||
kvm_reset_coprocs(vcpu);
|
||||
|
||||
/* Reset arch_timer context */
|
||||
kvm_timer_vcpu_reset(vcpu, cpu_vtimer_irq);
|
||||
|
||||
return 0;
|
||||
return kvm_timer_vcpu_reset(vcpu, cpu_vtimer_irq);
|
||||
}
|
||||
|
@ -121,7 +121,5 @@ int kvm_reset_vcpu(struct kvm_vcpu *vcpu)
|
||||
kvm_reset_sys_regs(vcpu);
|
||||
|
||||
/* Reset timer */
|
||||
kvm_timer_vcpu_reset(vcpu, cpu_vtimer_irq);
|
||||
|
||||
return 0;
|
||||
return kvm_timer_vcpu_reset(vcpu, cpu_vtimer_irq);
|
||||
}
|
||||
|
@ -52,13 +52,16 @@ struct arch_timer_cpu {
|
||||
|
||||
/* Timer IRQ */
|
||||
const struct kvm_irq_level *irq;
|
||||
|
||||
/* VGIC mapping */
|
||||
struct irq_phys_map *map;
|
||||
};
|
||||
|
||||
int kvm_timer_hyp_init(void);
|
||||
void kvm_timer_enable(struct kvm *kvm);
|
||||
void kvm_timer_init(struct kvm *kvm);
|
||||
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);
|
||||
void kvm_timer_vcpu_init(struct kvm_vcpu *vcpu);
|
||||
void kvm_timer_flush_hwstate(struct kvm_vcpu *vcpu);
|
||||
void kvm_timer_sync_hwstate(struct kvm_vcpu *vcpu);
|
||||
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user