1edf88417SAvi Kivity /* 2edf88417SAvi Kivity * irq.c: API for in kernel interrupt controller 3edf88417SAvi Kivity * Copyright (c) 2007, Intel Corporation. 49611c187SNicolas Kaiser * Copyright 2009 Red Hat, Inc. and/or its affiliates. 5edf88417SAvi Kivity * 6edf88417SAvi Kivity * This program is free software; you can redistribute it and/or modify it 7edf88417SAvi Kivity * under the terms and conditions of the GNU General Public License, 8edf88417SAvi Kivity * version 2, as published by the Free Software Foundation. 9edf88417SAvi Kivity * 10edf88417SAvi Kivity * This program is distributed in the hope it will be useful, but WITHOUT 11edf88417SAvi Kivity * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 12edf88417SAvi Kivity * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 13edf88417SAvi Kivity * more details. 14edf88417SAvi Kivity * 15edf88417SAvi Kivity * You should have received a copy of the GNU General Public License along with 16edf88417SAvi Kivity * this program; if not, write to the Free Software Foundation, Inc., 59 Temple 17edf88417SAvi Kivity * Place - Suite 330, Boston, MA 02111-1307 USA. 18edf88417SAvi Kivity * Authors: 19edf88417SAvi Kivity * Yaozu (Eddie) Dong <Eddie.dong@intel.com> 20edf88417SAvi Kivity * 21edf88417SAvi Kivity */ 22edf88417SAvi Kivity 231767e931SPaul Gortmaker #include <linux/export.h> 24edf88417SAvi Kivity #include <linux/kvm_host.h> 25edf88417SAvi Kivity 26edf88417SAvi Kivity #include "irq.h" 277837699fSSheng Yang #include "i8254.h" 288061823aSGleb Natapov #include "x86.h" 29edf88417SAvi Kivity 30edf88417SAvi Kivity /* 313d80840dSMarcelo Tosatti * check if there are pending timer events 323d80840dSMarcelo Tosatti * to be processed. 333d80840dSMarcelo Tosatti */ 343d80840dSMarcelo Tosatti int kvm_cpu_has_pending_timer(struct kvm_vcpu *vcpu) 353d80840dSMarcelo Tosatti { 361e3161b4SPaolo Bonzini if (lapic_in_kernel(vcpu)) 3723e7a794SJason Wang return apic_has_pending_timer(vcpu); 381e3161b4SPaolo Bonzini 391e3161b4SPaolo Bonzini return 0; 403d80840dSMarcelo Tosatti } 413d80840dSMarcelo Tosatti EXPORT_SYMBOL(kvm_cpu_has_pending_timer); 423d80840dSMarcelo Tosatti 433d80840dSMarcelo Tosatti /* 441c1a9ce9SSteve Rutherford * check if there is a pending userspace external interrupt 451c1a9ce9SSteve Rutherford */ 461c1a9ce9SSteve Rutherford static int pending_userspace_extint(struct kvm_vcpu *v) 471c1a9ce9SSteve Rutherford { 481c1a9ce9SSteve Rutherford return v->arch.pending_external_vector != -1; 491c1a9ce9SSteve Rutherford } 501c1a9ce9SSteve Rutherford 511c1a9ce9SSteve Rutherford /* 52c7c9c56cSYang Zhang * check if there is pending interrupt from 53c7c9c56cSYang Zhang * non-APIC source without intack. 54c7c9c56cSYang Zhang */ 55c7c9c56cSYang Zhang static int kvm_cpu_has_extint(struct kvm_vcpu *v) 56c7c9c56cSYang Zhang { 571c1a9ce9SSteve Rutherford u8 accept = kvm_apic_accept_pic_intr(v); 581c1a9ce9SSteve Rutherford 591c1a9ce9SSteve Rutherford if (accept) { 601c1a9ce9SSteve Rutherford if (irqchip_split(v->kvm)) 611c1a9ce9SSteve Rutherford return pending_userspace_extint(v); 62c7c9c56cSYang Zhang else 6390bca052SDavid Hildenbrand return v->kvm->arch.vpic->output; 641c1a9ce9SSteve Rutherford } else 65c7c9c56cSYang Zhang return 0; 66c7c9c56cSYang Zhang } 67c7c9c56cSYang Zhang 68c7c9c56cSYang Zhang /* 69c7c9c56cSYang Zhang * check if there is injectable interrupt: 70c7c9c56cSYang Zhang * when virtual interrupt delivery enabled, 71c7c9c56cSYang Zhang * interrupt from apic will handled by hardware, 72c7c9c56cSYang Zhang * we don't need to check it here. 73c7c9c56cSYang Zhang */ 74c7c9c56cSYang Zhang int kvm_cpu_has_injectable_intr(struct kvm_vcpu *v) 75c7c9c56cSYang Zhang { 76*04140b41SLiran Alon /* 77*04140b41SLiran Alon * FIXME: interrupt.injected represents an interrupt that it's 78*04140b41SLiran Alon * side-effects have already been applied (e.g. bit from IRR 79*04140b41SLiran Alon * already moved to ISR). Therefore, it is incorrect to rely 80*04140b41SLiran Alon * on interrupt.injected to know if there is a pending 81*04140b41SLiran Alon * interrupt in the user-mode LAPIC. 82*04140b41SLiran Alon * This leads to nVMX/nSVM not be able to distinguish 83*04140b41SLiran Alon * if it should exit from L2 to L1 on EXTERNAL_INTERRUPT on 84*04140b41SLiran Alon * pending interrupt or should re-inject an injected 85*04140b41SLiran Alon * interrupt. 86*04140b41SLiran Alon */ 8735754c98SPaolo Bonzini if (!lapic_in_kernel(v)) 88*04140b41SLiran Alon return v->arch.interrupt.injected; 89c7c9c56cSYang Zhang 90c7c9c56cSYang Zhang if (kvm_cpu_has_extint(v)) 91c7c9c56cSYang Zhang return 1; 92c7c9c56cSYang Zhang 93851c1a18SLiran Alon if (!is_guest_mode(v) && kvm_vcpu_apicv_active(v)) 94c7c9c56cSYang Zhang return 0; 95c7c9c56cSYang Zhang 96c7c9c56cSYang Zhang return kvm_apic_has_interrupt(v) != -1; /* LAPIC */ 97c7c9c56cSYang Zhang } 98c7c9c56cSYang Zhang 99c7c9c56cSYang Zhang /* 100edf88417SAvi Kivity * check if there is pending interrupt without 101edf88417SAvi Kivity * intack. 102edf88417SAvi Kivity */ 103edf88417SAvi Kivity int kvm_cpu_has_interrupt(struct kvm_vcpu *v) 104edf88417SAvi Kivity { 105*04140b41SLiran Alon /* 106*04140b41SLiran Alon * FIXME: interrupt.injected represents an interrupt that it's 107*04140b41SLiran Alon * side-effects have already been applied (e.g. bit from IRR 108*04140b41SLiran Alon * already moved to ISR). Therefore, it is incorrect to rely 109*04140b41SLiran Alon * on interrupt.injected to know if there is a pending 110*04140b41SLiran Alon * interrupt in the user-mode LAPIC. 111*04140b41SLiran Alon * This leads to nVMX/nSVM not be able to distinguish 112*04140b41SLiran Alon * if it should exit from L2 to L1 on EXTERNAL_INTERRUPT on 113*04140b41SLiran Alon * pending interrupt or should re-inject an injected 114*04140b41SLiran Alon * interrupt. 115*04140b41SLiran Alon */ 11635754c98SPaolo Bonzini if (!lapic_in_kernel(v)) 117*04140b41SLiran Alon return v->arch.interrupt.injected; 1188061823aSGleb Natapov 119c7c9c56cSYang Zhang if (kvm_cpu_has_extint(v)) 120c7c9c56cSYang Zhang return 1; 121f3200d00SGleb Natapov 122f3200d00SGleb Natapov return kvm_apic_has_interrupt(v) != -1; /* LAPIC */ 123edf88417SAvi Kivity } 124edf88417SAvi Kivity EXPORT_SYMBOL_GPL(kvm_cpu_has_interrupt); 125edf88417SAvi Kivity 126edf88417SAvi Kivity /* 127c7c9c56cSYang Zhang * Read pending interrupt(from non-APIC source) 128c7c9c56cSYang Zhang * vector and intack. 129c7c9c56cSYang Zhang */ 130c7c9c56cSYang Zhang static int kvm_cpu_get_extint(struct kvm_vcpu *v) 131c7c9c56cSYang Zhang { 1321c1a9ce9SSteve Rutherford if (kvm_cpu_has_extint(v)) { 1331c1a9ce9SSteve Rutherford if (irqchip_split(v->kvm)) { 1341c1a9ce9SSteve Rutherford int vector = v->arch.pending_external_vector; 1351c1a9ce9SSteve Rutherford 1361c1a9ce9SSteve Rutherford v->arch.pending_external_vector = -1; 1371c1a9ce9SSteve Rutherford return vector; 1381c1a9ce9SSteve Rutherford } else 139c7c9c56cSYang Zhang return kvm_pic_read_irq(v->kvm); /* PIC */ 1401c1a9ce9SSteve Rutherford } else 141c7c9c56cSYang Zhang return -1; 142c7c9c56cSYang Zhang } 143c7c9c56cSYang Zhang 144c7c9c56cSYang Zhang /* 145edf88417SAvi Kivity * Read pending interrupt vector and intack. 146edf88417SAvi Kivity */ 147edf88417SAvi Kivity int kvm_cpu_get_interrupt(struct kvm_vcpu *v) 148edf88417SAvi Kivity { 149c7c9c56cSYang Zhang int vector; 150c7c9c56cSYang Zhang 15135754c98SPaolo Bonzini if (!lapic_in_kernel(v)) 152923c61bbSGleb Natapov return v->arch.interrupt.nr; 1538061823aSGleb Natapov 154c7c9c56cSYang Zhang vector = kvm_cpu_get_extint(v); 155c7c9c56cSYang Zhang 15656cc2406SWanpeng Li if (vector != -1) 157c7c9c56cSYang Zhang return vector; /* PIC */ 158f3200d00SGleb Natapov 159f3200d00SGleb Natapov return kvm_get_apic_interrupt(v); /* APIC */ 160edf88417SAvi Kivity } 16177b0f5d6SBandan Das EXPORT_SYMBOL_GPL(kvm_cpu_get_interrupt); 162edf88417SAvi Kivity 163edf88417SAvi Kivity void kvm_inject_pending_timer_irqs(struct kvm_vcpu *vcpu) 164edf88417SAvi Kivity { 1651e3161b4SPaolo Bonzini if (lapic_in_kernel(vcpu)) 166edf88417SAvi Kivity kvm_inject_apic_timer_irqs(vcpu); 167edf88417SAvi Kivity } 168edf88417SAvi Kivity EXPORT_SYMBOL_GPL(kvm_inject_pending_timer_irqs); 169edf88417SAvi Kivity 1702f599714SMarcelo Tosatti void __kvm_migrate_timers(struct kvm_vcpu *vcpu) 1712f599714SMarcelo Tosatti { 1722f599714SMarcelo Tosatti __kvm_migrate_apic_timer(vcpu); 1732f599714SMarcelo Tosatti __kvm_migrate_pit_timer(vcpu); 1742f599714SMarcelo Tosatti } 175