3

NMI を処理し、NMI が発生したときに何かをしたい。まず、単純な nmi ハンドラを作成します。

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

モジュールを作成して nmi ハンドラーを登録し、APIC を使用して NMI を 5 回トリガーします。

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);
  }
}

ここで、「insmod xxx.ko」と入力してこのモジュールをインストールし、その後、/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

nmi_handler の登録に成功(result=0)し、NMI が 5 回トリガーされましたが、nmi_handler に出力すべき文字列が見つかりませんでした。私は Ubuntu 10.04 LTS、Intel Pentium 4 デュアルコアで作業しています。

  • NMI ハンドラが実行されなかったということですか?
  • Linux で NMI を処理するにはどうすればよいですか?
4

1 に答える 1

2

誰でもない?パートナーからあと 3 日与えられたので、ソース コードと ULK3 を読みました。これで、質問 1 に答えることができます。

  • NMI ハンドルが実行されなかったということですか?

実際、IRQ 番号INT ベクタ番号異なります。関数 request_irq() は 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);
}

これを見てください: @irq: Interrupt line to setup . 引数irqは、割り込みベクトル番号ではなく、割り込み行番号です。ULK3 PDF、P203、タイマー割り込みの IRQ 0 を調べますが、その INT nr は 32 です! したがって、INT2(NMI) をトリガーしますが、ハンドラーは実際には INT34 を処理します! ソース コードでより多くの証拠を見つけたい (たとえば、IRQ を INT に変換する方法は? ハンドラーと init を変更し、irq=2 を要求し、Linux は INT=50 を割り当てます)、何も得られません。linux-xxx/arch/x86/include/asm/irq_vectors.h

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

しばらくお待ちください...質問 2 に答えるためにコードをさらに読み上げさせてください。

于 2012-03-27T09:29:23.767 に答える