我按照here给出了步骤和指示,现在可以获得一次计数器溢出中断。但我不能多次得到它。无论我管理什么,Iterrupt都注意到了。尽管我负责清除中断屏蔽。
答案 0 :(得分:1)
没有任何代码很难判断,但如果你已经收到第一个PMI,那么计数器寄存器设置正确,问题可能在于上层 1 。
我会检查:
已将EOI发送至LAPIC。
我假设您使用固定向量配置了本地APIC的PMI寄存器
在这种情况下,您必须将EOI发送到EOI注册表
引用英特尔(第10.8.5节,第3卷)
对于除NMI,SMI,INIT,ExtINT,启动或INIT-Deassert交付之外的所有中断 模式,中断处理程序必须包括对中断结束(EOI)寄存器的写入。
示例代码:
mov DWORD [APIC_BASE+0xb0], eax
对于未迁移的LAPIC,有效地址为0xfee000b0
写入的值不相关,我选择了一个寄存器来保持指令编码的简短
当然,您必须根据您的情况正确访问LAPIC
设置IF
标记
明确IF
标志是一个不太可能的假设,但也很容易排除
由于中断门(但不是陷阱门)清除IF
,请确保选择退出ISR的方式正确恢复IF
。
1 如果我没记错的话,PMI不需要重新安装。
答案 1 :(得分:1)
此问题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之间切换会导致内核对计数器重新编程。