QEMU中VCPU线程间的IPI发送核间中断(基于QEMU2.0.0)

来源:互联网 发布:迅龙数据恢复软件安卓 编辑:程序博客网 时间:2024/06/05 07:53
 我们都知道对于多核CPU需要IPI机制进行通知或者唤醒,当CPU接收到的中断不是本地中断的时候,需要通过IPI唤醒对端CPU,然后进行中断的传递
那么QEMU中如何实现不同VCPU通知的呢

首先在初始化KVM虚拟机的时候,注册了核间通信处理函数,这个函数完成了IPI的功能

int kvm_init(QEMUMachine *machine){
     /*
     * 注册CPU见通信接口
     */
    cpu_interrupt_handler = kvm_handle_interrupt;          
}


/*
* CPU的IPI通信接口
*/
static void kvm_handle_interrupt(CPUState *cpu, int mask)
{
     /*记录中断请求号*/
    cpu->interrupt_request |= mask;

     /*如果不是本地CPU,启动相应的VCPU接收中断*/
    if (!qemu_cpu_is_self(cpu)) {
        qemu_cpu_kick(cpu);
    }
}

/*
* 启动指定的VCPU,
*/
void qemu_cpu_kick(CPUState *cpu)
{
     /*
     * 唤醒所有等待在cpu->halt_cond上的VCPU线程,关于QEMUCond,请参考《QEMU VCPU线程同步机制之QemuCond(基于QEMU2.0.0)》
     */
    qemu_cond_broadcast(cpu->halt_cond);

     /*
     * 对于不是TCG的且还没有被kick的VCPU线程进行唤醒
     */
    if (!tcg_enabled() && !cpu->thread_kicked) {
        qemu_cpu_kick_thread(cpu);
        cpu->thread_kicked = true; //标明指定的VCPU线程已被唤醒
    }
}


/*
* 唤醒指定的VCPU线程
*/
static void qemu_cpu_kick_thread(CPUState *cpu)
{
#ifndef _WIN32
    int err;

     /*
     * 通过pthread_kill将SIG_IPI信号发送到指定的VCPU线程,将其唤醒
     */
    err = pthread_kill(cpu->thread->thread, SIG_IPI);
    if (err) {
        fprintf(stderr, "qemu:%s: %s", __func__, strerror(err));
        exit(1);
    }
#else /* _WIN32 */
#endif
}



我们下面来看一下IPI的使用示例,

pic_irq_request是通过pc_init->pc_allocate_cpu_irq,注册的irq的handler

pic_irq_request
-> cpu_interrupt
-> cpu_interrupt_handler //这里调用kvm_handle_interrupt
-> kvm_handle_interrupt //唤醒指定VCPU的线程,发送中断


0 0