From: Haibin Wang wanghaibin.wang@huawei.com
virt inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I8URKX CVE: NA
------------------------------------------------------------------
Support vtimer irqbypass.
Signed-off-by: Zenghui Yu yuzenghui@huawei.com Signed-off-by: Haibin Wang wanghaibin.wang@huawei.com Signed-off-by: Kunkun Jiang jiangkunkun@huawei.com Signed-off-by: Dongxu Sun sundongxu3@huawei.com --- arch/arm64/kvm/arch_timer.c | 49 +++++++++++++++++++++++++++++++++++- arch/arm64/kvm/arm.c | 4 +++ include/kvm/arm_arch_timer.h | 1 + 3 files changed, 53 insertions(+), 1 deletion(-)
diff --git a/arch/arm64/kvm/arch_timer.c b/arch/arm64/kvm/arch_timer.c index 8601bc569c49..0d800445d85f 100644 --- a/arch/arm64/kvm/arch_timer.c +++ b/arch/arm64/kvm/arch_timer.c @@ -978,6 +978,15 @@ int kvm_timer_vcpu_reset(struct kvm_vcpu *vcpu) }
if (timer->enabled) { + if (vtimer_is_irqbypass()) { + kvm_timer_update_irq(vcpu, false, vcpu_ptimer(vcpu)); + + if (irqchip_in_kernel(vcpu->kvm) && map.direct_ptimer) + kvm_vgic_reset_mapped_irq(vcpu, timer_irq(map.direct_ptimer)); + + goto skip_reset_vtimer; + } + for (int i = 0; i < nr_timers(vcpu); i++) kvm_timer_update_irq(vcpu, false, vcpu_get_timer(vcpu, i)); @@ -991,6 +1000,8 @@ int kvm_timer_vcpu_reset(struct kvm_vcpu *vcpu)
if (map.emul_vtimer) soft_timer_cancel(&map.emul_vtimer->hrtimer); + +skip_reset_vtimer: if (map.emul_ptimer) soft_timer_cancel(&map.emul_ptimer->hrtimer);
@@ -1553,15 +1564,47 @@ static bool kvm_arch_timer_get_input_level(int vintid) return false; }
+static void vtimer_set_active_stat(struct kvm_vcpu *vcpu, int vintid, bool set) +{ +} + +static bool vtimer_get_active_stat(struct kvm_vcpu *vcpu, int vintid) +{ + return false; +} + +int kvm_vtimer_config(struct kvm_vcpu *vcpu) +{ + struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu; + int intid; + + if (!vtimer_is_irqbypass()) + return 0; + + if (timer->enabled) + return 0; + + if (!irqchip_in_kernel(vcpu->kvm)) + return -EINVAL; + + intid = timer_irq(vcpu_vtimer(vcpu)); + return kvm_vgic_config_vtimer_irqbypass(vcpu, intid, + vtimer_get_active_stat, + vtimer_set_active_stat); +} + int kvm_timer_enable(struct kvm_vcpu *vcpu) { struct arch_timer_cpu *timer = vcpu_timer(vcpu); struct timer_map map; - int ret; + int ret = 0;
if (timer->enabled) return 0;
+ if (!irqchip_in_kernel(vcpu->kvm) && vtimer_is_irqbypass()) + return -EINVAL; + /* Without a VGIC we do not map virtual IRQs to physical IRQs */ if (!irqchip_in_kernel(vcpu->kvm)) goto no_vgic; @@ -1577,6 +1620,9 @@ int kvm_timer_enable(struct kvm_vcpu *vcpu)
get_timer_map(vcpu, &map);
+ if (vtimer_is_irqbypass()) + goto skip_map_vtimer; + ret = kvm_vgic_map_phys_irq(vcpu, map.direct_vtimer->host_timer_irq, timer_irq(map.direct_vtimer), @@ -1584,6 +1630,7 @@ int kvm_timer_enable(struct kvm_vcpu *vcpu) if (ret) return ret;
+skip_map_vtimer: if (map.direct_ptimer) { ret = kvm_vgic_map_phys_irq(vcpu, map.direct_ptimer->host_timer_irq, diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c index 4866b3f7b4ea..0377276b7d28 100644 --- a/arch/arm64/kvm/arm.c +++ b/arch/arm64/kvm/arm.c @@ -603,6 +603,10 @@ int kvm_arch_vcpu_run_pid_change(struct kvm_vcpu *vcpu)
kvm_arm_vcpu_init_debug(vcpu);
+ ret = kvm_vtimer_config(vcpu); + if (ret) + return ret; + if (likely(irqchip_in_kernel(kvm))) { /* * Map the VGIC hardware resources before running a vcpu the diff --git a/include/kvm/arm_arch_timer.h b/include/kvm/arm_arch_timer.h index e748bc957d83..ae5e24d589e3 100644 --- a/include/kvm/arm_arch_timer.h +++ b/include/kvm/arm_arch_timer.h @@ -96,6 +96,7 @@ struct arch_timer_cpu {
int __init kvm_timer_hyp_init(bool has_gic); int kvm_timer_enable(struct kvm_vcpu *vcpu); +int kvm_vtimer_config(struct kvm_vcpu *vcpu); int kvm_timer_vcpu_reset(struct kvm_vcpu *vcpu); void kvm_timer_vcpu_init(struct kvm_vcpu *vcpu); void kvm_timer_sync_user(struct kvm_vcpu *vcpu);