时钟中断可以做 interrupt posting 吗?
当然是可以的,原始的 patch 在 2019 :
commit 0c5f81dad46c (“KVM: LAPIC: Inject timer interrupt via posted interrupt”)
添加如下测试:
static bool kvm_can_post_timer_interrupt(struct kvm_vcpu *vcpu)
{
// 只有 apicv ,其余都是 0
pr_info("pi : %d\n",pi_inject_timer);
pr_info("apicv : %d\n",kvm_vcpu_apicv_active(vcpu));
pr_info("mwait : %d\n",kvm_mwait_in_guest(vcpu->kvm));
pr_info("hlt : %d\n",kvm_hlt_in_guest(vcpu->kvm));
return pi_inject_timer && kvm_vcpu_apicv_active(vcpu) &&
(kvm_mwait_in_guest(vcpu->kvm) || kvm_hlt_in_guest(vcpu->kvm));
}
l1 中测试的结果:
[81572.263999] kvm: pi : 0
[81572.264160] kvm: apicv : 1
[81572.264315] kvm: mwait : 0
[81572.264496] kvm: hlt : 0
物理机中也是如此:
[223009.551111] kvm: A : 0
[223009.551112] kvm: B : 1
[223009.551112] kvm: C : 0
[223009.551112] kvm: D : 0
pi_inject_timer
取决于
if (pi_inject_timer == -1)
pi_inject_timer = housekeeping_enabled(HK_TYPE_TIMER);
housekeeping_enabled 相关到 docs/kernel/sched-isolation.md 中重新理解吧
hlt 和 timer
需要外部配置,不过这么用实际上是有 bug 的,而且 qemu 也不支持
case KVM_CAP_X86_DISABLE_EXITS:
r = -EINVAL;
if (cap->args[0] & ~KVM_X86_DISABLE_VALID_EXITS)
break;
if (cap->args[0] & KVM_X86_DISABLE_EXITS_PAUSE)
kvm->arch.pause_in_guest = true;
#define SMT_RSB_MSG "This processor is affected by the Cross-Thread Return Predictions vulnerability. " \
"KVM_CAP_X86_DISABLE_EXITS should only be used with SMT disabled or trusted guests."
if (!mitigate_smt_rsb) {
if (boot_cpu_has_bug(X86_BUG_SMT_RSB) && cpu_smt_possible() &&
(cap->args[0] & ~KVM_X86_DISABLE_EXITS_PAUSE))
pr_warn_once(SMT_RSB_MSG);
if ((cap->args[0] & KVM_X86_DISABLE_EXITS_MWAIT) &&
kvm_can_mwait_in_guest())
kvm->arch.mwait_in_guest = true;
if (cap->args[0] & KVM_X86_DISABLE_EXITS_HLT)
kvm->arch.hlt_in_guest = true;
if (cap->args[0] & KVM_X86_DISABLE_EXITS_CSTATE)
kvm->arch.cstate_in_guest = true;
}
结论
虚拟机靠 preempter timer 和 halt 之后,host 的 timer 注入
一个安静的 kvm 机器一天到晚都在 restart_apic_timer
@[
restart_apic_timer+1
kvm_arch_vcpu_load+419
finish_task_switch.isra.0+257
__schedule+911
schedule+94
yield_to+473
kvm_vcpu_yield_to+64
kvm_vcpu_on_spin+273
handle_pause+38
vmx_handle_exit+301
kvm_arch_vcpu_ioctl_run+1701
kvm_vcpu_ioctl+587
__x64_sys_ioctl+148
do_syscall_64+59
entry_SYSCALL_64_after_hwframe+110
]: 59
@[
restart_apic_timer+1
kvm_arch_vcpu_load+419
finish_task_switch.isra.0+257
__schedule+911
schedule+94
xfer_to_guest_mode_handle_work+97
kvm_arch_vcpu_ioctl_run+2174
kvm_vcpu_ioctl+587
__x64_sys_ioctl+148
do_syscall_64+59
entry_SYSCALL_64_after_hwframe+110
]: 8711
@[
restart_apic_timer+1
handle_fastpath_set_msr_irqoff+294
kvm_arch_vcpu_ioctl_run+1397
kvm_vcpu_ioctl+587
__x64_sys_ioctl+148
do_syscall_64+59
entry_SYSCALL_64_after_hwframe+110
]: 1519601
如果是的绝对的安静的时候,结果为:
- handle_fastpath_set_msr_irqoff
- handle_fastpath_set_tscdeadline ,显然,其实就是再重新编辑 tsc 的时间
static void restart_apic_timer(struct kvm_lapic *apic)
{
preempt_disable();
if (!apic_lvtt_period(apic) && atomic_read(&apic->lapic_timer.pending))
goto out;
if (!start_hv_timer(apic))
start_sw_timer(apic);
out:
preempt_enable();
}
start_sw_timer
@[
start_sw_timer+1
restart_apic_timer+110
handle_fastpath_set_msr_irqoff+220
kvm_arch_vcpu_ioctl_run+3236
kvm_vcpu_ioctl+621
__x64_sys_ioctl+130
do_syscall_64+59
entry_SYSCALL_64_after_hwframe+68
]: 24
@[
start_sw_timer+1
kvm_lapic_switch_to_sw_timer+63
kvm_arch_vcpu_ioctl_run+2628
kvm_vcpu_ioctl+621
__x64_sys_ioctl+130
do_syscall_64+59
entry_SYSCALL_64_after_hwframe+68
]: 290
本站所有文章转发 CSDN 将按侵权追究法律责任,其它情况随意。