Intel Atomプロセッサ ( 2 コアのx86_64 ) でLinux v3.2カーネル モジュールを作成しています。特定の IRQ 番号を無効にしたいのですが、Linux ではうまくいきません。
8259 PICチップと直接通信することで、Intel シンタックス x86 アセンブリの割り込みを簡単に無効にできるMS-DOSをデュアル ブートしています。
CLI ; disable all interrupts
MOV DX, 0x21 ; set 8259 ioport address
IN AL, DX ; store current interrupt mask in AL
AND AL, 0xDF ; modify mask to disable IRQ 5
OUT DX, AL ; send new mask to 8259
STI ; reenable interrupts
これは非常にうまく機能し、特定の IRQ 番号を無効にすることに成功しました。
Linux では、マクロを使用して割り込みを無効にする必要があることは認識してdisable_irq
いますが、効果がないようです。
#include <linux/interrupt.h>
...
disable_irq(5); // disable IRQ 5
このdisable_irq
行は、キャラクター ドライバーのopen
関数の先頭にあります。ただし、デバイス ノードを開くと、関数の残りのコードはopen
通常どおり実行されますが、IRQ 5 は有効のままですdisable_irq
。まったく効果がないように見えます。
マクロを正しく使用しているかどうか確信が持てなかったdisable_irq
ので、ロジックが正しいことを確認するために、ストレート インライン アセンブリを試すことにしました。シンプルに始めて、最初にすべての割り込みを無効にすることにしました。
__asm__("cli");
ただし、すべての割り込みが有効のままであるため、この単一の命令でさえ実行されないようです。
私は今完全に混乱しています.Linuxでストレートアセンブリが割り込みを無効にしないのはなぜですか? Linuxで割り込みを無効にする正しい方法は何ですか?
更新disable_irq
:の後に実行された場合にのみ機能することを発見しましたrequest_irq
。これはバグですか、それとも予想される動作ですか?
私が見ている動作を漠然と説明しているように見えるスレッドを見つけましたが、それは時代遅れであり、私のバージョンの Linux にまだ関連があるかどうかはわかりません。
更新 2:
Linux v3.2.0-4を実行しているDebianで試したカーネル モジュールは次のとおりです。
#include <linux/module.h>
#include <linux/kernel.h> /* Needed for KERN_INFO */
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/irqflags.h> /* Needed for local_irq_disable et al. */
MODULE_LICENSE("GPL");
static unsigned long flags = 0;
static int __init initialization_routine(void)
{
local_irq_save(flags);
local_irq_disable();
/* __asm__("cli"); */
/* disable_irq(15); */
return 0;
}
static void __exit cleanup_routine(void) {
local_irq_restore(flags);
/* __asm__("sti"); */
/* enable_irq(15); */
return;
}
module_init(initialization_routine);
module_exit(cleanup_routine);
disable_irq
/enable_irq
正常に動作します。私は単純な組み立て説明書にはあまり興味がありません (それらが機能しないのは奇妙なことです)。さらに、どのコアにも観察可能な影響がないのはなぜでしょうかlocal_irq_disable
。つまり、IRQ はすべてのコアに表示されます。
割り込みを確認するには、ターミナルで次のコマンドを実行します。
$ watch -d -n 0.5 cat /proc/interrupt
disable_irq
現在は完全に動作しているため、enable_irq
ある種の初期化コードを忘れているだけなのかlocal_irq_disable
、関連する機能が非推奨になっているのか、x86 プロセッサには適用されないのでしょうか?