1 /* 2 * irq.c: API for in kernel interrupt controller 3 * Copyright (c) 2007, Intel Corporation. 4 * Copyright 2009 Red Hat, Inc. and/or its affiliates. 5 * 6 * This program is free software; you can redistribute it and/or modify it 7 * under the terms and conditions of the GNU General Public License, 8 * version 2, as published by the Free Software Foundation. 9 * 10 * This program is distributed in the hope it will be useful, but WITHOUT 11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 13 * more details. 14 * 15 * You should have received a copy of the GNU General Public License along with 16 * this program; if not, write to the Free Software Foundation, Inc., 59 Temple 17 * Place - Suite 330, Boston, MA 02111-1307 USA. 18 * Authors: 19 * Yaozu (Eddie) Dong <Eddie.dong@intel.com> 20 * 21 */ 22 23 #include <linux/module.h> 24 #include <linux/kvm_host.h> 25 26 #include "irq.h" 27 #include "i8254.h" 28 #include "x86.h" 29 30 /* 31 * check if there are pending timer events 32 * to be processed. 33 */ 34 int kvm_cpu_has_pending_timer(struct kvm_vcpu *vcpu) 35 { 36 return apic_has_pending_timer(vcpu); 37 } 38 EXPORT_SYMBOL(kvm_cpu_has_pending_timer); 39 40 /* 41 * check if there is pending interrupt from 42 * non-APIC source without intack. 43 */ 44 static int kvm_cpu_has_extint(struct kvm_vcpu *v) 45 { 46 if (kvm_apic_accept_pic_intr(v)) 47 return pic_irqchip(v->kvm)->output; /* PIC */ 48 else 49 return 0; 50 } 51 52 /* 53 * check if there is injectable interrupt: 54 * when virtual interrupt delivery enabled, 55 * interrupt from apic will handled by hardware, 56 * we don't need to check it here. 57 */ 58 int kvm_cpu_has_injectable_intr(struct kvm_vcpu *v) 59 { 60 if (!irqchip_in_kernel(v->kvm)) 61 return v->arch.interrupt.pending; 62 63 if (kvm_cpu_has_extint(v)) 64 return 1; 65 66 if (kvm_apic_vid_enabled(v->kvm)) 67 return 0; 68 69 return kvm_apic_has_interrupt(v) != -1; /* LAPIC */ 70 } 71 72 /* 73 * check if there is pending interrupt without 74 * intack. 75 */ 76 int kvm_cpu_has_interrupt(struct kvm_vcpu *v) 77 { 78 if (!irqchip_in_kernel(v->kvm)) 79 return v->arch.interrupt.pending; 80 81 if (kvm_cpu_has_extint(v)) 82 return 1; 83 84 return kvm_apic_has_interrupt(v) != -1; /* LAPIC */ 85 } 86 EXPORT_SYMBOL_GPL(kvm_cpu_has_interrupt); 87 88 /* 89 * Read pending interrupt(from non-APIC source) 90 * vector and intack. 91 */ 92 static int kvm_cpu_get_extint(struct kvm_vcpu *v) 93 { 94 if (kvm_cpu_has_extint(v)) 95 return kvm_pic_read_irq(v->kvm); /* PIC */ 96 return -1; 97 } 98 99 /* 100 * Read pending interrupt vector and intack. 101 */ 102 int kvm_cpu_get_interrupt(struct kvm_vcpu *v) 103 { 104 int vector; 105 106 if (!irqchip_in_kernel(v->kvm)) 107 return v->arch.interrupt.nr; 108 109 vector = kvm_cpu_get_extint(v); 110 111 if (vector != -1) 112 return vector; /* PIC */ 113 114 return kvm_get_apic_interrupt(v); /* APIC */ 115 } 116 EXPORT_SYMBOL_GPL(kvm_cpu_get_interrupt); 117 118 void kvm_inject_pending_timer_irqs(struct kvm_vcpu *vcpu) 119 { 120 kvm_inject_apic_timer_irqs(vcpu); 121 /* TODO: PIT, RTC etc. */ 122 } 123 EXPORT_SYMBOL_GPL(kvm_inject_pending_timer_irqs); 124 125 void __kvm_migrate_timers(struct kvm_vcpu *vcpu) 126 { 127 __kvm_migrate_apic_timer(vcpu); 128 __kvm_migrate_pit_timer(vcpu); 129 } 130