Upload
takuya-asada
View
1.683
Download
2
Embed Size (px)
DESCRIPTION
カーネル/VM勉強会 第二回 OS基礎(xv6)
Citation preview
INTERRUPTS ON XV6
@syuu1228
資料 Software Developers Manual
http://download.intel.com/products/processor/manual/325462.pdf
ICH10 Datasheethttp://www.intel.com/assets/pdf/datasheet/319973.pdf
おさらい このあたりは「はじめて読む 486」を読んでれば分かってるはず
わかってない人がこの場にいるとも思えないんだけれども…
割り込みとは 現在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の関係
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
Local APIC内のコンポーネントなにやら割り込みコントローラ以外にも幾つか機能が乗っている タイマーカーネルの tickに使うことが多い
温度センサ パフォーマンスモニタリングカウンタ
APIC ID
Local APIC ID Registerから取得可 APIC IDでプロセッサを一意に特定 この IDで I/O APICから割り込み先
CPUを指定
Local Vector Table
ローカル割り込みのベクタ番号を設定CMCI(Corrected Machine Check Interrupt)TimerThermal MonitorPerformance CounterLINT0/1 レガシーデバイスとかError
外部割り込みはここで設定しない
割り込みの受信 IRR: Interrupt Request Register
CPUが未処理の割り込みベクタ番号にビットが立っている
ISR: In Service Register次に割り込む候補EOIへ書き込まれた時に IRR→ISRへビットが更新される
EOI: End Of Interrupt Register割り込みハンドラ終了通知として 0を書き込む(例外有り)
I/O APIC (ICH10の場合 )
24本の割り込みをサポート Redirection Tableで割り込み先 Local
APICを決定( 24エントリのテーブル)
Redirection Table
各 IRQの宛先 APIC ID, Vectorなどを設定Destination 宛先 APIC IDMask 割り込みマスクTrigger Mode Edge/LevelRemote IRRInterrupt Input Pin PolarityDelivery Status Idle/PendingDestination Mode Physical/LogicalDelivery Mode Fixed/Lowest…Vector Vector no of interrupt
Destination Mode
Physical Destination ModeLAPIC上の Local APIC ID Registerの値を指定する事により CPUを一意に特定
Logical Destination ModeLAPIC上の 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
FixedDestinationに指定された全ての CPUへ割り込み
Lowest priorityDestinationのうち LAPICの Task Priority Registerの値が最も小さい CPUへ割り込み→ TPRを制御する事で動的に割り込み先を変更可能
xv6の LAPIC周りを見てみる main.c:main()
lapicinit(); LAPICを初期化 lapic.c:lapicinit()
LAPIC有効化タイマー初期化LINT0/LINT1、パフォーマンスカウンタ割り込み無効化
エラー割り込みのベクタ番号設定エラーステータスレジスタクリア割り込みクリア
割り込みハンドラ周りのLAPIC trap.c:trap()
lapiceoi(); EOIレジスタへ 0書き込み lapic.c:lapiceoi()
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は何?
xv6の I/O APIC周り console.c:consoleinit()
ioapicenable(IRQ_KBD, 0) uart.c:uartinit()
ioapicenable(IRQ_COM1, 0)
PIC(8259) IOAPICと同様 ICHに存在
IOAPIC(又は cpu0の Local APIC)へ接続されている
「古い割り込みコントローラ」のように紹介したが、レガシデバイスが接続されているのでそのようなデバイスを使う場合は PICを使う必要がある
xv6ではレガシデバイスを使う為、PIC→IOAPICの順で割り込みの設定を行なっているideinit(),consoleinit(),uartinit()で呼んでいる
ioapicenable()の手前にある picenable()
レガシデバイス 以下の様なデバイス
PS/2 キーボード/マウスIDECOM0, COM1Floppyetc…
MSI: Message Signal InterruptMSI-X: MSI Extended Interrupt
物理的な割り込み線を用いず、(多分、PCIの?)メッセージング機構により割り込みを通知する仕組み
PCI Expressからサポート必須 IO APICを経由しない(!) →割り込み先どうやって決めんの?
PCI Configuration Spaceに設定
MSIの割り込み設定 詳細はここをみてね IOAPICと同じく、 Logical/Physicalの
Destination Mode、 Fixed/Lowestなどの Delivery modeが存在
x2apic
拡張された APIC 何が拡張されたか?
色々あるはずだが、少なくとも Local APIC IDや Destinationのフィールド長が拡張されている
より沢山の CPUをサポート出来るようになった