在 qemu - kvm 上获取多个性能监控中断

Geting multiple performance monitoring interrupt on qemu - kvm

我按照 给出的步骤和指示进行操作,现在可以得到一次计数器溢出中断。但是我不能多次得到它。无论我如何处理,Iterrupt 确实会再次触发。尽管我负责清除中断掩码。

没有任何代码很难判断,但如果您已经收到第一个 PMI,那么计数器寄存器设置正确,问题可能出在上层1

我会检查:

  1. 已将 EOI 发送到 LAPIC。

    我假设您使用固定向量配置了本地 APIC 的 PMI 寄存器。
    在这种情况下,您必须将 EOI 发送到 EOI 寄存器。
    引用英特尔(第 3 卷第 10.8.5 章)

    For all interrupts except those delivered with the NMI, SMI, INIT, ExtINT, the start-up, or INIT-Deassert delivery mode, the interrupt handler must include a write to the end-of-interrupt (EOI) register.

    示例代码:

    mov DWORD [APIC_BASE+0xb0], eax
    


    对于未重定位的 LAPIC,有效地址是 0xfee000b0.
    写入的值无关紧要,我拿起一个寄存器来保持指令的编码简短。
    当然,您必须根据您的上下文正确访问 LAPIC。

  2. 要设置 IF 标志

    IF 标志清除是一个不太可能的假设,但也很容易排除。
    由于中断门(但不是陷阱门)清除 IF,因此请确保您选择退出 ISR 的方式正确恢复 IF


1 如果我没记错的话,PMI 不需要重新装备。

这个问题在 forum 中讨论,他们发现这是内核中的错误。但是,您可以这样做来规避它: 在需要重新编程 msr MSR_PERF_FIXED_CTR0 (0x38d) 的任何地方,放置这些行:

Msr::write(Msr::MSR_PERF_FIXED_CTR0, 0xfffffffffff0ull);
Msr::write(Msr::MSR_PERF_FIXED_CTRL, 0x0);
Msr::write(Msr::MSR_PERF_FIXED_CTR0, 0xfffffffffff0ull);
Msr::write(Msr::MSR_PERF_FIXED_CTRL, 0xa);

值 0x0 和 0xa 之间的切换导致内核重新编程计数器。