Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Interrupts on xv6

Takuya ASADA
September 02, 2012

Interrupts on xv6

Takuya ASADA

September 02, 2012
Tweet

More Decks by Takuya ASADA

Other Decks in Technology

Transcript

  1. @syuu1228

    View Slide

  2. 資料
    ž  Software Developers Manual
    http://download.intel.com/products/
    processor/manual/325462.pdf
    ž  ICH10 Datasheet
    http://www.intel.com/assets/pdf/
    datasheet/319973.pdf

    View Slide

  3. おさらい
    ž  このあたりは「はじめて読む486」を読
    んでれば分かってるはず
    ž  わかってない人がこの場にいるとも思え
    ないんだけれども…

    View Slide

  4. 割り込みとは
    ž  現在CPU上で実行しているプログラムを停止
    して別の処理を実行する為にCPUが持つ機能
    —  UNIX上のアプリケーションにおける「シグナル」に
    近い概念
    ž  二種類ある
    —  ハードウェア割り込み
    ○  ハードウェアからCPUへ「キーボード押されたよ」な
    どのメッセージを通知するのに使う
    ○  単に「割り込み」と呼ばれる事もある
    —  ソフトウェア割り込み
    ○  ソフトウェアから割り込みを起こせる
    ○  モード切替に利用される→システムコールに使う

    View Slide

  5. ハードウェア割り込みの例
    ž  ATAコントローラ
    —  HDDへのread/writeリクエストの完了通知
    ž  シリアルポート・NIC
    —  受信通知
    —  送信完了通知
    ž  タイマー
    —  一定期間毎に割り込み
    —  指定期間後に割り込み

    View Slide

  6. ATA受信割り込みの例
    1.  ユーザプログラムがファイルに対して
    writeシステムコールを実行
    2.  ファイルシステムがバッファキャッシュ
    へ書き込み(ダーティフラグON)
    3.  バッファキャッシュがHDDへライトバッ

    4.  ATAドライバがATAコントローラへ書き込
    み要求を送信
    5.  書き込みが終了したらバッファキャッ
    シュのダーティフラグをクリア

    View Slide

  7. 書き込みが終了したら?
    割り込みを使わない場合
    ž  ATAコントローラのステータスレジスタを確認
    し続ければ完了したかどうか分かる
    send_write_request(buffer);
    while(read_ata_status() &
    ATA_STATUS_BUSY)
    ;
    buffer.is_dirty = 0;
    ž  busy waitになってしまう→CPUの無駄

    View Slide

  8. 書き込みが終了したら?
    割り込みを使う場合
    ž  送信完了時の処理は、割り込み着信時に実行すれ
    ばいい
    書き込み処理:
    send_write_request(buffer);
    sleep(buffer);
    割り込みハンドラ:
    buffer = find_buffer(ata_reg);
    buffer.is_dirty = 0;
    wakeup(buffer);
    ž  busy waitしていない分のCPU時間を別の処
    理(別のプロセスを実行など)にまわせる
    ž  sleep()/wakeup()で待ち合わせ

    View Slide

  9. 割り込みハンドラ
    ž  割り込みを受けた時にCPUが実行するプロ
    グラム(関数呼び出しを伴わない関数のよ
    うなもの)
    ž  割り込みハンドラ実行時にCPUがレジスタ
    の状態をスタックへ退避
    ž  ハードウェア割り込みの場合は、デバイス
    のレジスタを読んで割り込みの処理に応じ
    た最小限の処理を実行
    ž  割り込みハンドラから終了用の命令を実行
    して、スタックから割り込み前の状態へ復

    View Slide

  10. プリエンプティブマルチタスクと割
    り込み
    ž  プリエンプティブマルチタスク:
    カーネルがプロセスへのCPUの割り当
    て時間を管理、タイマーを使ってアプリ
    ケーションを一定時間毎に切り替え
    ž  プロセスが無限ループなどに陥りカーネ
    ルへ制御を渡さない場合でもタイマー割
    り込みにより中断され、割り当て時間を
    使い切ったら他のプロセスへ切り替えら
    れる
    ž  割り込みがないと実現出来ない

    View Slide

  11. 例外
    ž  割り込みとは別の概念だが、実装上の共
    通点は多いためx86では共通の仕組みで
    取り扱われている
    —  アプリケーション上の例外とほぼ意味は同
    じだが、CPU上の機能
    ž  例外の例:
    ゼロ除算、無効な命令、ページフォール
    ト、一般保護例外、ブレークポイント

    View Slide

  12. 割り込み/例外ベクタ
    ž  0-255のベクタ番号が割り込みと例外に
    割り当てられる
    —  例外は要因毎に0-19の固定された値
    —  ソフト割り込みは0-255へ割り込み可
    —  ハードウェア割り込みはLAPIC経由の場合
    16-255へ割り込み可
    ž  OSはIDT(Interrupt Descriptor Table)
    を作成し、CPUへアドレスを設定

    View Slide

  13. IDT(Interrupt Descriptor Table)と
    IDTR
    ž  各ベクタの割り込みハンドラの情報を持
    つGate Descriptorが並んでいるメモリ上
    のテーブル
    ž  テーブルの先頭アドレスとLimit値
    (テーブルのサイズ、255未満のGate数
    に対応)をCPUのIDTRに書き込む事に
    より設定(IDTRを設定しない限り、
    CPUは割り込み時に何をしたらいいか
    分からない)

    View Slide

  14. Gate Descriptor
    ž  前述の「割込みハンドラ」のアドレスを持つ
    構造体
    ž  単なる関数へのポインタではなくて、セグメ
    ントの設定とか権限(Ring)とか16 bit/32 bit
    のモード選択とか、幾つかのパラメータを含

    ž  Task gate, Interrupt gate, Trap gateの三種類あ

    —  Task gateはHWのマルチタスク機能でハンドリング
    する方法で今は使われていない
    —  Interrupt gateとTrap gateは普通に割り込みハンドラ
    へジャンプする方法
    EFLAGS.IFフラグをクリアするか否かが違い

    View Slide

  15. 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

    View Slide

  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のアド
    レスを設定

    View Slide

  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/キーボー
    ド/シリアル割り込みの場合についてそれぞれのハンド
    ル関数をコールしている

    View Slide

  18. CPU内部の割り込みの話おわり
    ž  実際には、割り込みはCPUの外から
    やってくる
    ž  これを受け取ってどうCPUへ割り込み
    をかけるかを司る、仲介役を果たす「割
    り込みコントローラ」が必要
    ž  割り込みコントローラのずっと向こう側
    に、実際に割り込みを送っているデバイ
    スが居る
    ž  さぁ、CPUの向こう側の話をしよう

    View Slide

  19. Advanced Programmable
    Interrupt Controller (APIC)
    ž  オリジナルのx86アーキテクチャでは割
    り込みコントローラとしてPIC(8259)を
    使っていたが、P6以降のx86アーキテク
    チャではAPICへ移行(PICも未だ存在し
    ていて使える)
    ž  CPU毎に存在しCPUに内蔵されている
    Local APICと、ICH(Southbridge)に
    内蔵されているI/O APICから構成されて
    いる

    View Slide

  20. Local APICとI/O APIC
    ž  Local APIC
    ローカル割り込みのベクタ番号設定、割
    り込みベクタ番号通知、EOIなど一般的
    な割り込みコントローラの役割
    ž  I/O APIC
    どの外部割り込みをどのLocal APICに振
    るか等を決める役割

    View Slide

  21. 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

    View Slide

  22. Local APIC内のコンポーネント
    なにやら割り込みコントローラ以外にも幾
    つか機能が乗っている
    ž  タイマー
    カーネルのtickに使うことが多い
    ž  温度センサ
    ž  パフォーマンスモニタリングカウンタ

    View Slide

  23. APIC ID
    ž  Local APIC ID Registerから取得可
    ž  APIC IDでプロセッサを一意に特定
    ž  このIDでI/O APICから割り込み先CPUを
    指定

    View Slide

  24. Local Vector Table
    ž  ローカル割り込みのベクタ番号を設定
    —  CMCI(Corrected Machine Check Interrupt)
    —  Timer
    —  Thermal Monitor
    —  Performance Counter
    —  LINT0/1 レガシーデバイスとか
    —  Error
    ž  外部割り込みはここで設定しない

    View Slide

  25. 割り込みの受信
    ž  IRR: Interrupt Request Register
    CPUが未処理の割り込みベクタ番号にビッ
    トが立っている
    ž  ISR: In Service Register
    次に割り込む候補
    EOIへ書き込まれた時にIRR→ISRへビット
    が更新される
    ž  EOI: End Of Interrupt Register
    割り込みハンドラ終了通知として0を書き
    込む(例外有り)

    View Slide

  26. I/O APIC (ICH10の場合)
    ž  24本の割り込みをサポート
    ž  Redirection Tableで割り込み先Local
    APICを決定(24エントリのテーブル)

    View Slide

  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

    View Slide

  28. Destination Mode
    ž  Physical Destination Mode
    —  LAPIC上のLocal APIC ID Registerの値を指
    定する事によりCPUを一意に特定
    ž  Logical Destination Mode
    —  LAPIC上のLogical Destination Registerと
    Destination Format Registerの値とAddress
    されたIDがマッチするかどうかで判別

    View Slide

  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をサ
    ポートする為の階層化?

    View Slide

  30. Delivery Mode
    ž  Fixed
    Destinationに指定された全てのCPUへ
    割り込み
    ž  Lowest priority
    DestinationのうちLAPICのTask Priority
    Registerの値が最も小さいCPUへ割り込

    →TPRを制御する事で動的に割り込み先
    を変更可能

    View Slide

  31. xv6のLAPIC周りを見てみる
    ž  main.c:main()
    —  lapicinit(); LAPICを初期化
    ž  lapic.c:lapicinit()
    —  LAPIC有効化
    —  タイマー初期化
    —  LINT0/LINT1、パフォーマンスカウンタ割り
    込み無効化
    —  エラー割り込みのベクタ番号設定
    —  エラーステータスレジスタクリア
    —  割り込みクリア

    View Slide

  32. 割り込みハンドラ周りのLAPIC
    ž  trap.c:trap()
    —  lapiceoi(); EOIレジスタへ0書き込み
    ž  lapic.c:lapiceoi()

    View Slide

  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は
    何?

    View Slide

  34. xv6のI/O APIC周り
    ž  console.c:consoleinit()
    ioapicenable(IRQ_KBD, 0)
    ž  uart.c:uartinit()
    ioapicenable(IRQ_COM1, 0)

    View Slide

  35. PIC(8259)
    ž  IOAPICと同様ICHに存在
    IOAPIC(又はcpu0のLocal APIC)へ接続
    されている
    ž  「古い割り込みコントローラ」のように紹
    介したが、レガシデバイスが接続されてい
    るのでそのようなデバイスを使う場合は
    PICを使う必要がある
    ž  xv6ではレガシデバイスを使う為、
    PIC→IOAPICの順で割り込みの設定を行
    なっている
    —  ideinit(),consoleinit(),uartinit()で呼んでいる
    ioapicenable()の手前にあるpicenable()

    View Slide

  36. レガシデバイス
    ž  以下の様なデバイス
    —  PS/2 キーボード/マウス
    —  IDE
    —  COM0, COM1
    —  Floppy
    —  etc…

    View Slide

  37. MSI: Message Signal Interrupt
    MSI-X: MSI Extended Interrupt
    ž  物理的な割り込み線を用いず、(多分、
    PCIの?)メッセージング機構により割
    り込みを通知する仕組み
    ž  PCI Expressからサポート必須
    ž  IO APICを経由しない(!)
    ž  →割り込み先どうやって決めんの?
    —  PCI Configuration Spaceに設定

    View Slide

  38. MSIの割り込み設定
    ž  詳細はここをみてね
    ž  IOAPICと同じく、Logical/Physicalの
    Destination Mode、Fixed/Lowestなどの
    Delivery modeが存在

    View Slide

  39. x2apic
    ž  拡張されたAPIC
    ž  何が拡張されたか?
    —  色々あるはずだが、少なくともLocal APIC
    IDやDestinationのフィールド長が拡張され
    ている
    —  より沢山のCPUをサポート出来るように
    なった

    View Slide