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 */ 34int kvm_cpu_has_pending_timer(struct kvm_vcpu *vcpu) 35{ 36 return apic_has_pending_timer(vcpu); 37} 38EXPORT_SYMBOL(kvm_cpu_has_pending_timer); 39 40/* 41 * check if there is pending interrupt from 42 * non-APIC source without intack. 43 */ 44static 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 */ 58int 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 */ 76int 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} 86EXPORT_SYMBOL_GPL(kvm_cpu_has_interrupt); 87 88/* 89 * Read pending interrupt(from non-APIC source) 90 * vector and intack. 91 */ 92static 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 */ 102int 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} 116EXPORT_SYMBOL_GPL(kvm_cpu_get_interrupt); 117 118void kvm_inject_pending_timer_irqs(struct kvm_vcpu *vcpu) 119{ 120 kvm_inject_apic_timer_irqs(vcpu); 121 /* TODO: PIT, RTC etc. */ 122} 123EXPORT_SYMBOL_GPL(kvm_inject_pending_timer_irqs); 124 125void __kvm_migrate_timers(struct kvm_vcpu *vcpu) 126{ 127 __kvm_migrate_apic_timer(vcpu); 128 __kvm_migrate_pit_timer(vcpu); 129} 130