More Related Content
Similar to Interrupts on xv6 (20)
More from Takuya ASADA (20)
Interrupts on xv6
- 2. 資料
Software Developers Manual
http://download.intel.com/products/proce
ssor/manual/325462.pdf
ICH10 Datasheet
http://www.intel.com/assets/pdf/datashe
et/319973.pdf
- 4. 割り込みとは
現在CPU上で実行しているプログラムを停止
して別の処理を実行する為にCPUが持つ機能
UNIX上のアプリケーションにおける「シグナル」に
近い概念
二種類ある
ハードウェア割り込み
○ ハードウェアからCPUへ「キーボード押されたよ」な
どのメッセージを通知するのに使う
○ 単に「割り込み」と呼ばれる事もある
ソフトウェア割り込み
○ ソフトウェアから割り込みを起こせる
○ モード切替に利用される→システムコールに使う
- 5. ハードウェア割り込みの例
ATAコントローラ
HDDへのread/writeリクエストの完了通知
シリアルポート・NIC
受信通知
送信完了通知
タイマー
一定期間毎に割り込み
指定期間後に割り込み
- 6. ATA受信割り込みの例
1. ユーザプログラムがファイルに対して
writeシステムコールを実行
2. ファイルシステムがバッファキャッシュ
へ書き込み(ダーティフラグON)
3. バッファキャッシュがHDDへライトバッ
ク
4. ATAドライバがATAコントローラへ書き込
み要求を送信
5. 書き込みが終了したらバッファキャッ
シュのダーティフラグをクリア
- 7. 書き込みが終了したら?
割り込みを使わない場合
ATAコントローラのステータスレジスタを確
認し続ければ完了したかどうか分かる
send_write_request(buffer);
while(read_ata_status() &
ATA_STATUS_BUSY)
;
buffer.is_dirty = 0;
busy waitになってしまう→CPUの無駄
- 8. 書き込みが終了したら?
割り込みを使う場合
送信完了時の処理は、割り込み着信時に実行すれ
ばいい
書き込み処理:
send_write_request(buffer);
sleep(buffer);
割り込みハンドラ:
buffer = find_buffer(ata_reg);
buffer.is_dirty = 0;
wakeup(buffer);
busy waitしていない分のCPU時間を別の処
理(別のプロセスを実行など)にまわせる
sleep()/wakeup()で待ち合わせ
- 9. 割り込みハンドラ
割り込みを受けた時にCPUが実行するプロ
グラム(関数呼び出しを伴わない関数のよ
うなもの)
割り込みハンドラ実行時にCPUがレジスタ
の状態をスタックへ退避
ハードウェア割り込みの場合は、デバイス
のレジスタを読んで割り込みの処理に応じ
た最小限の処理を実行
割り込みハンドラから終了用の命令を実行
して、スタックから割り込み前の状態へ復
帰
- 10. プリエンプティブマルチタスク
と割り込み
プリエンプティブマルチタスク:
カーネルがプロセスへのCPUの割り当
て時間を管理、タイマーを使ってアプリ
ケーションを一定時間毎に切り替え
プロセスが無限ループなどに陥りカーネ
ルへ制御を渡さない場合でもタイマー割
り込みにより中断され、割り当て時間を
使い切ったら他のプロセスへ切り替えら
れる
割り込みがないと実現出来ない
- 11. 例外
割り込みとは別の概念だが、実装上の共
通点は多いためx86では共通の仕組みで
取り扱われている
アプリケーション上の例外とほぼ意味は同
じだが、CPU上の機能
例外の例:
ゼロ除算、無効な命令、ページフォール
ト、一般保護例外、ブレークポイント
- 12. 割り込み/例外ベクタ
0-255のベクタ番号が割り込みと例外に
割り当てられる
例外は要因毎に0-19の固定された値
ソフト割り込みは0-255へ割り込み可
ハードウェア割り込みはLAPIC経由の場合
16-255へ割り込み可
OSはIDT(Interrupt Descriptor Table)
を作成し、CPUへアドレスを設定
- 14. Gate Descriptor
前述の「割込みハンドラ」のアドレスを持つ
構造体
単なる関数へのポインタではなくて、セグメ
ントの設定とか権限(Ring)とか16 bit/32 bit
のモード選択とか、幾つかのパラメータを含
む
Task gate, Interrupt gate, Trap gateの三種類あ
る
Task gateはHWのマルチタスク機能でハンドリング
する方法で今は使われていない
Interrupt gateとTrap gateは普通に割り込みハンドラ
へジャンプする方法
EFLAGS.IFフラグをクリアするか否かが違い
- 15. IDT,IDTR,Gate descriptorの関
係
IDTR register
47 16 15 0
Base address Limit
IDT
Gate for interrupt 255
…
Gate for interrupt 3
Gate for interrupt 2
Gate for interrupt 1 Interrupt Gate
DPL rese segment
Gate for interrupt 0 offset 31..16 offset 15..0
/P rved selector
- 16. 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のアド
レスを設定
- 17. 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/キーボー
ド/シリアル割り込みの場合についてそれぞれのハンド
ル関数をコールしている
- 19. Advanced Programmable
Interrupt Controller (APIC)
オリジナルのx86アーキテクチャでは割
り込みコントローラとしてPIC(8259)を
使っていたが、P6以降のx86アーキテク
チャではAPICへ移行(PICも未だ存在し
ていて使える)
CPU毎に存在しCPUに内蔵されている
Local APICと、ICH(Southbridge)に
内蔵されているI/O APICから構成されて
いる
- 20. Local APICとI/O APIC
Local APIC
ローカル割り込みのベクタ番号設定、割
り込みベクタ番号通知、EOIなど一般的
な割り込みコントローラの役割
I/O APIC
どの外部割り込みをどのLocal APICに振
るか等を決める役割
- 21. Local APICとI/O APIC
8259A PIC
CPU CPU CPU
LINT0 IPI
Local APIC Local APIC
Timer
LINT1 Local APIC
NMI
IOAPIC External Interrupts
ICH(South bridge)
- 23. APIC ID
Local APIC ID Registerから取得可
APIC IDでプロセッサを一意に特定
このIDでI/O APICから割り込み先CPUを
指定
- 24. Local Vector Table
ローカル割り込みのベクタ番号を設定
CMCI(Corrected Machine Check Interrupt)
Timer
Thermal Monitor
Performance Counter
LINT0/1 レガシーデバイスとか
Error
外部割り込みはここで設定しない
- 25. 割り込みの受信
IRR: Interrupt Request Register
CPUが未処理の割り込みベクタ番号にビッ
トが立っている
ISR: In Service Register
次に割り込む候補
EOIへ書き込まれた時にIRR→ISRへビット
が更新される
EOI: End Of Interrupt Register
割り込みハンドラ終了通知として0を書き
込む(例外有り)
- 27. 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
- 28. Destination Mode
Physical Destination Mode
LAPIC上のLocal APIC ID Registerの値を指
定する事によりCPUを一意に特定
Logical Destination Mode
LAPIC上のLogical Destination Registerと
Destination Format Registerの値とAddress
されたIDがマッチするかどうかで判別
- 29. 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をサ
ポートする為の階層化?
- 30. Delivery Mode
Fixed
Destinationに指定された全てのCPUへ
割り込み
Lowest priority
DestinationのうちLAPICのTask Priority
Registerの値が最も小さいCPUへ割り込
み
→TPRを制御する事で動的に割り込み先
を変更可能
- 31. xv6のLAPIC周りを見てみる
main.c:main()
lapicinit(); LAPICを初期化
lapic.c:lapicinit()
LAPIC有効化
タイマー初期化
LINT0/LINT1、パフォーマンスカウンタ割り
込み無効化
エラー割り込みのベクタ番号設定
エラーステータスレジスタクリア
割り込みクリア
- 33. 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は
何?
- 35. PIC(8259)
IOAPICと同様ICHに存在
IOAPIC(又はcpu0のLocal APIC)へ接続
されている
「古い割り込みコントローラ」のように紹
介したが、レガシデバイスが接続されてい
るのでそのようなデバイスを使う場合は
PICを使う必要がある
xv6ではレガシデバイスを使う為、
PIC→IOAPICの順で割り込みの設定を行
なっている
ideinit(),consoleinit(),uartinit()で呼んでいる
ioapicenable()の手前にあるpicenable()
- 36. レガシデバイス
以下の様なデバイス
PS/2 キーボード/マウス
IDE
COM0, COM1
Floppy
etc…
- 37. MSI: Message Signal Interrupt
MSI-X: MSI Extended Interrupt
物理的な割り込み線を用いず、(多分、
PCIの?)メッセージング機構により割
り込みを通知する仕組み
PCI Expressからサポート必須
IO APICを経由しない(!)
→割り込み先どうやって決めんの?
PCI Configuration Spaceに設定