osdev-jpでは、OS開発に有用な情報を収集し公開しています
PCI には MSI = Message Signaled Interrupt という割り込み機能がある. システムバスに対して,メモリ・ライト・サイクルを発行することでシステムに対し割り込みを行う機能である.
MSI(および拡張規格の MSI-X)をサポートする PCI デバイスには,メモリ書き込みを行うアドレスとデータを指定するレジスタがある. それぞれ Message Address,Message Data という名前である. 両者のレジスタの具体的な内容は PCI 規格では決まっておらず,CPU の種類により異なっている.
x86 ベースのシステムにおけるレジスタの定義は Intel SDM Vol.3 “10.11 MESSAGE SIGNALED INTERRUPTS” に載っている.
Message Address は次の通り.
31 20 19 12 11 4 3 2 1
| 0xfee | Dest ID | Resvd | RH | DM | XX |
Dest ID(Destination ID)は割り込みの配送先の ID を設定する. RH と DM の設定によって意味が変わるが,RH = 1,DM = 0 の場合は配送先の CPU コアの Local APIC ID である.
Local APIC ID はマルチコアシステムにおいて,CPU コアを識別するための ID. CPU の物理アドレス 0xfee00020 にマップされている Local APIC ID レジスタからその CPU コアの Local APIC ID を読み取ることができる. BSP(Boot Strap Processor)だと 0 になる,かもしれない.
const uint8_t local_apic_id = *reinterpret_cast<const uint32_t*>(0xfee00020) >> 24;
このプログラムを実行した CPU コアの ID を取得することができるはず(マルチコアを有効にして実験したことが無いので確信は無い).
Message Data は次の通り.
31 16 15 14 13 11 10 8 7 0
| Resvd | TM | LV | Resvd | Deliv | Vector |
Deliv は Delivery Mode のこと.0 にすると,Message Address の Destination ID で指定されたすべての配送先に配送される. その他は,最低優先度の CPU に送信するモードや NMI 割り込みとして割り込みをかけるモードなどがあるが,筆者は使ったことがない.
Vector は割り込みベクタ番号.設定してよい値は 16 から 254.
x86 システムの割り込み記述子テーブル IDT は 256 個の割り込みベクタをサポートする. Intel SDM Vol.3 “Table 6-1. Protected-Mode Exceptions and Interrupts” によればベクタ番号の使用用途は次の通り.
ベクタ番号 | 用途 |
---|---|
0 - 20 | CPU 例外(一般保護例外やページフォルトなど) |
21 - 31 | Intel により予約済み |
32 - 255 | ユーザ定義割り込み |
Message Data の Vector には割り込みベクタ番号 16 - 254 を設定できる. ただ,上の表を見る限り 16 - 31 も避けた方が良いので,実際には 33 - 254 の範囲で設定することになる.
MSI では複数の割り込みベクタを扱うことができる. 割り込みベクタ数は Message Control レジスタの Multiple Message Enable フィールドで指定できる.
割り込み送出時,Multiple Message Enable フィールドで設定したベクタ数に応じて, Message Data の Vector の下位数ビットが変更されて Message Address で指定したアドレスに書き込まれる.
MME の値 | 割り当てられるベクタ数 | 割り込みベクタ範囲 |
---|---|---|
000 | 1 | Vector |
001 | 2 | Vector - Vector+1 |
010 | 4 | Vector - Vector+3 |
011 | 8 | Vector - Vector+7 |
100 | 16 | Vector - Vector+15 |
101 | 32 | Vector - Vector+31 |
110, 111 | Reserved | - |
※MME = Multiple Message Enable
例えば Vector = 0x40,MME = 010 のとき,割り込み送出時の Vector フィールドは次のようになる.
bit 7 0
Vector 010000xx
割り込み要因に応じて,割り込みベクタ 0x40,0x41,0x42,0x43 のいずれかに割り込みがかかる.