You are here: Home / Projects / OSADL Linux Add-on Patch / 
2018-11-14 - 12:45
OSADL Projects

OSADL Linux Add-on Patch: NMI SysRq

Ping SysRqNMI SysRqLatency histograms - Built-in kernel patchset - Precise load measurement

Why NMI?

A system may become non-responsive in such a way that no input can be sent any longer to the system; such situation normally is the result of disabled interrupts and a complete system misbehavior that prevents it from re-enabling them. The last resort to gain diagnostic data in order to elucidate the origin of the system misbehavior is the non-maskable interrupt (NMI) that very probably still is executed from time to time and which may be polled. For such polling an input channel is needed that can be probed without the need for interrupt processing. An appropriate input channel for this purpose is the parallel interface aka Centronics printer port. It has eight output and four input channels. While the input channels are used to select an action to be executed when the NMI fires, the output channels can be used to signal a particular action – again without the need of interrupt processing. Some – rather oldish – computers still may be equipped with a Centronics printer port, while on newer computers a separate parallel printer port with PCI or PCIe bus interface must be installed (see figure at the left). A simple device with a 25-pin parallel port connector, eight LEDs to display the output channels and four touch buttons to set the input channels dubbed OSADL Parport Monitor can be ordered at OSADL (see figure at the right). Alternatively, it can be home made, since all required production material is available online. Last not least, the OSADL Parport Monitor can be bought at a popular Web store.

Kernel configuration help text

It sometimes is required to directly signal a specific state at the parallel port without using a driver, e.g. in a crashed system that still has some kind of life in it. Usage:
echo 0 .. 255 >/dev/setparport set output byte
echo 256 .. 511 >/dev/setparport boolean "or" action with output byte
echo 512 >/dev/setparport clear all output bits
echo 513 >/dev/setparport set all output bits
echo 514 >/dev/setparport invert output bits
echo 515 >/dev/setparport increment output bits
echo 516 >/dev/setparport decrement output bits
echo 517 >/dev/setparport copy status register to output bits
echo 518 >/dev/setparport copy jiffies LSBs >> 10 to output bits

In addition, this driver is used as a callback in the NMI handler. If installed, it allows to monitor NMI activity, e.g. using LEDs connected to the parallel port. The module parameter "nmicode" is then used to define the code to be sent at every NMI call, e.g. to increment the 8-bit number at the parallel port at every NMI
modprobe setparport nmicode=515
or
echo 515 >/sys/module/setparport/parameters/nmicode

The four input lines can also be used to request specific actions; defaults are enabled, if the parameter actions=yes is given:

  • S4: Show task states (SysRq-T)
  • S5: Sync block devices (SysRq-S)
  • S6: Unmount bloick devices (SysRq-U)
  • S7: Reboot (SysRq-B)

Please note that this is a simple polling mechanism; you need to press the button at least as long as until the next NMI occurs. This was deliberately implemented this way in order to keep it functional even if the entire IRQ subsystem is no longer working. The only prerequisite is a working memory mapping of the parallel port's IO region. If you want to let the NMI execute other debug actions, they must be programmed into drivers/misc/setparport.c.

Last not least, this driver can be used to output the LSB of the most recent syscall, hardware IRQ or software IRQ vector at the parallel port which may provide useful post-mortem information in case of a system crash.

System call:
modprobe setparport sysenter=1 sysexit=0
or
echo 1 >/sys/module/setparport/parameters/sysenter
echo 0 >/sys/module/setparport/parameters/sysexit

Hardware IRQ number:
modprobe setparport irqenter=1, irqexit=384
or
echo 1 >/sys/module/setparport/parameters/irqenter
echo 384 >/sys/module/setparport/parameters/irqexit

Software IRQ vector number:
modprobe setparport sirqenter=1 sirqexit=384
or
echo 1 >/sys/module/setparport/parameters/sirqenter
echo 384 >/sys/module/setparport/parameters/sirqexit

If configured as a built-in kernel module, the following kernel command line parameters apply:
setparport=<actions>,<nmicode>
setparportirq=<irqenter>,<irqexit>
setparportsirq=<sirqenter>,<sirqexit>
setparportsyscall=<sysenter>,<sysexit>

Download patch