虚拟中断控制器

虚拟机监控程序虚拟化到虚拟处理器的中断传送。 这是通过使用合成中断控制器 (SynIC) 实现的,这是虚拟化本地 APIC 的扩展;也就是说,每个虚拟处理器都有一个具有 SynIC 扩展的本地 APIC 实例。 这些扩展提供了一种简单的分区间通信机制,如下一章所述。 传递到分区的中断分为两类:外部和内部。 外部中断源自其他分区或设备,内部中断源自分区本身。

在以下情况下会生成外部中断:

  • 物理硬件设备生成硬件中断。
  • 父分区通常在模拟硬件设备) 的过程中断言虚拟中断 (。
  • 虚拟机监控程序 (传递消息,例如,由于对分区) 截获。
  • 另一个分区发布消息。
  • 另一个分区发出事件信号。

在以下情况下会生成内部中断:

  • 虚拟处理器 (ICR) 访问 APIC 中断命令寄存器。
  • 合成计时器过期。

本地 APIC

SynIC 是本地 APIC 的超集。 此 APIC 的接口由一组 32 位内存映射寄存器提供。 此本地 APIC (包括内存映射寄存器的行为) 通常与 P4/Xeon 系统上的本地 APIC 兼容,如 Intel 和 AMD 文档中所述。

虚拟机监控程序的本地 APIC 虚拟化可能会通过以下方式偏离物理 APIC 操作:

  • 在物理系统上,系统中每个处理器的IA32_APIC_BASE MSR 可能不同。 虚拟机监控程序可能要求此 MSR 包含分区内所有虚拟处理器的相同值。 因此,可将此 MSR 视为分区范围的值。 如果虚拟处理器修改此寄存器,则该值可能会有效地传播到分区中的所有虚拟处理器。
  • IA32_APIC_BASE MSR 定义用于启用或禁用 APIC 的“全局启用”位。 可能始终启用虚拟化的 APIC。 如果是这样,则此位将始终设置为 1。
  • 虚拟机监控程序的本地 APIC 可能无法生成虚拟 SCI, (系统管理中断) 。
  • 如果为分区中的多个虚拟处理器分配了相同的 APIC ID,则定向中断传递的行为是有限且未定义的。 也就是说,虚拟机监控程序可以免费将中断传送到一个虚拟处理器、具有指定 APIC ID 的所有虚拟处理器,或者没有虚拟处理器。 这种情况被视为来宾编程错误。
  • 某些内存映射的 APIC 寄存器可以通过虚拟 MSR 访问。
  • 虚拟机监控程序可能不允许来宾修改其 APIC ID。

本部分的其余部分仅介绍作为本地 APIC 扩展的 SynIC 功能的那些方面。

本地 APIC MSR 访问

虚拟机监控程序提供对高使用率内存映射 APIC 寄存器的加速 MSR 访问。 这些是 TPR、EOI 和 ICR 寄存器。 ICR 低寄存器和 ICR 高寄存器合并为一个 MSR。 出于性能原因,来宾操作系统应遵循有关使用 APIC MSR 的虚拟机监控程序建议。

MSR 地址 注册名称 说明
0x40000070 HV_X64_MSR_EOI 访问 APIC EOI
0x40000071 HV_X64_MSR_ICR 访问 APIC ICR-high 和 ICR-low
0x40000072 HV_X64_MSR_TPR 访问 APIC TPR

HV_X64_MSR_EOI

Bits 说明 属性
63:32 rsvdZ (保留,应为零) 写入
31:0 EOI 值 写入

HV_X64_MSR_ICR

Bits 说明 属性
63:32 ICR 高值 读/写
31:0 ICR 值低 读/写

HV_X64_MSR_TPR

Bits 说明 属性
63:8 rsvdZ (保留,应为零) 读/写
7:0 TPR 值 读/写

此 MSR 旨在加速对 32 位模式来宾分区中的 TPR 的访问。 64 位模式来宾分区应通过 CR8 设置 TPR。

合成群集 IPI

虚拟机监控程序支持超调用,允许将虚拟固定中断发送到任意虚拟处理器集。

Hypercall 说明
HvCallSendSyntheticClusterIpi 将虚拟固定中断发送到指定的虚拟处理器集。
HvCallSendSyntheticClusterIpiEx 与 HvCallSendSyntheticClusterIpi 类似,将稀疏 VP 集作为输入。

EOI 助手

“虚拟处理器助手”页中的一个字段是“EOI 助手”字段。 EOI Assist 字段位于覆盖页的偏移量 0 处,大小为 32 位。 EOI 助手字段的格式如下所示:

Bits 说明 属性
31:1 RsvdZ 读/写
0 不需要 EOI 读/写

来宾 OS 通过以原子方式将零写入虚拟 VP 助手页的 EOI Assist 字段,并检查“不需要 EOI”字段以前是否为零来执行 EOI。 如果是,OS 必须写入HV_X64_APIC_EOI MSR,从而触发对虚拟机监控程序的拦截。 建议使用以下代码来执行 EOI:

lea rcx, [VirtualApicAssistVa]
btr [rcx], 0
jc NoEoiRequired

mov ecx, HV_X64_APIC_EOI
wrmsr

NoEoiRequired:

如果满足以下条件,虚拟机监控程序在注入虚拟中断时设置“不需要 EOI”位:

  • 虚拟中断由边缘触发,并且
  • 没有优先级较低的中断挂起

如果稍后请求较低优先级的中断,虚拟机监控程序会清除“不需要 EOI”,以便后续 EOI 导致截获。

发生嵌套中断时,仅针对最高优先级中断避免 EOI 截获。 这是必需的,因为 OS 执行的 EOI 数量不保留计数。 因此,只能避免第一个 EOI,并且由于第一个 EOI 清除了“不需要 EOI”位,因此下一个 EOI 将生成截距。 但是,嵌套中断很少见,因此在常见情况下这不是问题。

请注意,设备和/或 I/O APIC (物理或合成) 不需要收到边缘触发中断的 EOI 通知 - 虚拟机监控程序仅截获此类 EO 以更新虚拟 APIC 状态。 在某些情况下,虚拟 APIC 状态可以延迟更新 - 在这种情况下,“NoEoiRequired”位由虚拟机监控程序设置,向来宾指示不需要 EOI 截获。 稍后,虚拟机监控程序可以根据“NoEoiRequired”位的当前值派生本地 APIC 的状态。

随时可以独立于中断活动和当时的 APIC 状态来启用和禁用此启发。 虽然启用了启发,但不管“不需要 EOI”值如何,传统 EOI 仍可以执行,但它们不会实现启蒙的性能优势。