您的位置:首页 > 编程语言

关于KVM中处理外部中断的处理代码

2016-09-11 08:20 1176 查看
今天读代码发现了一个关于"acknowledge interrupt on exit"特性细节

VM-EIXT外部中断的处理函数为handle_external_interrupt
static int (*const kvm_vmx_exit_handlers[])(struct kvm_vcpu *vcpu) = {
[EXIT_REASON_EXTERNAL_INTERRUPT]      = handle_external_interrupt
}


而该函数中只是增加了统计信息,没有处理,就开始找外部中断的真正处理地方
static int handle_external_interrupt(struct kvm_vcpu *vcpu)
{
++vcpu->stat.irq_exits;
return 1;
}


最后发现原来是在vcpu_enter_guest中调用vmx_handle_external_intr进行了外部中断的真正处理

vcpu_enter_guest()
{
kvm_x86_ops->handle_external_intr(vcpu); //也就是vmx_handle_external_intr()
}

static void vmx_handle_external_intr(struct kvm_vcpu *vcpu)
{
u32 exit_intr_info = vmcs_read32(VM_EXIT_INTR_INFO);

/*
* 如果中心的类型是外部中断
*/
if ((exit_intr_info & (INTR_INFO_VALID_MASK | INTR_INFO_INTR_TYPE_MASK))
== (INTR_INFO_VALID_MASK | INTR_TYPE_EXT_INTR)) {
unsigned int vector;
unsigned long entry;
gate_desc *desc;
struct vcpu_vmx *vmx = to_vmx(vcpu);
#ifdef CONFIG_X86_64
unsigned long tmp;
#endif

/* 取得外部中断的vector值,
* (这是因为处理器的"acknowledge interrupt on exit"特性会自动ACK,就自动拿到了vector,
*  但是这个特性使能之后,处理器不会再通过IDT调用中断处理函数,而是使用vmx handler
*  vmx handler在这里构造中断栈帧,然后根据vector的值到IDT中找到真正的处理函数完成中断的处理
*  注意,这里会将中断栈帧中的IF置位,这样中断处理完成的时候,就会自动的开启中断了)
*/
vector =  exit_intr_info & INTR_INFO_VECTOR_MASK;
/*
* 找到中断描述符,并得到门入口
*/
desc = (gate_desc *)vmx->host_idt_base + vector;
entry = gate_offset(*desc);
asm volatile(
#ifdef CONFIG_X86_64
"mov %%" _ASM_SP ", %[sp]\n\t"
"and $0xfffffffffffffff0, %%" _ASM_SP "\n\t"
"push $%c[ss]\n\t"
"push %[sp]\n\t"
#endif
"pushf\n\t"
"or$%c[cs]\n\t"
"call *%[entryl $0x200, (%%" _ASM_SP ")\n\t"  /*调用真正的中断处理函数*/
__ASM_SIZE(push) " ]\n\t"
:
#ifdef CONFIG_X86_64
[sp]"=&r"(tmp)
#endif
:
[entry]"r"(entry),
[ss]"i"(__KERNEL_DS),
[cs]"i"(__KERNEL_CS)
);
} else /*如果不是外部中断,直接调用local_irq_enable开启中断*/
local_irq_enable();
}


vmx_handle_external_intr 处理了真正的外部物理中断,后面的exit handler 就只是增加个统计就可以了
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: