Skip to the content.

dm 是什么意思 ?

具体含义未知,不过应该是来自于 userspace 的:

kvm_cpu_accept_dm_intr dm_request_for_irq_injection

request_irq_exits 这个字段也是和这个有关系的

看上去是用户的 irq windows 而已

? 这里的 dm 是 Device Model(设备模型),指 QEMU 这类 userspace VMM 中负责模拟设备的部分。

似乎又到了死对头那里了 !

因此,Device Model 是有依据的解释;但我尚未找到该函数作者直接展开这个缩写的证据。

代码真正区分的是:谁负责提供待注入中断,以及是否需要返回 userspace 等它提交。

当前 dm_request_for_irq_injection() (arch/x86/kvm/x86.c:10540) 的实现很明确:

return vcpu->run->request_interrupt_window && likely(!pic_in_kernel(vcpu->kvm));

对应关系是:

irqchip 配置 这条 userspace 窗口请求路径 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ PIC、IOAPIC、LAPIC 都在 userspace 可以使用 ─────────────────────────────────────────────────────── ────────────────────────────────────────────── split irqchip:LAPIC 在内核,PIC、IOAPIC 在 userspace 可以使用,KVM_INTERRUPT 用于提供 ExtINT 向量 ─────────────────────────────────────────────────────── ────────────────────────────────────────────── 完整的 in-kernel irqchip 此判断恒为假,不走这条路径

所谓“非 dm 场景”,最直接的例子就是 in-kernel LAPIC timer 中断:

内核模拟的 LAPIC timer 到期 → 中断进入虚拟 LAPIC → KVM 获取待注入向量 → guest 可以接收时注入

KVM 在 arch/x86/kvm/x86.c:10792 中直接调用:

int irq = kvm_cpu_get_interrupt(vcpu); kvm_queue_interrupt(vcpu, irq, false); kvm_x86_call(inject_irq)(vcpu, false);

如果暂时不能注入,这条路径也会调用 enable_irq_window(),等 guest 可接收时继续处理,无需为了取中断向量返回 userspace。

还有一个关键点:设备由 QEMU 模拟,也不代表其中断一定走 dm_request_for_irq_injection()。 QEMU 可以通过 KVM_IRQ_LINE 向内核 irqchip 报告 IRQ 引脚状态,后 续由内核中断控制器处理。这里设备仍然属于 userspace Device Model,却不需要这套窗口请求协议。

所以,读这几个函数时,把 dm 理解成 “userspace 直接提交中断向量的那条路径” 最准确;它不是把所有虚拟设备正式划分为 “DM / 非 DM” 两类的标志。

flexpriority_enabled

kvm 参数 flexpriority_enabled 是做什么的?

codex

• flexpriority_enabled 可以理解为:KVM 是否启用 Intel FlexPriority,利用硬件加速 guest 对 APIC 任务优先级寄存器 TPR 的访问,减少 VM exit。

这里的 priority 指 guest 的中断优先级,与宿主机调度 vCPU 的优先级无关。

  1. 它解决什么问题?

Guest 通过 Local APIC 的 TPR(Task Priority Register)设置中断优先级门槛。提高 TPR 可以屏蔽较低优先级的中断,降低 TPR 则可能让等待中的中断变得可投递。

Guest 访问 TPR 的方式包括:

• xAPIC 模式:访问 APIC MMIO 页的 0x80 偏移。 • 64 位模式:通过 CR8 访问 TPR 的优先级部分。

如果这些访问频繁触发 VM exit,再由 KVM 模拟,开销就很大。FlexPriority 的核心是:让硬件使用内存中的虚拟 TPR,直接处理符合条件的访问。 Intel 技术说明 (https://builders.intel.com/docs/Open_Standard_Virtualization_White_Paper_v2013-06-25.pdf)

  1. 对应到你这份代码

arch/x86/kvm/vmx/capabilities.h:299 明确定义了 FlexPriority 需要的两个能力:

static inline bool cpu_has_vmx_flexpriority(void) { return cpu_has_vmx_tpr_shadow() && cpu_has_vmx_virtualize_apic_accesses(); }

可以分别理解为:

能力 作用 ━━━━━━━━━━━━━━━━━━━━━━━━━━ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ TPR shadow 通过 virtual-APIC page 保存虚拟 TPR,让硬件处理相应访问 ────────────────────────── ───────────────────────────────────────────────────────────────────────── Virtualize APIC accesses 识别 guest 对 APIC 页的访问,使 xAPIC MMIO 访问进入硬件 APIC 虚拟化路径

两者配合后的典型路径是:

guest 访问 xAPIC 的 TPR ↓ 硬件识别 APIC 页及 TPR 偏移 ↓ 读写 virtual-APIC page 中的虚拟 TPR ↓ 通常无需 VM exit

但它不代表所有 APIC 操作都不退出。以基础 TPR shadow 路径为例,降低 TPR 导致其优先级低于 TPR_THRESHOLD 时,仍会触发退出,让 KVM 重新处理中断状态。对应代 码是 vmx_update_cr8_intercept() (arch/x86/kvm/vmx/vmx.c:6873)。

  1. enabled 的具体含义

它是全局模块参数,默认打开:

bool __read_mostly flexpriority_enabled = 1; module_param_named(flexpriority, flexpriority_enabled, bool, 0444);

硬件不支持上述两个能力时,初始化会将它清零。对于具体 vCPU,还需要内核管理 LAPIC;运行时在 xAPIC 模式下启用 SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES。见 vmx_set_virtual_apic_mode() (arch/x86/kvm/vmx/vmx.c:6887)。

一个容易误读的地方:这份代码里,flexpriority_enabled = 0 不等于关闭所有 TPR shadow,也不等于关闭整个 APICv。

TPR shadow 自己的判断独立于这个参数:

static inline bool cpu_need_tpr_shadow(struct kvm_vcpu *vcpu) { return cpu_has_vmx_tpr_shadow() && lapic_in_kernel(vcpu); }

所以读代码时,把 flexpriority_enabled 主要理解成 xAPIC MMIO 访问加速这条路径的开关,比把它理解成“APIC 虚拟化总开关”更准确。

本站所有文章转发 CSDN 将按侵权追究法律责任,其它情况随意。