Share
Embed
Interrupts on xv6
Takuya ASADA
September 02, 2012
Transcript
39 slides
-
資料 Software Developers Manual http://download.intel.com/products/ processor/manual/325462.pdf ICH10 Datasheet
http://www.intel.com/assets/pdf/ datasheet/319973.pdf -
割り込みとは 現在CPU上で実行しているプログラムを停止 して別の処理を実行する為にCPUが持つ機能 UNIX上のアプリケーションにおける「シグナル」に 近い概念 二種類ある
ハードウェア割り込み ◦ ハードウェアからCPUへ「キーボード押されたよ」な どのメッセージを通知するのに使う ◦ 単に「割り込み」と呼ばれる事もある ソフトウェア割り込み ◦ ソフトウェアから割り込みを起こせる ◦ モード切替に利用される→システムコールに使う -
ハードウェア割り込みの例 ATAコントローラ HDDへのread/writeリクエストの完了通知 シリアルポート・NIC 受信通知
送信完了通知 タイマー 一定期間毎に割り込み 指定期間後に割り込み -
ATA受信割り込みの例 1. ユーザプログラムがファイルに対して writeシステムコールを実行 2. ファイルシステムがバッファキャッシュ へ書き込み(ダーティフラグON) 3. バッファキャッシュがHDDへライトバッ ク
4. ATAドライバがATAコントローラへ書き込 み要求を送信 5. 書き込みが終了したらバッファキャッ シュのダーティフラグをクリア -
書き込みが終了したら? 割り込みを使わない場合 ATAコントローラのステータスレジスタを確認 し続ければ完了したかどうか分かる send_write_request(buffer); while(read_ata_status() & ATA_STATUS_BUSY) ;
buffer.is_dirty = 0; busy waitになってしまう→CPUの無駄 -
書き込みが終了したら? 割り込みを使う場合 送信完了時の処理は、割り込み着信時に実行すれ ばいい 書き込み処理: send_write_request(buffer); sleep(buffer); 割り込みハンドラ: buffer
= find_buffer(ata_reg); buffer.is_dirty = 0; wakeup(buffer); busy waitしていない分のCPU時間を別の処 理(別のプロセスを実行など)にまわせる sleep()/wakeup()で待ち合わせ -
割り込みハンドラ 割り込みを受けた時にCPUが実行するプロ グラム(関数呼び出しを伴わない関数のよ うなもの) 割り込みハンドラ実行時にCPUがレジスタ の状態をスタックへ退避 ハードウェア割り込みの場合は、デバイス
のレジスタを読んで割り込みの処理に応じ た最小限の処理を実行 割り込みハンドラから終了用の命令を実行 して、スタックから割り込み前の状態へ復 帰 -
プリエンプティブマルチタスクと割 り込み プリエンプティブマルチタスク: カーネルがプロセスへのCPUの割り当 て時間を管理、タイマーを使ってアプリ ケーションを一定時間毎に切り替え プロセスが無限ループなどに陥りカーネ ルへ制御を渡さない場合でもタイマー割
り込みにより中断され、割り当て時間を 使い切ったら他のプロセスへ切り替えら れる 割り込みがないと実現出来ない -
例外 割り込みとは別の概念だが、実装上の共 通点は多いためx86では共通の仕組みで 取り扱われている アプリケーション上の例外とほぼ意味は同 じだが、CPU上の機能 例外の例:
ゼロ除算、無効な命令、ページフォール ト、一般保護例外、ブレークポイント -
割り込み/例外ベクタ 0-255のベクタ番号が割り込みと例外に 割り当てられる 例外は要因毎に0-19の固定された値 ソフト割り込みは0-255へ割り込み可 ハードウェア割り込みはLAPIC経由の場合
16-255へ割り込み可 OSはIDT(Interrupt Descriptor Table) を作成し、CPUへアドレスを設定 -
IDT(Interrupt Descriptor Table)と IDTR 各ベクタの割り込みハンドラの情報を持 つGate Descriptorが並んでいるメモリ上 のテーブル
テーブルの先頭アドレスとLimit値 (テーブルのサイズ、255未満のGate数 に対応)をCPUのIDTRに書き込む事に より設定(IDTRを設定しない限り、 CPUは割り込み時に何をしたらいいか 分からない) -
Gate Descriptor 前述の「割込みハンドラ」のアドレスを持つ 構造体 単なる関数へのポインタではなくて、セグメ ントの設定とか権限(Ring)とか16 bit/32 bit
のモード選択とか、幾つかのパラメータを含 む Task gate, Interrupt gate, Trap gateの三種類あ る Task gateはHWのマルチタスク機能でハンドリング する方法で今は使われていない Interrupt gateとTrap gateは普通に割り込みハンドラ へジャンプする方法 EFLAGS.IFフラグをクリアするか否かが違い -
IDT,IDTR,Gate descriptorの関係 Base address Limit 0 15 16 47 IDTR
register IDT Gate for interrupt 0 Gate for interrupt 1 Gate for interrupt 2 Gate for interrupt 3 … Gate for interrupt 255 offset 15..0 segment selector rese rved DPL /P offset 31..16 Interrupt Gate -
xv6のIDT周りを見てみる main.c:main() tvinit(); 割り込みベクタの設定 mpmain(); ◦ idtinit();
IDTRの設定 trap.c:tvinit() for(0..255) SETGATE(idt[i] … vectors[i] …) idt[i]にvectors[i]を割り込みハンドラとしたgate descriptorを設定 システムコールだけDPL_USERに trap.c:idtinit() x86.h:lidt() ◦ asm volatile(“lidt (%0)” :: “r” (pd)); LIDT命令でidtのアド レスを設定 -
xv6の割り込み・例外ハンドラ vectors.pl→vectors.S vectorsはvector0..vector255を指すポインタが入っている テーブルで、vectorNはalltrapsを呼んでいる trapasm.S 全レジスタpush
pushl %esp call trap 全レジスタpop iret (割り込みからの復帰) trap.c:trap() trapasm.Sから引数として渡されたスタックポインタを構 造体として参照 trapnoがシステムコールの場合・タイマ/IDE/キーボー ド/シリアル割り込みの場合についてそれぞれのハンド ル関数をコールしている -
CPU内部の割り込みの話おわり 実際には、割り込みはCPUの外から やってくる これを受け取ってどうCPUへ割り込み をかけるかを司る、仲介役を果たす「割 り込みコントローラ」が必要 割り込みコントローラのずっと向こう側
に、実際に割り込みを送っているデバイ スが居る さぁ、CPUの向こう側の話をしよう -
Advanced Programmable Interrupt Controller (APIC) オリジナルのx86アーキテクチャでは割 り込みコントローラとしてPIC(8259)を 使っていたが、P6以降のx86アーキテク チャではAPICへ移行(PICも未だ存在し
ていて使える) CPU毎に存在しCPUに内蔵されている Local APICと、ICH(Southbridge)に 内蔵されているI/O APICから構成されて いる -
Local APICとI/O APIC Local APIC ローカル割り込みのベクタ番号設定、割 り込みベクタ番号通知、EOIなど一般的 な割り込みコントローラの役割
I/O APIC どの外部割り込みをどのLocal APICに振 るか等を決める役割 -
Local APICとI/O APIC CPU Local APIC CPU Local APIC CPU
Local APIC ICH(South bridge) IOAPIC External Interrupts 8259A PIC LINT0 LINT1 NMI IPI Timer -
APIC ID Local APIC ID Registerから取得可 APIC IDでプロセッサを一意に特定
このIDでI/O APICから割り込み先CPUを 指定 -
Local Vector Table ローカル割り込みのベクタ番号を設定 CMCI(Corrected Machine Check Interrupt)
Timer Thermal Monitor Performance Counter LINT0/1 レガシーデバイスとか Error 外部割り込みはここで設定しない -
割り込みの受信 IRR: Interrupt Request Register CPUが未処理の割り込みベクタ番号にビッ トが立っている ISR:
In Service Register 次に割り込む候補 EOIへ書き込まれた時にIRR→ISRへビット が更新される EOI: End Of Interrupt Register 割り込みハンドラ終了通知として0を書き 込む(例外有り) -
Redirection Table 各IRQの宛先APIC ID, Vectorなどを設定 Destination 宛先APIC ID
Mask 割り込みマスク Trigger Mode Edge/Level Remote IRR Interrupt Input Pin Polarity Delivery Status Idle/Pending Destination Mode Physical/Logical Delivery Mode Fixed/Lowest… Vector Vector no of interrupt -
Destination Mode Physical Destination Mode LAPIC上のLocal APIC ID
Registerの値を指 定する事によりCPUを一意に特定 Logical Destination Mode LAPIC上のLogical Destination Registerと Destination Format Registerの値とAddress されたIDがマッチするかどうかで判別 -
Logical Destination Mode Destination Format Registerでモード選択 flat model
各LAPIC毎にLDRへ異なるbitを立て、宛先アド レスには複数のbitを立てる事で複数のCPUのを 選択可能 アドレスが8bitしか無いので対応CPU数は8まで cluster model LDRと宛先アドレスを4bitで分割、双方cluster IDとlogical IDを持つ 使い方がよくわからない…8より多いCPUをサ ポートする為の階層化? -
Delivery Mode Fixed Destinationに指定された全てのCPUへ 割り込み Lowest priority DestinationのうちLAPICのTask
Priority Registerの値が最も小さいCPUへ割り込 み →TPRを制御する事で動的に割り込み先 を変更可能 -
xv6のLAPIC周りを見てみる main.c:main() lapicinit(); LAPICを初期化 lapic.c:lapicinit() LAPIC有効化
タイマー初期化 LINT0/LINT1、パフォーマンスカウンタ割り 込み無効化 エラー割り込みのベクタ番号設定 エラーステータスレジスタクリア 割り込みクリア -
xv6のI/O APIC周り main.c:main() ioapicinit(); ideinit(); ioapic.c:ioapicinit()
全ての割り込みを無効に ide.c:ideinit() ioapicenable(IRQ_IDE, ncpu – 1); IRQ_IDEをAPIC ID=ncpu -1へ送るよう設定 質問:Delivery ModeとDestination Modeは 何? -
PIC(8259) IOAPICと同様ICHに存在 IOAPIC(又はcpu0のLocal APIC)へ接続 されている 「古い割り込みコントローラ」のように紹 介したが、レガシデバイスが接続されてい るのでそのようなデバイスを使う場合は
PICを使う必要がある xv6ではレガシデバイスを使う為、 PIC→IOAPICの順で割り込みの設定を行 なっている ideinit(),consoleinit(),uartinit()で呼んでいる ioapicenable()の手前にあるpicenable() -
レガシデバイス 以下の様なデバイス PS/2 キーボード/マウス IDE COM0, COM1
Floppy etc… -
MSI: Message Signal Interrupt MSI-X: MSI Extended Interrupt 物理的な割り込み線を用いず、(多分、
PCIの?)メッセージング機構により割 り込みを通知する仕組み PCI Expressからサポート必須 IO APICを経由しない(!) →割り込み先どうやって決めんの? PCI Configuration Spaceに設定 -
x2apic 拡張されたAPIC 何が拡張されたか? 色々あるはずだが、少なくともLocal APIC IDやDestinationのフィールド長が拡張され ている
より沢山のCPUをサポート出来るように なった