Skip to contentSkip to conversation

NMI handling rework

DISCUSSION Corey Minyard 6 participants 9 messages Nov 7, 2002 – Nov 8, 2002

lore
Share & tools
lore
#0 lore raw

Ingo et al...

Since a lot of things have started tying into the NMI handler (oprofile, nmi watchdog, memory errors, bus error, now the IPMI watchdog), I think it better to use a request/release mechanism for the NMI handlers. Plus, I think the current NMI code is actually not correct, it's theoretically possible to miss NMIs if two occur at the same time. So I'm proposing the patch at http://home.attbi.com/~minyard/linux-nmi-v8.diff, relative to current 2.5. This has been posted on lkml, and reviewed by John Levon and others.

Thanks,

-Corey

#1 lore raw
Quoted 7 lines · Corey Minyard

Ingo et al...

Since a lot of things have started tying into the NMI handler (oprofile, nmi watchdog, memory errors, bus error, now the IPMI watchdog), I think it better to use a request/release mechanism for the NMI handlers.
Plus, I think the current NMI code is actually not correct, it's
theoretically possible to miss NMIs if two occur at the same time. So

How? The NMI interrupt should be internally masked till IRET. I think your code is ok, but i don't see how it takes care of concurrent users such as oprofile and the nmi watchdog, the nmi watchdog already programs its own interrupt interval if its shared, what is the intended base NMI interval? How about handlers requiring a different interrupt interval? I have code which does the following;

base NMI poll function with time interval T;
master queue with slots per timeout;
slots with task queues which are flushed whenever we hit the timeout;

you can therefore add tasks in with specific time intervals which will get triggered. This code currently is only running the nmi watchdog, but i'll be experimenting with various other handlers. I'll post a URL soon.

To support external devices which trigger NMI we can simply check wether we have hit an nmi interval period, if not we run through the NMI handler lists.

Zwane

Signature · 1 line
function.linuxpower.ca
#2 lore raw
Quoted 4 lines · Zwane Mwaikambo

On Thu, 7 Nov 2002, Corey Minyard wrote:

Quoted 8 lines
Quoted 5 lines

Ingo et al...

Since a lot of things have started tying into the NMI handler (oprofile, nmi watchdog, memory errors, bus error, now the IPMI watchdog), I think it better to use a request/release mechanism for the NMI handlers. Plus, I think the current NMI code is actually not correct, it's theoretically possible to miss NMIs if two occur at the same time. So

How? The NMI interrupt should be internally masked till IRET. I think your code is ok, but i don't see how it takes care of concurrent users such as oprofile and the nmi watchdog, the nmi watchdog already programs its own interrupt interval if its shared, what is the intended base NMI interval? How about handlers requiring a different interrupt interval? I have code which does the following;

NMIs cannot be masked, they are by definition non-maskable :-). You can get an NMI while executing an NMI.

NMIs are edge-triggered going into the processor. For external level-generating inputs, this is fine, because if two NMIs are occuring, you would handle the first, clear it, and there's some code that will turn off and back on the external NMI, if it is still asserted (by another input) you would get another NMI. From what I can tell (by inference, not by direct documentation) at least the IO APIC version is pulsed, because there is no code to turn it off. If a pulsed and another NMI occur at the same time, it is possible to miss one. It may be that this is not important. If so, it's easy to change it to only handle the first one (since the handlers are supposed to return a value saying if they handle the NMI or not). I'm not sure about this, maybe someone who is more familiar with the hardware could comment?

Quoted 8 lines

base NMI poll function with time interval T;
master queue with slots per timeout;
slots with task queues which are flushed whenever we hit the timeout;

you can therefore add tasks in with specific time intervals which will get triggered. This code currently is only running the nmi watchdog, but i'll be experimenting with various other handlers. I'll post a URL soon.

To support external devices which trigger NMI we can simply check wether we have hit an nmi interval period, if not we run through the NMI handler lists.

An NMI-based timer? I can see the use if you REALLY need accurate intervals, but you can't do much in an NMI, no spinlocks, even.

-Corey

#3 lore raw
Quoted 9 lines · Corey Minyard
Quoted 7 lines

How? The NMI interrupt should be internally masked till IRET. I think your code is ok, but i don't see how it takes care of concurrent users such as oprofile and the nmi watchdog, the nmi watchdog already programs its own interrupt interval if its shared, what is the intended base NMI interval? How about handlers requiring a different interrupt interval? I have code which does the following;

NMIs cannot be masked, they are by definition non-maskable :-). You can get an NMI while executing an NMI.

Not on the i386 family. Once an NMI is accepted by the CPU, it gets
internally masked until an iret instruction gets executed. If another NMI happens maenwhile, it's latched by the processor internally and dispatched as soon as NMIs are unmasked. Further NMIs received when masked are lost.

Check datasheets for details.

Signature · 3 lines
+  Maciej W. Rozycki, Technical University of Gdansk, Poland   +
+--------------------------------------------------------------+
+        e-mail: [email protected], PGP key available        +
#4 lore raw
In reply to Corey Minyard
Quoted 2 lines · Corey Minyard

