对比线程,一个VCPU是什么

1. VCPU是线程不?

2. VCPU的线程是在用户态创建还是在KVM创建?
    用户态,qemu先创建用户态线程,然后调用KVM ioctl的KVM_CREATE_VCPU;
    最终会执行到kvm_main.c中kvm_vm_ioctl_create_vcpu,创建出VCPU;
    而用户态线程调用KVM ioctl的KVM_RUN时,发起调用的线程将会作为VCPU的线程执行Guest代码;

3. 进入Guest代码的点?
    在__kvm_vpu_run函数会将当前EL1寄存器状态保存,并打开EL2的trap,配置VTTBR、VPIDR等寄存器;
    配置VGIC并将Guest的EL1相关寄存器更改为Guest的context;
    真实进入Guest代码的点是__guest_enter(vcpu, host_ctxt),保存X19-X30寄存器并eret到EL1

4. 退出Guest代码的点?
    而Guest的退出必然是由exception(包括IRQ)触发的,最终又会走到__guest_exit(),保存Guest X2-X30;
    然后恢复Host X19-X30,将退出码放到X0并ret(X0再gcc中用于存函数返回值),回到__kvm_vpu_run函数。

5. VCPU的调度与用户线程的调度有何不同?
    VCPU的调度与线程是一样的;

6. 傻子也能看得出,VCPU的context比一个thread得多出一堆EL1的特殊寄存器吧,你告诉我VCPU的调度跟线程一样?
    是的,就是一样的,虽然KVM在task_struct中多注册了preempt_notifiers元素;
    我仔细分析了这个notifier:
        这个notifier中的preempt_ops有sched_in/sched_out两个方法:
        schedule调度入口在执行context_switch时,
            在prepare_task_switch中调用了fire_sched_out_preempt_notifier,
            在finish_task_switch中调用了fire_sched_in_preempt_notifier;
    struct kvm_vcpu->preempt_notifier中的sched_in/sched_out在上述两处被调用
    但这仅在CONFIG_PREEMPT_NOTIFIERS打开时,才可能有用(还受preempt_notifier_key变量控制);
    并且我自己查找并确认,#####sched_in/sched_out并没有保存/恢复EL1的各个特殊寄存器#####

7. 那么EL1的特殊寄存器集合是如何在每次context切换中保存/恢复的:
    我认为是在__kvm_vpu_run
    下面的分析没有Google到太权威的支撑,但是经过对kernel4.15代码的分析、搜索,我认为这是对的:
    首先要说,当VCPU在物理CPU中运行时,物理中断发生,是可以对其打断并进入异常向量处理的,
    根据__kvm_hyp_vector中的指示,大概就是陷入EL2 context,然后走el1_irq向量,然后执行__guest_exit,也就是4.中所说退出Guest的点
    在Guest退出点会恢复之前的线程上下文(依旧在EL2中),也就是回到__kvm_vcpu_run中,若事件可直接处理,在处理完毕后可直接再回到Guest上下文;
    若无法直接处理则保存Guest上下文并退出EL2。

    在整个退出EL2之前,我认为没有机会触发Host schedule,Host调度Timer等需要Host处理的中断,自然会使VCPU保存Guest上下文并走到Host处理流程。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值