Software Tuning, Performance Optimization & Platform Monitoring
Discussion around monitoring and software tuning methodologies, Performance Monitoring Unit (PMU) of Intel microprocessors, and platform monitoring

Generate NMI from PMI


I wonder if you can help this novice reconcile a few threads and get PMIs firing. I'm trying to generate an interrupt after retiring N instructions in an experimental operating system where maskable interrupts are masked off (EFLAGS.IF = 0). It looks like the way to do this is by overflowing a PMC which generates a PMI which can be used to trigger a NMI depending on how the LVT is configured. I found a number of posts helpful including this one:

What I've been reading:

A PMI is delivered via the local APIC (vol. 3a 10-1 & vol. 3b, which is considered an external hardware interrupt (vol. 3a 6.3.1). Maskable hardware interrupts include interrupts delivered to the processor via the local APIC(vol 3a 6.3.2). Specifically, the local APIC can ONLY send interrupt request vectors in the range 16-255 (vol. 3A 10-15)

But this is refined by the NMI (vol. 3a 6.8.1):

The IF flag does not affect non-maskable interrupts (NMIs) delivered to the NMI pin or delivery mode NMI messages delivered through the local APIC, nor does it affect processor generated exceptions. 

I'm struggling to understand the note here that "The PMI is always non-maskable. It seems to me that the PMI is only maskable if the local vector table entry (vol. 3a 10.5.1) chooses NMI as the delivery mode.

Assuming I configured the fixed PMC for retired instructions correctly (I am seeing bit 32 set in the IA32_PERF_GLOBAL_STATUS flip on), and that I'm using x2APIC mode, would if be correct to simply:

1) write a handler and insert it in the IDT (as element 32 - 255),

2) set the LVT entry corresponding to a performance monitoring overflow (0x834 in MSR space) to that vector established in 1) then set the delivery mode to NMI?


Or maybe implement the NMI handler (vector 2) as my handler, put a bogus 16 < value < 255 into the vector field and set delivery method to NMI?

I hope this question makes sense; I'm happy to clarify any part. Thanks.

0 Kudos
1 Reply

Or maybe implement the NMI handler (vector 2) as my handler, put a bogus 16 < value < 255 into the vector field and set delivery method to NMI?

I got this option to work, but value can even be in the < 16 range and still trigger the NMI. This doesn't make sense to me because (vol. 3A 10-15) clearly says:

Bit 6: Receive Illegal Vector.

Set when the local APIC detects an illegal vector (one in the range 0 to 15) in an interrupt message it receives or in an interrupt generated locally from the local vector table or via a self IPI. Such interrupts are not delivered to the processor; the local APIC will never set an IRR bit in the range 0 to 15. 

Which, since the APIC is generating the vector from it's LVT, I would think would prevent delivering the interrupt to the processor. If anyone can shed light on this, or if I missed some technique that allows the programmer to run an arbitrary handler while being delivered as a NMI, I would appreciate any input.