Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Interrupts on xv6
Search
Takuya ASADA
September 02, 2012
Technology
0
160
Interrupts on xv6
Takuya ASADA
September 02, 2012
Tweet
Share
More Decks by Takuya ASADA
See All by Takuya ASADA
Interrupt Affinityについて
syuu1228
0
290
僕のIntel NUCが起動しないわけがない
syuu1228
3
4.4k
Introduction to bhyve
syuu1228
1
410
OSv on bhyve
syuu1228
3
420
ruby-virtualmachine
syuu1228
0
270
BHyVeでOSvを起動したい 〜BIOSがなくてもこの先生きのこるには〜
syuu1228
2
850
10GbE時代のネットワークI/O高速化
syuu1228
14
8.7k
Play with UEFI
syuu1228
1
350
仮想化環境での利用者公平性
syuu1228
0
180
Other Decks in Technology
See All in Technology
abema-trace-sampling-observability-cost-optimization
tetsuya28
0
400
GPUをつかってベクトル検索を扱う手法のお話し~NVIDIA cuVSとCAGRA~
fshuhe
0
310
文字列操作の達人になる ~ Kotlinの文字列の便利な世界 ~ - Kotlin fest 2025
tomorrowkey
2
300
マルチエージェントのチームビルディング_2025-10-25
shinoyamada
0
230
InsightX 会社説明資料/ Company deck
insightx
0
150
個人でデジタル庁の デザインシステムをVue.jsで 作っている話
nishiharatsubasa
3
5.3k
AI連携の新常識! 話題のMCPをはじめて学ぶ!
makoakiba
0
170
SOTA競争から人間を超える画像認識へ
shinya7y
0
650
20251102 WordCamp Kansai 2025
chiilog
0
310
Open Table Format (OTF) が必要になった背景とその機能 (2025.10.28)
simosako
3
570
20251027_マルチエージェントとは
almondo_event
1
500
激動の時代を爆速リチーミングで乗り越えろ
sansantech
PRO
1
210
Featured
See All Featured
The World Runs on Bad Software
bkeepers
PRO
72
11k
What's in a price? How to price your products and services
michaelherold
246
12k
Writing Fast Ruby
sferik
630
62k
The Power of CSS Pseudo Elements
geoffreycrofte
80
6k
Testing 201, or: Great Expectations
jmmastey
46
7.7k
Dealing with People You Can't Stand - Big Design 2015
cassininazir
367
27k
Faster Mobile Websites
deanohume
310
31k
Context Engineering - Making Every Token Count
addyosmani
8
320
Building a Modern Day E-commerce SEO Strategy
aleyda
44
7.9k
Refactoring Trust on Your Teams (GOTO; Chicago 2020)
rmw
35
3.2k
Raft: Consensus for Rubyists
vanstee
140
7.2k
The Web Performance Landscape in 2024 [PerfNow 2024]
tammyeverts
10
900
Transcript
@syuu1228
資料  Software Developers Manual http://download.intel.com/products/ processor/manual/325462.pdf  ICH10 Datasheet
http://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の関係 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
Local APIC内のコンポーネント なにやら割り込みコントローラ以外にも幾 つか機能が乗っている  タイマー カーネルのtickに使うことが多い  温度センサ 
パフォーマンスモニタリングカウンタ
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を書き 込む(例外有り)
I/O APIC (ICH10の場合)  24本の割り込みをサポート  Redirection Tableで割り込み先Local APICを決定(24エントリのテーブル)
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、パフォーマンスカウンタ割り 込み無効化  エラー割り込みのベクタ番号設定  エラーステータスレジスタクリア  割り込みクリア
割り込みハンドラ周りの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 キーボード/マウス  IDE  COM0, COM1
 Floppy  etc…
MSI: Message Signal Interrupt MSI-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をサポート出来るように なった