在Xen 3.4.2中,Xen Guest中斷包括硬件中斷和軟中斷(Soft IRQ)兩種,在硬件虛擬化中,前者的分發在陷入Xen Hypervisor後由其負責,後者的話其實是在調用Xen Hypervisor中的一些函數,只能算模擬
與前者功能相關的文件是arch\x86\vmx\Vmx.c文件中的vmx_vmexit_handler函數,後者則是arch\x86\irq.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\n", 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\n", 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\n", 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)