13b20eb23SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only 2edf88417SAvi Kivity /* 3edf88417SAvi Kivity * irq.c: API for in kernel interrupt controller 4edf88417SAvi Kivity * Copyright (c) 2007, Intel Corporation. 59611c187SNicolas Kaiser * Copyright 2009 Red Hat, Inc. and/or its affiliates. 6edf88417SAvi Kivity * 7edf88417SAvi Kivity * Authors: 8edf88417SAvi Kivity * Yaozu (Eddie) Dong <Eddie.dong@intel.com> 9edf88417SAvi Kivity */ 10*8d20bd63SSean Christopherson #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 11edf88417SAvi Kivity 121767e931SPaul Gortmaker #include <linux/export.h> 13edf88417SAvi Kivity #include <linux/kvm_host.h> 14edf88417SAvi Kivity 15edf88417SAvi Kivity #include "irq.h" 167837699fSSheng Yang #include "i8254.h" 178061823aSGleb Natapov #include "x86.h" 1840da8ccdSDavid Woodhouse #include "xen.h" 19edf88417SAvi Kivity 20edf88417SAvi Kivity /* 213d80840dSMarcelo Tosatti * check if there are pending timer events 223d80840dSMarcelo Tosatti * to be processed. 233d80840dSMarcelo Tosatti */ kvm_cpu_has_pending_timer(struct kvm_vcpu * vcpu)243d80840dSMarcelo Tosattiint kvm_cpu_has_pending_timer(struct kvm_vcpu *vcpu) 253d80840dSMarcelo Tosatti { 2653639526SJoao Martins int r = 0; 271e3161b4SPaolo Bonzini 2853639526SJoao Martins if (lapic_in_kernel(vcpu)) 2953639526SJoao Martins r = apic_has_pending_timer(vcpu); 3053639526SJoao Martins if (kvm_xen_timer_enabled(vcpu)) 3153639526SJoao Martins r += kvm_xen_has_pending_timer(vcpu); 3253639526SJoao Martins 3353639526SJoao Martins return r; 343d80840dSMarcelo Tosatti } 353d80840dSMarcelo Tosatti 363d80840dSMarcelo Tosatti /* 371c1a9ce9SSteve Rutherford * check if there is a pending userspace external interrupt 381c1a9ce9SSteve Rutherford */ pending_userspace_extint(struct kvm_vcpu * v)391c1a9ce9SSteve Rutherfordstatic int pending_userspace_extint(struct kvm_vcpu *v) 401c1a9ce9SSteve Rutherford { 411c1a9ce9SSteve Rutherford return v->arch.pending_external_vector != -1; 421c1a9ce9SSteve Rutherford } 431c1a9ce9SSteve Rutherford 441c1a9ce9SSteve Rutherford /* 45c7c9c56cSYang Zhang * check if there is pending interrupt from 46c7c9c56cSYang Zhang * non-APIC source without intack. 47c7c9c56cSYang Zhang */ kvm_cpu_has_extint(struct kvm_vcpu * v)4871cc849bSPaolo Bonziniint kvm_cpu_has_extint(struct kvm_vcpu *v) 49c7c9c56cSYang Zhang { 50c7c9c56cSYang Zhang /* 5172c3bcdcSPaolo Bonzini * FIXME: interrupt.injected represents an interrupt whose 5204140b41SLiran Alon * side-effects have already been applied (e.g. bit from IRR 5304140b41SLiran Alon * already moved to ISR). Therefore, it is incorrect to rely 5404140b41SLiran Alon * on interrupt.injected to know if there is a pending 5504140b41SLiran Alon * interrupt in the user-mode LAPIC. 5604140b41SLiran Alon * This leads to nVMX/nSVM not be able to distinguish 5704140b41SLiran Alon * if it should exit from L2 to L1 on EXTERNAL_INTERRUPT on 5804140b41SLiran Alon * pending interrupt or should re-inject an injected 5904140b41SLiran Alon * interrupt. 6004140b41SLiran Alon */ 6135754c98SPaolo Bonzini if (!lapic_in_kernel(v)) 6204140b41SLiran Alon return v->arch.interrupt.injected; 63c7c9c56cSYang Zhang 6440da8ccdSDavid Woodhouse if (kvm_xen_has_interrupt(v)) 6540da8ccdSDavid Woodhouse return 1; 6640da8ccdSDavid Woodhouse 6772c3bcdcSPaolo Bonzini if (!kvm_apic_accept_pic_intr(v)) 6872c3bcdcSPaolo Bonzini return 0; 6972c3bcdcSPaolo Bonzini 7072c3bcdcSPaolo Bonzini if (irqchip_split(v->kvm)) 7172c3bcdcSPaolo Bonzini return pending_userspace_extint(v); 7272c3bcdcSPaolo Bonzini else 7372c3bcdcSPaolo Bonzini return v->kvm->arch.vpic->output; 7472c3bcdcSPaolo Bonzini } 7572c3bcdcSPaolo Bonzini 7672c3bcdcSPaolo Bonzini /* 7772c3bcdcSPaolo Bonzini * check if there is injectable interrupt: 7872c3bcdcSPaolo Bonzini * when virtual interrupt delivery enabled, 7972c3bcdcSPaolo Bonzini * interrupt from apic will handled by hardware, 8072c3bcdcSPaolo Bonzini * we don't need to check it here. 8172c3bcdcSPaolo Bonzini */ kvm_cpu_has_injectable_intr(struct kvm_vcpu * v)8272c3bcdcSPaolo Bonziniint kvm_cpu_has_injectable_intr(struct kvm_vcpu *v) 8372c3bcdcSPaolo Bonzini { 84c7c9c56cSYang Zhang if (kvm_cpu_has_extint(v)) 85c7c9c56cSYang Zhang return 1; 86c7c9c56cSYang Zhang 87851c1a18SLiran Alon if (!is_guest_mode(v) && kvm_vcpu_apicv_active(v)) 88c7c9c56cSYang Zhang return 0; 89c7c9c56cSYang Zhang 90c7c9c56cSYang Zhang return kvm_apic_has_interrupt(v) != -1; /* LAPIC */ 91c7c9c56cSYang Zhang } 92ffdf7f9eSPaolo Bonzini EXPORT_SYMBOL_GPL(kvm_cpu_has_injectable_intr); 93c7c9c56cSYang Zhang 94c7c9c56cSYang Zhang /* 95edf88417SAvi Kivity * check if there is pending interrupt without 96edf88417SAvi Kivity * intack. 97edf88417SAvi Kivity */ kvm_cpu_has_interrupt(struct kvm_vcpu * v)98edf88417SAvi Kivityint kvm_cpu_has_interrupt(struct kvm_vcpu *v) 99edf88417SAvi Kivity { 100c7c9c56cSYang Zhang if (kvm_cpu_has_extint(v)) 101c7c9c56cSYang Zhang return 1; 102f3200d00SGleb Natapov 103f3200d00SGleb Natapov return kvm_apic_has_interrupt(v) != -1; /* LAPIC */ 104edf88417SAvi Kivity } 105edf88417SAvi Kivity EXPORT_SYMBOL_GPL(kvm_cpu_has_interrupt); 106edf88417SAvi Kivity 107edf88417SAvi Kivity /* 108c7c9c56cSYang Zhang * Read pending interrupt(from non-APIC source) 109c7c9c56cSYang Zhang * vector and intack. 110c7c9c56cSYang Zhang */ kvm_cpu_get_extint(struct kvm_vcpu * v)111c7c9c56cSYang Zhangstatic int kvm_cpu_get_extint(struct kvm_vcpu *v) 112c7c9c56cSYang Zhang { 11372c3bcdcSPaolo Bonzini if (!kvm_cpu_has_extint(v)) { 11472c3bcdcSPaolo Bonzini WARN_ON(!lapic_in_kernel(v)); 11572c3bcdcSPaolo Bonzini return -1; 11672c3bcdcSPaolo Bonzini } 11772c3bcdcSPaolo Bonzini 11872c3bcdcSPaolo Bonzini if (!lapic_in_kernel(v)) 11972c3bcdcSPaolo Bonzini return v->arch.interrupt.nr; 12072c3bcdcSPaolo Bonzini 12140da8ccdSDavid Woodhouse if (kvm_xen_has_interrupt(v)) 12240da8ccdSDavid Woodhouse return v->kvm->arch.xen.upcall_vector; 12340da8ccdSDavid Woodhouse 1241c1a9ce9SSteve Rutherford if (irqchip_split(v->kvm)) { 1251c1a9ce9SSteve Rutherford int vector = v->arch.pending_external_vector; 1261c1a9ce9SSteve Rutherford 1271c1a9ce9SSteve Rutherford v->arch.pending_external_vector = -1; 1281c1a9ce9SSteve Rutherford return vector; 1291c1a9ce9SSteve Rutherford } else 130c7c9c56cSYang Zhang return kvm_pic_read_irq(v->kvm); /* PIC */ 131c7c9c56cSYang Zhang } 132c7c9c56cSYang Zhang 133c7c9c56cSYang Zhang /* 134edf88417SAvi Kivity * Read pending interrupt vector and intack. 135edf88417SAvi Kivity */ kvm_cpu_get_interrupt(struct kvm_vcpu * v)136edf88417SAvi Kivityint kvm_cpu_get_interrupt(struct kvm_vcpu *v) 137edf88417SAvi Kivity { 13872c3bcdcSPaolo Bonzini int vector = kvm_cpu_get_extint(v); 13956cc2406SWanpeng Li if (vector != -1) 140c7c9c56cSYang Zhang return vector; /* PIC */ 141f3200d00SGleb Natapov 142f3200d00SGleb Natapov return kvm_get_apic_interrupt(v); /* APIC */ 143edf88417SAvi Kivity } 14477b0f5d6SBandan Das EXPORT_SYMBOL_GPL(kvm_cpu_get_interrupt); 145edf88417SAvi Kivity kvm_inject_pending_timer_irqs(struct kvm_vcpu * vcpu)146edf88417SAvi Kivityvoid kvm_inject_pending_timer_irqs(struct kvm_vcpu *vcpu) 147edf88417SAvi Kivity { 1481e3161b4SPaolo Bonzini if (lapic_in_kernel(vcpu)) 149edf88417SAvi Kivity kvm_inject_apic_timer_irqs(vcpu); 15053639526SJoao Martins if (kvm_xen_timer_enabled(vcpu)) 15153639526SJoao Martins kvm_xen_inject_timer_irqs(vcpu); 152edf88417SAvi Kivity } 153edf88417SAvi Kivity __kvm_migrate_timers(struct kvm_vcpu * vcpu)1542f599714SMarcelo Tosattivoid __kvm_migrate_timers(struct kvm_vcpu *vcpu) 1552f599714SMarcelo Tosatti { 1562f599714SMarcelo Tosatti __kvm_migrate_apic_timer(vcpu); 1572f599714SMarcelo Tosatti __kvm_migrate_pit_timer(vcpu); 158b3646477SJason Baron static_call_cond(kvm_x86_migrate_timers)(vcpu); 1592f599714SMarcelo Tosatti } 160654f1f13SPeter Xu kvm_arch_irqfd_allowed(struct kvm * kvm,struct kvm_irqfd * args)161654f1f13SPeter Xubool kvm_arch_irqfd_allowed(struct kvm *kvm, struct kvm_irqfd *args) 162654f1f13SPeter Xu { 163654f1f13SPeter Xu bool resample = args->flags & KVM_IRQFD_FLAG_RESAMPLE; 164654f1f13SPeter Xu 165654f1f13SPeter Xu return resample ? irqchip_kernel(kvm) : irqchip_in_kernel(kvm); 166654f1f13SPeter Xu } 167d663b8a2SPaolo Bonzini kvm_arch_irqchip_in_kernel(struct kvm * kvm)168d663b8a2SPaolo Bonzinibool kvm_arch_irqchip_in_kernel(struct kvm *kvm) 169d663b8a2SPaolo Bonzini { 170d663b8a2SPaolo Bonzini return irqchip_in_kernel(kvm); 171d663b8a2SPaolo Bonzini } 172