silverbullettt
silverbullettt

Reputation: 868

Why can't I handle NMI?

I want to handle NMI and do something when NMI occur. Firstly I write a naive nmi handler:

static irqreturn_t nmi_handler(int irq, void* dev_id) {
  printk("-#_#- I'm TT, I am handling NMI.\n");
  return IRQ_HANDLED;
}

And write a module to register my nmi handler, then use APIC to trigger NMI 5 times:

static void __init ipi_init(void) {
  printk("-#_#- I'm coming again, hahaha!\n");

  int result = request_irq(NMI_VECTOR, 
      nmi_handler, IRQF_DISABLED, "NMI Watchdog", NULL);
  printk("--- the result of request_irq is: %d\n", result);
  int i;
  for (i = 0; i < 5; ++i) {
    apic->send_IPI_allbutself(NMI_VECTOR);
    ssleep(1);
  }
}

Now I type "insmod xxx.ko" to install this module, after that, I check the /var/log/syslog:

kernel: [ 1166.231005] -#_#- I'm coming again, hahaha!
kernel: [ 1166.231028] --- the result of request_irq is: 0
kernel: [ 1166.231050] Uhhuh. NMI received for unknown reason 00 on CPU 1.
kernel: [ 1166.231055] Do you have a strange power saving mode enabled?
kernel: [ 1166.231058] Dazed and confused, but trying to continue
kernel: [ 1167.196293] Uhhuh. NMI received for unknown reason 00 on CPU 1.
kernel: [ 1167.196293] Do you have a strange power saving mode enabled?
kernel: [ 1167.196293] Dazed and confused, but trying to continue
kernel: [ 1168.201288] Uhhuh. NMI received for unknown reason 00 on CPU 1.
kernel: [ 1168.201288] Do you have a strange power saving mode enabled?
kernel: [ 1168.201288] Dazed and confused, but trying to continue
kernel: [ 1169.235553] Uhhuh. NMI received for unknown reason 00 on CPU 1.
kernel: [ 1169.235553] Do you have a strange power saving mode enabled?
kernel: [ 1169.235553] Dazed and confused, but trying to continue
kernel: [ 1170.236343] Uhhuh. NMI received for unknown reason 00 on CPU 1.
kernel: [ 1170.236343] Do you have a strange power saving mode enabled?
kernel: [ 1170.236343] Dazed and confused, but trying to continue

It shows that I register nmi_handler successfully(result=0), and NMI were triggered 5 times, but I didn't find sting that should be outputed in nmi_handler. I work on Ubuntu 10.04 LTS, Intel Pentium 4 Dual-core.

Upvotes: 3

Views: 4896

Answers (1)

silverbullettt
silverbullettt

Reputation: 868

Nobody? My partner gave me 3 more days, so I read the source code and ULK3, now I can answer question 1:

  • Does it mean my NMI handle didn't execute?

In fact, IRQ number and INT vector number are different! The function request_irq() call setup_irq():

/**
 *  setup_irq - setup an interrupt
 *  @irq: Interrupt line to setup
 *  @act: irqaction for the interrupt
 *
 * Used to statically setup interrupts in the early boot process.
 */
int setup_irq(unsigned int irq, struct irqaction *act)
{
    struct irq_desc *desc = irq_to_desc(irq);

    return __setup_irq(irq, desc, act);
}

Look at this: @irq: Interrupt line to setup . The argument irq is interrupt line number, not interrupt vector number. Look up ULK3 PDF, P203, Timer interrupt has IRQ 0, but its INT nr is 32! So I trigger the INT2(NMI) but my handler handle the INT34 actually! I want to find more evidence in source code(e.g. how to convert IRQ to INT? I modify my handler and init, I request irq=2, and Linux allot INT=50), but get nothing, expect linux-xxx/arch/x86/include/asm/irq_vectors.h

/*
 * IDT vectors usable for external interrupt sources start
 * at 0x20:
 */
#define FIRST_EXTERNAL_VECTOR       0x20

Wait me for a while...let me read more codes to answer question 2.

Upvotes: 2

Related Questions