NMIs cannot be masked, they are by definition non-maskable :-). You can get an NMI while executing an NMI.

"After an NMI interrupt is recognized by the P6 family, Pentium, Intel486, Intel386, and Intel 286 processors, the NMI interrupt is masked until the first IRET instruction is executed, unlike the 8086 processor."

- 18.22.2 NMI Interrupts, Intel IA32 System Developer's Manual vol3

Quoted 2 lines

An NMI-based timer? I can see the use if you REALLY need accurate intervals, but you can't do much in an NMI, no spinlocks, even.

You don't have to worry about protection in the handler, just make sure external references (non NMI) mask that handler. Alternatively you can do a spin_trylock if you really need to and consider it a lost NMI if you can't acquire.

Zwane

Signature · 1 line
function.linuxpower.ca
#5 lore raw
Quoted 14 lines · Zwane Mwaikambo
Quoted 2 lines · Corey Minyard

NMIs cannot be masked, they are by definition non-maskable :-). You can get an NMI while executing an NMI.

"After an NMI interrupt is recognized by the P6 family, Pentium, Intel486, Intel386, and Intel 286 processors, the NMI interrupt is masked until the first IRET instruction is executed, unlike the 8086 processor."

- 18.22.2 NMI Interrupts, Intel IA32 System Developer's Manual vol3

Quoted 2 lines

An NMI-based timer? I can see the use if you REALLY need accurate intervals, but you can't do much in an NMI, no spinlocks, even.

[SNIPPED...]

You can use a spinlock and, in fact, that's the only way you can protect a critical section. The other CPU will spin of course, just like the other CPU in a maskable interrupt. That's what spin-locks are for. With maskable interrupts, the "cli" affects only the CPU that actually fetches that instruction. That's why you need spin-lock protection when you have more than one CPU. With NMI, no CPU has the effect a "cli" would provide, so they just spin at the lock until the lock is released.

Cheers,
Dick Johnson
Penguin : Linux version 2.4.18 on an i686 machine (797.90 BogoMips).
Bush : The Fourth Reich of America

#8 lore raw
In reply to Zwane Mwaikambo
Quoted 1 line · Zwane Mwaikambo

How? The NMI interrupt should be internally masked till IRET. I think your

The question is not re-entrancy of the NMI handler (this cannot happen indeed) but whether if when an NMI is generated, and the CPU is handling an NMI, it will create another interrupt following the current one.

For the performance counters this seems to be the case, but Corey is unsure about other sources of NMIs...

Quoted 3 lines

you can therefore add tasks in with specific time intervals which will get triggered. This code currently is only running the nmi watchdog, but i'll be experimenting with various other handlers. I'll post a URL soon.

This can easily be built on top of the above API anyway, I think

regards
john

Signature · 3 lines
"When a man has nothing to say, the worst thing he can do is to say it
memorably."
	- Calvin Trillin
#6 lore raw
In reply to Richard B. Johnson
Quoted 8 lines · Richard B. Johnson
Quoted 4 lines · Zwane Mwaikambo

On Thu, 7 Nov 2002, Corey Minyard wrote:

Quoted 7 lines
Quoted 7 lines
Quoted 3 lines

NMIs cannot be masked, they are by definition non-maskable :-). You can get an NMI while executing an NMI.

"After an NMI interrupt is recognized by the P6 family, Pentium, Intel486, Intel386, and Intel 286 processors, the NMI interrupt is masked until the first IRET instruction is executed, unlike the 8086 processor."

- 18.22.2 NMI Interrupts, Intel IA32 System Developer's Manual vol3d

Thanks, and thanks to everyone else that pointed this out.

It is still possible, though unlikely, that two NMI sources could occur at the same time. Maybe that's not worth worrying about, and maybe for the APICs it works fine.

Quoted 5 lines
Quoted 3 lines
Quoted 3 lines

An NMI-based timer? I can see the use if you REALLY need accurate intervals, but you can't do much in an NMI, no spinlocks, even.

[SNIPPED...]

Quoted 9 lines

You can use a spinlock and, in fact, that's the only way you can protect a critical section. The other CPU will spin of course, just like the other CPU in a maskable interrupt. That's what spin-locks are for. With maskable interrupts, the "cli" affects only the CPU that actually fetches that instruction. That's why you need spin-lock protection when you have more than one CPU. With NMI, no CPU has the effect a "cli" would provide, so they just spin at the lock until the lock is released.

I should have been more precise here. You cannot use a spinlock that you use outside of the NMI, too. You might be holding the spinlock when the NMI occurs, and you would then be in deadlock.

-Corey

#7 lore raw
In reply to Corey Minyard
Quoted 2 lines · Corey Minyard

NMIs cannot be masked, they are by definition non-maskable :-). You can get an NMI while executing an NMI.

The intel docs certainly imply NMI is never interrupted by an NMI, so you have one per CPU to worry about