2007-07-06 13:20:49 +04:00
/*
* irq . c : API for in kernel interrupt controller
* Copyright ( c ) 2007 , Intel Corporation .
2010-10-06 16:23:22 +04:00
* Copyright 2009 Red Hat , Inc . and / or its affiliates .
2007-07-06 13:20:49 +04:00
*
* This program is free software ; you can redistribute it and / or modify it
* under the terms and conditions of the GNU General Public License ,
* version 2 , as published by the Free Software Foundation .
*
* This program is distributed in the hope it will be useful , but WITHOUT
* ANY WARRANTY ; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE . See the GNU General Public License for
* more details .
*
* You should have received a copy of the GNU General Public License along with
* this program ; if not , write to the Free Software Foundation , Inc . , 59 Temple
* Place - Suite 330 , Boston , MA 02111 - 1307 USA .
* Authors :
* Yaozu ( Eddie ) Dong < Eddie . dong @ intel . com >
*
*/
# include <linux/module.h>
2007-12-16 12:02:48 +03:00
# include <linux/kvm_host.h>
2007-07-06 13:20:49 +04:00
# include "irq.h"
2008-01-28 00:10:22 +03:00
# include "i8254.h"
2009-04-21 18:44:56 +04:00
# include "x86.h"
2007-07-06 13:20:49 +04:00
2008-04-11 21:53:26 +04:00
/*
* check if there are pending timer events
* to be processed .
*/
int kvm_cpu_has_pending_timer ( struct kvm_vcpu * vcpu )
{
2010-08-27 13:15:06 +04:00
return apic_has_pending_timer ( vcpu ) ;
2008-04-11 21:53:26 +04:00
}
EXPORT_SYMBOL ( kvm_cpu_has_pending_timer ) ;
2013-01-25 06:18:51 +04:00
/*
* check if there is pending interrupt from
* non - APIC source without intack .
*/
static int kvm_cpu_has_extint ( struct kvm_vcpu * v )
{
if ( kvm_apic_accept_pic_intr ( v ) )
return pic_irqchip ( v - > kvm ) - > output ; /* PIC */
else
return 0 ;
}
/*
* check if there is injectable interrupt :
* when virtual interrupt delivery enabled ,
* interrupt from apic will handled by hardware ,
* we don ' t need to check it here .
*/
int kvm_cpu_has_injectable_intr ( struct kvm_vcpu * v )
{
if ( ! irqchip_in_kernel ( v - > kvm ) )
return v - > arch . interrupt . pending ;
if ( kvm_cpu_has_extint ( v ) )
return 1 ;
if ( kvm_apic_vid_enabled ( v - > kvm ) )
return 0 ;
return kvm_apic_has_interrupt ( v ) ! = - 1 ; /* LAPIC */
}
2007-07-06 13:20:49 +04:00
/*
* check if there is pending interrupt without
* intack .
*/
int kvm_cpu_has_interrupt ( struct kvm_vcpu * v )
{
2009-04-21 18:44:56 +04:00
if ( ! irqchip_in_kernel ( v - > kvm ) )
2009-05-11 14:35:48 +04:00
return v - > arch . interrupt . pending ;
2009-04-21 18:44:56 +04:00
2013-01-25 06:18:51 +04:00
if ( kvm_cpu_has_extint ( v ) )
return 1 ;
2012-12-10 16:05:55 +04:00
return kvm_apic_has_interrupt ( v ) ! = - 1 ; /* LAPIC */
2007-07-06 13:20:49 +04:00
}
EXPORT_SYMBOL_GPL ( kvm_cpu_has_interrupt ) ;
2013-01-25 06:18:51 +04:00
/*
* Read pending interrupt ( from non - APIC source )
* vector and intack .
*/
static int kvm_cpu_get_extint ( struct kvm_vcpu * v )
{
if ( kvm_cpu_has_extint ( v ) )
return kvm_pic_read_irq ( v - > kvm ) ; /* PIC */
return - 1 ;
}
2007-07-06 13:20:49 +04:00
/*
* Read pending interrupt vector and intack .
*/
int kvm_cpu_get_interrupt ( struct kvm_vcpu * v )
{
2013-01-25 06:18:51 +04:00
int vector ;
2009-04-21 18:44:56 +04:00
if ( ! irqchip_in_kernel ( v - > kvm ) )
2009-05-11 14:35:48 +04:00
return v - > arch . interrupt . nr ;
2009-04-21 18:44:56 +04:00
2013-01-25 06:18:51 +04:00
vector = kvm_cpu_get_extint ( v ) ;
if ( kvm_apic_vid_enabled ( v - > kvm ) | | vector ! = - 1 )
return vector ; /* PIC */
2012-12-10 16:05:55 +04:00
return kvm_get_apic_interrupt ( v ) ; /* APIC */
2007-07-06 13:20:49 +04:00
}
2007-09-12 11:58:04 +04:00
2007-09-03 17:56:58 +04:00
void kvm_inject_pending_timer_irqs ( struct kvm_vcpu * vcpu )
{
kvm_inject_apic_timer_irqs ( vcpu ) ;
/* TODO: PIT, RTC etc. */
}
EXPORT_SYMBOL_GPL ( kvm_inject_pending_timer_irqs ) ;
2008-05-27 19:10:20 +04:00
void __kvm_migrate_timers ( struct kvm_vcpu * vcpu )
{
__kvm_migrate_apic_timer ( vcpu ) ;
__kvm_migrate_pit_timer ( vcpu ) ;
}