Xen Guest中断简介2011-01-09 博客园 Superymk在Xen 3.4.2中,Xen Guest中断包括硬件中断和软中断(Soft IRQ)两种,在硬件虚拟化中,前者的分发在陷入Xen Hypervisor后由其负责,后者的话其实是在调用Xen Hypervisor中的一些函数,只能算模拟与前者功能相关的文件是archx86vmxVmx.c文件中的vmx_vmexit_handler函数,后者则是archx86irq.c 文件的do_IRQ函数,翻翻就可以看到,在xen中,Timer Interrupt和UART的一些中断都是软件中断。Xen Guest中断拦截试验在做context switch相关的实验中要注意,对于中断,既要处理外部中断又要处理异常,其效果也就是整个idt表都要hook住。附上一些代码关键point在vmx_vmexit_handler函数中switch ( exit_reason )
{
case EXIT_REASON_EXCEPTION_NMI:
{
/*
* We don"t set the software-interrupt exiting (INT n).
* (1) We can get an exception (e.g. #PG) in the guest, or
* (2) NMI
*/
unsigned int intr_info, vector;
intr_info = __vmread(VM_EXIT_INTR_INFO);
BUG_ON(!(intr_info & INTR_INFO_VALID_MASK));
vector = intr_info & INTR_INFO_VECTOR_MASK;
//[Superymk] Add hook_idt //<---------------------------Key Point
if(hook_idt)
{
joan_dprintk("Int:%d
", vector);
}
//[Superymk] Add finished
/*
* Re-set the NMI shadow if vmexit caused by a guest IRET fault (see 3B
* 25.7.1.2, "Resuming Guest Software after Handling an Exception").
* (NB. If we emulate this IRET for any reason, we should re-clear!)
*/
在do_IRQ函数中spin_lock(&desc->lock);
desc->handler->ack(vector);
if ( likely(desc->status & IRQ_GUEST) )
{
//[Superymk] Add hook_idt //<---------------------------Key Point
if(hook_idt)
{
joan_dprintk("Int:%d
", vector);
}
//[Superymk] Add finished
irq_enter();
__do_IRQ_guest(vector);
irq_exit();
spin_unlock(&desc->lock);
return;
}
desc->status &= ~IRQ_REPLAY;
desc->status |= IRQ_PENDING;
/*
* Since we set PENDING, if another processor is handling a different
* instance of this same irq, the other processor will take care of it.
*/
if ( desc->status & (IRQ_DISABLED | IRQ_INPROGRESS) )
goto out;
desc->status |= IRQ_INPROGRESS;
action = desc->action;
while ( desc->status & IRQ_PENDING )
{
//[Superymk] Add hook_idt //<---------------------------Key Point
if(hook_idt)
{
joan_dprintk("Int:%d
", vector);
}
//[Superymk] Add finished
desc->status &= ~IRQ_PENDING;
irq_enter();
spin_unlock_irq(&desc->lock);
action->handler(vector_to_irq(vector), action->dev_id, regs);
spin_lock_irq(&desc->lock);
irq_exit();
}
之所以都在irq_enter()外修改,是因为尽量缩短IRQ的处理时间。(它们需要在高特权级别下运行,未核实irq_enter()是否会提升IRQL)