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 affilates. 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 int ret; 37 38 ret = pit_has_pending_timer(vcpu); 39 ret |= apic_has_pending_timer(vcpu); 40 41 return ret; 42 } 43 EXPORT_SYMBOL(kvm_cpu_has_pending_timer); 44 45 /* 46 * check if there is pending interrupt without 47 * intack. 48 */ 49 int kvm_cpu_has_interrupt(struct kvm_vcpu *v) 50 { 51 struct kvm_pic *s; 52 53 if (!irqchip_in_kernel(v->kvm)) 54 return v->arch.interrupt.pending; 55 56 if (kvm_apic_has_interrupt(v) == -1) { /* LAPIC */ 57 if (kvm_apic_accept_pic_intr(v)) { 58 s = pic_irqchip(v->kvm); /* PIC */ 59 return s->output; 60 } else 61 return 0; 62 } 63 return 1; 64 } 65 EXPORT_SYMBOL_GPL(kvm_cpu_has_interrupt); 66 67 /* 68 * Read pending interrupt vector and intack. 69 */ 70 int kvm_cpu_get_interrupt(struct kvm_vcpu *v) 71 { 72 struct kvm_pic *s; 73 int vector; 74 75 if (!irqchip_in_kernel(v->kvm)) 76 return v->arch.interrupt.nr; 77 78 vector = kvm_get_apic_interrupt(v); /* APIC */ 79 if (vector == -1) { 80 if (kvm_apic_accept_pic_intr(v)) { 81 s = pic_irqchip(v->kvm); 82 s->output = 0; /* PIC */ 83 vector = kvm_pic_read_irq(v->kvm); 84 } 85 } 86 return vector; 87 } 88 EXPORT_SYMBOL_GPL(kvm_cpu_get_interrupt); 89 90 void kvm_inject_pending_timer_irqs(struct kvm_vcpu *vcpu) 91 { 92 kvm_inject_apic_timer_irqs(vcpu); 93 /* TODO: PIT, RTC etc. */ 94 } 95 EXPORT_SYMBOL_GPL(kvm_inject_pending_timer_irqs); 96 97 void __kvm_migrate_timers(struct kvm_vcpu *vcpu) 98 { 99 __kvm_migrate_apic_timer(vcpu); 100 __kvm_migrate_pit_timer(vcpu); 101 } 102