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 23edf88417SAvi Kivity #include <linux/module.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 { 3623e7a794SJason Wang return apic_has_pending_timer(vcpu); 373d80840dSMarcelo Tosatti } 383d80840dSMarcelo Tosatti EXPORT_SYMBOL(kvm_cpu_has_pending_timer); 393d80840dSMarcelo Tosatti 403d80840dSMarcelo Tosatti /* 41*c7c9c56cSYang Zhang * check if there is pending interrupt from 42*c7c9c56cSYang Zhang * non-APIC source without intack. 43*c7c9c56cSYang Zhang */ 44*c7c9c56cSYang Zhang static int kvm_cpu_has_extint(struct kvm_vcpu *v) 45*c7c9c56cSYang Zhang { 46*c7c9c56cSYang Zhang if (kvm_apic_accept_pic_intr(v)) 47*c7c9c56cSYang Zhang return pic_irqchip(v->kvm)->output; /* PIC */ 48*c7c9c56cSYang Zhang else 49*c7c9c56cSYang Zhang return 0; 50*c7c9c56cSYang Zhang } 51*c7c9c56cSYang Zhang 52*c7c9c56cSYang Zhang /* 53*c7c9c56cSYang Zhang * check if there is injectable interrupt: 54*c7c9c56cSYang Zhang * when virtual interrupt delivery enabled, 55*c7c9c56cSYang Zhang * interrupt from apic will handled by hardware, 56*c7c9c56cSYang Zhang * we don't need to check it here. 57*c7c9c56cSYang Zhang */ 58*c7c9c56cSYang Zhang int kvm_cpu_has_injectable_intr(struct kvm_vcpu *v) 59*c7c9c56cSYang Zhang { 60*c7c9c56cSYang Zhang if (!irqchip_in_kernel(v->kvm)) 61*c7c9c56cSYang Zhang return v->arch.interrupt.pending; 62*c7c9c56cSYang Zhang 63*c7c9c56cSYang Zhang if (kvm_cpu_has_extint(v)) 64*c7c9c56cSYang Zhang return 1; 65*c7c9c56cSYang Zhang 66*c7c9c56cSYang Zhang if (kvm_apic_vid_enabled(v->kvm)) 67*c7c9c56cSYang Zhang return 0; 68*c7c9c56cSYang Zhang 69*c7c9c56cSYang Zhang return kvm_apic_has_interrupt(v) != -1; /* LAPIC */ 70*c7c9c56cSYang Zhang } 71*c7c9c56cSYang Zhang 72*c7c9c56cSYang Zhang /* 73edf88417SAvi Kivity * check if there is pending interrupt without 74edf88417SAvi Kivity * intack. 75edf88417SAvi Kivity */ 76edf88417SAvi Kivity int kvm_cpu_has_interrupt(struct kvm_vcpu *v) 77edf88417SAvi Kivity { 788061823aSGleb Natapov if (!irqchip_in_kernel(v->kvm)) 79923c61bbSGleb Natapov return v->arch.interrupt.pending; 808061823aSGleb Natapov 81*c7c9c56cSYang Zhang if (kvm_cpu_has_extint(v)) 82*c7c9c56cSYang Zhang return 1; 83f3200d00SGleb Natapov 84f3200d00SGleb Natapov return kvm_apic_has_interrupt(v) != -1; /* LAPIC */ 85edf88417SAvi Kivity } 86edf88417SAvi Kivity EXPORT_SYMBOL_GPL(kvm_cpu_has_interrupt); 87edf88417SAvi Kivity 88edf88417SAvi Kivity /* 89*c7c9c56cSYang Zhang * Read pending interrupt(from non-APIC source) 90*c7c9c56cSYang Zhang * vector and intack. 91*c7c9c56cSYang Zhang */ 92*c7c9c56cSYang Zhang static int kvm_cpu_get_extint(struct kvm_vcpu *v) 93*c7c9c56cSYang Zhang { 94*c7c9c56cSYang Zhang if (kvm_cpu_has_extint(v)) 95*c7c9c56cSYang Zhang return kvm_pic_read_irq(v->kvm); /* PIC */ 96*c7c9c56cSYang Zhang return -1; 97*c7c9c56cSYang Zhang } 98*c7c9c56cSYang Zhang 99*c7c9c56cSYang Zhang /* 100edf88417SAvi Kivity * Read pending interrupt vector and intack. 101edf88417SAvi Kivity */ 102edf88417SAvi Kivity int kvm_cpu_get_interrupt(struct kvm_vcpu *v) 103edf88417SAvi Kivity { 104*c7c9c56cSYang Zhang int vector; 105*c7c9c56cSYang Zhang 1068061823aSGleb Natapov if (!irqchip_in_kernel(v->kvm)) 107923c61bbSGleb Natapov return v->arch.interrupt.nr; 1088061823aSGleb Natapov 109*c7c9c56cSYang Zhang vector = kvm_cpu_get_extint(v); 110*c7c9c56cSYang Zhang 111*c7c9c56cSYang Zhang if (kvm_apic_vid_enabled(v->kvm) || vector != -1) 112*c7c9c56cSYang Zhang return vector; /* PIC */ 113f3200d00SGleb Natapov 114f3200d00SGleb Natapov return kvm_get_apic_interrupt(v); /* APIC */ 115edf88417SAvi Kivity } 116edf88417SAvi Kivity 117edf88417SAvi Kivity void kvm_inject_pending_timer_irqs(struct kvm_vcpu *vcpu) 118edf88417SAvi Kivity { 119edf88417SAvi Kivity kvm_inject_apic_timer_irqs(vcpu); 120edf88417SAvi Kivity /* TODO: PIT, RTC etc. */ 121edf88417SAvi Kivity } 122edf88417SAvi Kivity EXPORT_SYMBOL_GPL(kvm_inject_pending_timer_irqs); 123edf88417SAvi Kivity 1242f599714SMarcelo Tosatti void __kvm_migrate_timers(struct kvm_vcpu *vcpu) 1252f599714SMarcelo Tosatti { 1262f599714SMarcelo Tosatti __kvm_migrate_apic_timer(vcpu); 1272f599714SMarcelo Tosatti __kvm_migrate_pit_timer(vcpu); 1282f599714SMarcelo Tosatti } 129