概要

「割り込み処理」とは、読んで字のごとく、通常の流れでプログラムを実行している所へ割り込んで別のプログラムを実行させることです。通常は、周辺デバイスなどからのイベント通知に使われるハードウェア割り込みを指しますので、本稿でも以下その意味で使います。

Linuxに限らず、現在一般的なOSでは、ディスクやマウスなどのデバイス入出力の他、タスクの切り替えや定時処理などさまざまな場面で割り込み機能を駆使して作られています。

ところで、現在一般的なPC/PCサーバは、IBM PCやIBM PC/AT以来約30年間、互換性を保ちながら発展してきたものであり、こと割り込みまわりに関しては、たいへんに複雑です。これを制御するLinuxも、この複雑さに対応するために、複雑な作りになっています。
本稿では、この複雑なLinuxの割り込み処理の低レイヤ (もっともハードウェアに近い部分) について解説していきます。

今回の調査では次の環境を使用しています。

 

  • Red Hat Enterprise Linux 5.6
  • x86_64

上記の通りx86_64アーキテクチャの場合について解説していますが、RHEL6、i386の環境でもそれほど大きな違いはないと思われます。

x86プロセッサの例外処理

割り込みは、x86プロセッサでは「例外」と同じような動作をします。
例外とは、0除算や保護レベルに対する違反、不正命令などにあたった際の処理であり、割り込みは周辺デバイスなどからのイベント通知です。いずれの場合も、プロセッサは現在実行中のプログラムを中断し、専用の割り込みハンドラ/例外ハンドラを呼び出します。

ハンドラは通常のサブルーチンに類似したプログラムです。ハンドラが実行を終えると、中断したプログラムの実行に戻ります。
ハンドラは、割り込みや例外の種類毎にIDT (Interrupt Descriptor Table) なるテーブルに、その先頭アドレスなどを記載しておきます (これはOSが用意します)。IDTのエントリ数は256個ですが、うち32が例外、224が割り込みに割り当てられています。

IDTの構成は、LDT (Local Descriptor Table) やGDT (Global Desciptor Table) に類似しています。割り込みも例外も、プロセッサの保護レベルによらず発生しますが、ハンドラはいずれもRing 0 (カーネルモード) で実行されますので、(LDTやGDTによる特権レベル間コールと同様) 「ゲート」という仕組みが使われます。
割り込み用に利用できるゲートとしては、「割り込みゲート」、「タスクゲート」、「トラップゲート」がありますが、Linuxでは割り込みゲートを利用しています。割り込みゲートの特徴は、ハンドラ呼出し時に続く割り込みが禁止される (EFLAGSレジスタのIFがクリアされる)点にあります。

 

割り込みコントローラ

割り込みコントローラは、デバイスからの割り込み信号を受け取り、プロセッサに伝える働きがあります。
プロセッサが必要とする割り込み情報としては割り込みベクタなどがあり、またマルチプロセッサシステムにおいては、どのプロセッサに割り込みを通知するかも判断しなければなりません。これらはOSが割り込みコントローラに設定します。

8259 PIC

8259 PICは、Intel 8080時代から使われている割り込みコントローラで、単体で8つのデバイスからの割り込みをCPUにマルチプレクスし、割り込みベクタ番号を送出します。PCでは2つの8259をカスケード接続していますので、下図のように15のデバイスからの割り込みを受け付けます。デバイスからの割り込みを受け付ける部分をピンと呼んだりします。

8259での接続ピンは、IRQ0 はタイマ、IRQ4はCOMA、…などそれぞれ割り込みラインが割り当てられています。PCIの割り込みは、残るIRQ5、IRQ9、IRQ10、IRQ11などを (共有の上) 利用します。ただし、ISAの割り込みはエッジトリガであったため、共有はできません。

下記のAPICは、PICの機能を内包しており、起動時にはPIC互換モードになっています。APICの機能を使うには、APICモードに移行します。

APIC (Advanced Programmable Interrupt Controller)

APICは、Intelが開発したx86アーキテクチャにおける割り込みコントローラで、マルチプロセッサシステム対応に伴い登場しました。

単一のCPUに対応し、割り込みの受信や自CPU、他のCPUへの割り込み送信 (プロセッサ間割り込み、IPI: Inter-Processor Interrupt) を行うLocal APIC (LAPIC)と、デバイスからの割り込みを受けて特定のLAPICにベクタなどを指定して送信するI/O APICで構成されています。

現在では、LAPICはCPUに、I/O APICはサウスブリッジ (あるいはI/O Controller Hubなど) に内蔵されています。サウスブリッジ内蔵のI/O APICは、通常24個のピンを持ちますが、I/O APICは増設することもでき、多数のデバイスを繋いでいてもピンが共有されないよう構成することもできます (共有する構成が普通ではあります)。

割り込みの設定

各割り込みにはそれぞれ以下のような設定が可能です。
これらの設定項目を、I/O APICの各ピンに予め設定したり、IPI送信時に設定したりすることにより、割り込みがどのように配送されるかが決まります。

xAPIC / x2APIC

xAPICはExtended APICの略で、ハードウェア的には上図にある専用のAPIC Busを使わずFSBを共用するようになりましたが、ソフトウェア的にはLow Priorityモードが使えなくなった程度の違いしかありません。

Low Priorityモードは、APIC Busの調停機能の特性を使って配送先LAPICを決定していましたが、FSBの調停機能は仕組みが異なるためうまく使えなくなったものと思われます。配送先はOSが指定した方が性能的にも有利です。

x2APICは、Nehalemマイクロアーキテクチャから使用されており、APICレジスタに (メモリマップI/Oではなく) MSR経由でアクセスし、4G (40億) プロセッサをサポートしています。後方互換性のためxAPICモードを実装しています。