Qemu-KVM Guest OS Time Tick Source (3)

在(1)中详细阐述了KVM是如何模拟内核PIT以及如何将timer中断注入到guest中去的。但是,那时对这一整套的机制理解还不够深,现在通过研究代码,理解又上升了一层,所以加深的总结一下。
核心想搞清楚的问题是如下几个:
1. 假如guest中设定PIT的频率为1000Hz,那么KVM如何为模拟PIT产生这个1000Hz的时钟源
2. 当时钟周期到时,会产生物理中断,KVM是如何将这个物理中断最终注入到guest中,使guest产生一个虚拟时钟中断的
第一个问题在(1)中讲的比较清楚,总的来讲就是,KVM的内核模拟PIT实际是用host Linux的hrtimer机制来产生时钟源。模拟PIT时钟源周期是1ms,那么KVM就创建一个hrtimer,过期时间是now+1ms。
第二个问题比较复杂。首先,当now+1ms到时,host hrtimer所利用的物理时钟设备,如物理PIT,会产生一个物理中断。这里就要分两种情况来讨论了:
1. 第一种情况是,物理中断产生的这一刻是guest在运行,这种情况下又有两种方式可以将虚拟时钟中断注入guest中:
1.1 直接注入进去
1.1.1 先要发生VM exit,在vmx_vcpu_run的最后调用complete_interrupt,会将vcpu.arch.interrupt_pending位置1,并从VMCS中取出中断信息保存到vcpu控制结构中去。
1.1.2 下一次迭代重新进入vcpu_guest_enter后,在vmx_vcpu_run之前会调用inject_pending_event。它会检测vcpu->arch.interrupt_pending位,发现是1,那么调用kvm_x86_ops->set_irq将中断真正注入VMCS中去,在VM entry时guest就能响应虚拟中断了。
1.2 通过模拟PIC或模拟APIC注入虚拟中断
1.2.1 先要发生VM exit,随后vmx_vcpu_run返回到vcpu_guest_enter中后将开中断,立刻进入host中断处理流程。
1.2.2 host ISR发现为模拟PIT创建的hrtimer到期,将在softirq中调用它的回调函数kvm_timer_fn。
1.2.3 kvm_timer_fn将设置ktimer.pending为1,其实就是vcpu.kvm->arch.pit->pit_state.pit_timer. pending这是模拟了PIT设备产生一次时钟信号的操作。
1.2.4 之后vcpu_guest_enter返回到__vcpu_enter中,将调用kvm_cpu_has_pending_timer,其实就是去检测那个pending位,将发现已经有了pending timer,那么会调用kvm_inject_pending_timer_irqs将这个时钟中断注入到模拟PIC或模拟APIC中去,这是模拟了一次PIT设备向PIC或APIC发送一个中断信号的操作
1.2.5 下一次迭代重新进入vcpu_guest_enter后,在vmx_vcpu_run之前会调用inject_pending_event。它中间会调用kvm_cpu_has_interrupt去检测模拟PIC或模拟APIC中是否有中断触发,发现有,将首先设置 vcpu->arch.interrupt_pending位为1,再 调用kvm_x86_ops->set_irq将中断真正注入VMCS中去,在VM entry时guest就能响应了,这是模拟了一次PIC或APIC向CPU发送一个中断信号的操作
上述两种情况会同时发生,只有在最后inject_pending_event中,如果前一种方式存在,那么后面这种方式就不用注入了,因为检测vcpu->arch.interrupt_pending在前,如果为1后面会直接返回了。
2. 第二种情况时,物理中断发生时guest并没有在运行。那么将直接进入host ISR,此时只能是通过上述第二种方式将虚拟时钟中断注入到guest中去。这应该就是为什么要设计两种注入方式的原因吧。

1. Interrupt occurs when guest code is running
1. vmx_vcpu_run--> complete_interrupt --> vcpu.arch.interrupt.pending = 1
2. vcpu_enter_guest (before vmx_vcpu_run) --> inject_pending_event --> kvm_x86_ops->set_irq (vmx_inject_irq) --> vmcs_write (VM_ENTRY_INTR_INFO_FIELD)

2. Timer ISR --> hrtimer_func (kvm_timer_fn) --> timer->pending --> __vcpu_run (after vcpu_enter_guest return) -->
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值