Interrupt Affinity

について
@syuu1228
Interrupt Affinity?
今時の普通のPCはマルチコアである
デバイス1:IRQ1:CPUいっぱい

という関係になっている
デバイスはどこに割り込んでいるの?

LinuxはどのCPUに割り込ませているの?


→ Interrupt Affinity
Interrupt Affinityの
ユーザインタフェース
$ cat /proc/interrupts
CPU0 CPU1
0: 36843 61973 IO-APIC-edge timer
1: 518 591 IO-APIC-edge i8042
8: 1 0 IO-APIC-edge rtc0
9: 387 321 IO-APIC-fasteoi acpi
12: 11236 79 IO-APIC-edge i8042
16: 0 0 IO-APIC-fasteoi uhci_hcd:usb6
17: 12 11 IO-APIC-fasteoi uhci_hcd:usb7
18: 0 0 IO-APIC-fasteoi uhci_hcd:usb8
19: 6531 235 IO-APIC-fasteoi ehci_hcd:usb2
20: 0 0 IO-APIC-fasteoi uhci_hcd:usb3
21: 85 69 IO-APIC-fasteoi uhci_hcd:usb4
22: 0 0 IO-APIC-fasteoi uhci_hcd:usb5
23: 20 15 IO-APIC-fasteoi ehci_hcd:usb1
40: 0 0 PCI-MSI-edge PCIe PME, pciehp
41: 0 0 PCI-MSI-edge PCIe PME, pciehp
42: 0 0 PCI-MSI-edge PCIe PME, pciehp
43: 33199 31756 PCI-MSI-edge ahci
44: 19 1583 PCI-MSI-edge eth0
45: 10 11 PCI-MSI-edge mei
46: 41104 59303 PCI-MSI-edge i915
47: 170268 708 PCI-MSI-edge iwlwifi
48: 78 77 PCI-MSI-edge snd_hda_intel
NMI: 1406 1430 Non-maskable interrupts
CPU毎の割り込み統計を表示
/proc/interrupts
/proc/irq/*/smp_affinity
割り込み先CPU群をビットで指定する
と、指定されたCPU群にラウンドロビ
ンで割り込まれる(ビットが単一なら
常にそのCPUへ割り込み)
# cat /proc/irq/43/smp_affinity
3
# echo 1 > /proc/irq/43/smp_affinity
これを書き換えると割り込み先CPUが変わる
Linuxでのデフォルト値
全CPUのビットが有効になっており、
1つの割り込みが全CPUへラウンドロ
ビンする
ラウンドロビン割り込みに対応しないPC
ではあるCPUへ固定的に割り込む
(cpu0?)
/proc/irq/*/smp_affinity_list
ヒューマンリーダブルなsmp_affinity
# echo ff > /proc/irq/43/smp_affinity
# cat /proc/irq/43/smp_affinity_list

0-7
/proc/irq/*/smp_affinity_hint
デバイスドライバからユーザランドデー
モン(irqbalance)へこのIRQに適切
なCPU maskを通知
irqbalance
10秒ごとにシステム負荷状況をチェッ
ク、各IRQのsmp_affinityを書き換え
てCPU負荷を公平にするデーモン
oneshotモードでは起動時に適切と思
われる値をsmp_affinityに設定して
exit
MultiQueue NICの割り込み
CPU毎に送受信キュー、キュー毎に
MSI-X割り込みを持つ
正しいsmp_affinityは固定的に決まっ
ている
複数CPUへ散らしてはならない
47: 7602 0 0 0 0 3 23 0 PCI-MSI-edge p1p1-TxRx-0
48: 0 7602 0 0 0 0 13 12 PCI-MSI-edge p1p1-TxRx-1
49: 12 0 7605 0 0 0 10 0 PCI-MSI-edge p1p1-TxRx-2
50: 0 12 0 7602 3 0 10 0 PCI-MSI-edge p1p1-TxRx-3
51: 0 0 12 0 7602 3 10 0 PCI-MSI-edge p1p1-TxRx-4
52: 0 0 0 20 0 7602 13 0 PCI-MSI-edge p1p1-TxRx-5
53: 0 0 0 0 12 0 7612 3 PCI-MSI-edge p1p1-TxRx-6
54: 3 0 0 0 0 13 10 7602 PCI-MSI-edge p1p1-TxRx-7
55: 0 2 0 0 0 0 2 0 PCI-MSI-edge p1p1
ソースコード
/proc/interrupts

fs/proc/interrupts.c
/proc/irq/

kernel/irq/proc.c
irqbalance

https://github.com/irqbalance/
irqbalance
PCアーキテクチャにおける

割り込みルーティング
PC上の割り込みコンポーネント
CPU
Local APIC
CPU
Local APIC
CPU
Local APIC
ICH
8259A PIC
Timer
I/O APIC
Legacy
PCI
Devices
MSI(-X)
Capable
Devices
IPI
Legacy PCI
8259A IntrMSI(-X)
PCI-LPC
bridge
SuperIO
Chip
Local APIC
CPU毎の割り込みコントローラ 割り込みを許可・マスクし
たり、EOIしたり
システム全体で一意なAPIC IDを持つ
他のLAPICへ割り込める(IPI: Inter-processor Interrupt)
CPU
Local APIC
CPU
Local APIC
CPU
Local APIC
ICH
8259A PIC
Timer
I/O APIC
Legacy
PCI
Devices
MSI(-X)
Capable
Devices
IPI
Legacy PCI
8259A IntrMSI(-X)
PCI-LPC
bridge
SuperIO
Chip
LAPIC - Interrupt
Command Register(ICR)
Vector:宛先LAPICのベクタ番号
Delivery Mode:割り込み配送モード
Destination Mode:宛先モード
Deliver Status:前回の割り込みの配送状況
Trigger Mode:レベルトリガ/エッジトリガ
Destination Shorthand:宛先のマスク方式(自CPUをマスク・
アンマスクなど)
Destination ID:宛先
ソースコード
ICR

arch/x86/include/asm/ipi.h
データシート
Intel® 64 and IA-32
Architectures Software
Developer Manuals

10.6.1 Interrupt Command
Register(ICR)
補足:x2APIC
LAPIC IDは従来8bitだったが、コア数の増加によ
りビット数が足りなくなってしまったので32bitへ
ビットを追加
これに伴って、以降で解説する各レジスタでの割り
込み先LAPIC指定フィールドのアドレス幅もビット
追加された
データシート
Intel® 64 Architecture x2APIC Specification

1.3 GLOSSARY
I/O APIC
限られた本数の物理割り込み線を各PCIデバイスで共有

(PCIeには物理割り込み線は無く、メッセージングによってI/O APIC経由割り込みを
エミュレート)
各IRQをどのLAPICへ転送するかを定義するRedirection Table

(I/O APIC上のレジスタ群)を持つ
PCIデバイスはI/O APICを通じてLAPICへ割り込みメッセージを送信
CPU
Local APIC
CPU
Local APIC
CPU
Local APIC
ICH
8259A PIC
Timer
I/O APIC
Legacy
PCI
Devices
MSI(-X)
Capable
Devices
IPI
Legacy PCI
8259A IntrMSI(-X)
PCI-LPC
bridge
SuperIO
Chip
I/O APIC - REDIR_TBL
Vector:宛先LAPICのベクタ番号
Delivery Mode:割り込み配送モード
Destination Mode:宛先モード
Delivery Status:前回の割り込みの配送状況
Interrupt Input Pin Polarity:割り込みピンの極性
Remote IRR:自動的にEOIするかどうか
Trigger Mode:レベルトリガ/エッジトリガ
Mask:割り込みマスク
Destination ID:宛先
ソースコード
REDIR_TBL

arch/x86/kernel/apic/io_apic.c
データシート
Intel® I/O Controller Hub 10
(ICH10) Family Datasheet

13.5.7 REDIR_TBL-Redirection
Table
レガシデバイス
レガシデバイスからの割り込みをPCI-LPC bridgeでPCIへ変換
PCIデバイス同様にI/O APICを通じてLAPICへ割り込みメッセー
ジを送信
互換性のため8259Aにも接続されていると思われる
CPU
Local APIC
CPU
Local APIC
CPU
Local APIC
ICH
8259A PIC
Timer
I/O APIC
Legacy
PCI
Devices
MSI(-X)
Capable
Devices
IPI
Legacy PCI
8259A IntrMSI(-X)
PCI-LPC
bridge
SuperIO
Chip
8259A PIC
省略(まだ残ってますが、もう使わな
いでしょう)
MSI(-X) capable PCI devices
各デバイスが任意の数のIRQを持てる
各IRQの割り込み先LAPICはPCIデバイスのPCI
Configuration Spaceに持つ
PCIデバイスは直接LAPICへ割り込みメッセージを送信
CPU
Local APIC
CPU
Local APIC
CPU
Local APIC
ICH
8259A PIC
Timer
I/O APIC
Legacy
PCI
Devices
MSI(-X)
Capable
Devices
IPI
Legacy PCI
8259A IntrMSI(-X)
PCI-LPC
bridge
SuperIO
Chip
MSI Capability on

PCI configuration space
Device ID Vendor ID
…
Reserved Cap. Pointer
…
Capability x CAP ID(x)Next Pointer
…
Capability y CAP ID(yy)Next Pointer
…
MSICTL CAP ID(D0h)Next Pointer
MSIAR
MSIDR
MSI Capability - MSICTL
省略(MSI有効、64bit、複数割り込
み有効などのフィールド)
MSI Capability - MSIAR
Destination Mode:宛先モード
Redirection Hint:logical mode&
LowPriでのredirectionを有効化
Destination ID:宛先
MSI Capability - MSIDR
Vector:宛先LAPICのベクタ番号
Delivery Mode:割り込み配送モード
Delivery Status:割り込み状況
Trigger Mode:レベルトリガ/エッ
ジトリガ
MSI-Xの場合
省略(フィールドが拡張されて沢山割
り込みが持てるが、仕組みは同じ)
ソースコード
MSI(-X) Capability

arch/x86/kernel/apic/io_apic.c
データシート
Intel® 5520 Chipset and Intel® 5500
Chipset

19.11.4.7 MSICTL: MSI Control
Register

19.11.4.8 MSIAR: MSI Address
Register

19.11.4.9 MSIDR: MSI Data Register
各方式で共通な要素
以下の三つのフィールドで宛先が指定
される
Destination Mode
Delivery Mode
Destination ID
割り込み先の指定方法
Physical Destination Mode
Destination FieldにAPIC IDを指定

「常に同じCPUへ割り込み」を実現
Logical Destination Mode(Flat Model)
Destination Fieldのbitで宛先LAPIC群の範囲を表現
Delivery Mode
Fixed

指定範囲の全てのLAPICへ割り込み
Lowest Priority

指定範囲の中で、最もTPR(Task Priority Register)の値が
低いCPUへ割り込み
Logical Destination Mode

(Cluster Model)
x2APICの場合、

bit31:16 = Cluster ID

bit15:0 = Logical ID
Flat Modelに比べて多くのCPU数を
サポートできる
Lowest Priority Mode
指定範囲の中で、最もTPR(Task
Priority Register)の値が低いLAPICへ
割り込み
但し、Linuxでは動作中にTPRを更新しな
い→全LAPICのTPRは全て同じ値
最小値のTPRを持つLAPICが複数ある場
合はラウンドロビンで1つ選択
データシート
Intel® 64 and IA-32 Architectures Software Developer
Manuals

10.6.1 Interrupt Command Register(ICR)

10.6.2.1 Physical Destination Mode 

10.6.2.2 Logical Destination Mode

10.6.2.4 Lowest Priority Delivery Mode
Intel® 64 Architecture x2APIC Specification

2.4.2 Logical Destination Register
Intel® I/O Controller Hub 10 (ICH10) Family Datasheet

5.8.4.3 Automatic Rotation Mode (Equal Priority Devices) 

5.8.4.4 Specific Rotation Mode (Specific Priority)
echo 1 > /proc/irq/<IRQ>/
smp_affinityした時に何が起きるのか
MSIなPCIeデバイスで確かめてみる
Intel Pro/1000(e1000e)
PCI Configuration Spaceはrootなら
/sys/bus/pciから読める

→ユーザランドから読める

→もしかして:lspci

# lspci -vvvv -s 00:19.0
00:19.0 Ethernet controller: Intel Corporation 82567LM Gigabit Network Connection (rev 03)
Subsystem: Lenovo Device 20ee
Control: I/O+ Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR+ FastB2B- DisINTx+
Status: Cap+ 66MHz- UDF- FastB2B- ParErr- DEVSEL=fast >TAbort- <TAbort- <MAbort- >SERR- <PERR- INTx-
Latency: 0
Interrupt: pin A routed to IRQ 44
Region 0: Memory at f2600000 (32-bit, non-prefetchable) [size=128K]
Region 1: Memory at f2625000 (32-bit, non-prefetchable) [size=4K]
Region 2: I/O ports at 1840 [size=32]
Capabilities: [c8] Power Management version 2
Flags: PMEClk- DSI+ D1- D2- AuxCurrent=0mA PME(D0+,D1-,D2-,D3hot+,D3cold+)
Status: D0 NoSoftRst- PME-Enable- DSel=0 DScale=1 PME-
Capabilities: [d0] MSI: Enable+ Count=1/1 Maskable- 64bit+
Address: 00000000fee0300c Data: 41b9
Capabilities: [e0] PCI Advanced Features
AFCap: TP+ FLR+
AFCtrl: FLR-
AFStatus: TP-
Kernel driver in use: e1000e
Kernel modules: e1000e
赤く塗った所がMSIのフィールドだが、これだ
と読めないのでlspciをforkしてMSIフィール
ドを表示するツールを作成

https://gist.github.com/1568777
# gcc -lpci msireg.c!
# ./a.out 00:19.0!
Message Signalled Interrupts: 64bit+ Queue=0/0 Enable+!
address_hi=0!
address_lo=fee0300c dest_mode=logical redirection=lowpri dest_id=3!
data=41b9 trigger=edge level=assert delivery_mode=lowpri vector=185
Logical modeでLowpri、destid=3、
vector=185になっている
# echo 1 > /proc/irq/44/smp_affinity!
# ./a.out 00:19.0!
Message Signalled Interrupts: 64bit+ Queue=0/0 Enable+!
address_hi=0!
address_lo=fee0100c dest_mode=logical redirection=lowpri dest_id=1!
data=41b9 trigger=edge level=assert delivery_mode=lowpri vector=185
dest_idが1に書き換わった
Affinityセット時のカーネルの挙動
システムグローバルなDestination Modeと
Delivery Modeの設定を保持

(apic->irq_dest_mode,

apic->irq_delivery_mode)
Affinityセット時にこの値を参照、Destination
IDと併せて書き込む
native_compose_msi_msg

arch/x86/kernel/apic/io_apic.c
OS初期化時の割り込みモード設定
環境によって異なるドライバを使用

arch/x86/kernel/apic/apic_flat_64.c, x2apic_cluster.c,
x2apic_phys.c…
apic_flat(非x2apicモード)

Delivery Mode = LowPri

Destination Mode = Logical
apic_physflat(非x2apicモード, CPUS > 8)

Delivery Mode = Fixed

Destination Mode = Physical
apic_x2apic_phys(x2apicモード,ACPIでPhysicalモード指定)

同上
ラウンドロビン割り込みできる環境は一定条件を満たした場合のみ
Intel® 64 and IA-32 Architectures Software
Developer Manuals
Intel® I/O Controller Hub 10 (ICH10) Family
Datasheet
Intel® 64 Architecture x2APIC Specification
Intel® 5520 Chipset and Intel® 5500 Chipset
linux/Documentation/IRQ-affinity.txt
Understanding the Linux Kernel, 3rd Edition
PCI Local Bus Specification Revision 3.0
参考資料
今までにまとめた資料
最近のPCアーキテクチャにおける割り込みルーティングの仕組み
/proc/irq/<IRQ>/smp_affinityの書き換えでPCIコンフィグレー
ション空間はどのように書き換わるか
/proc/irq/<IRQ>/smp_affinity
Interrupts on xv6
ハイパーバイザの作り方∼ちゃんと理解する仮想化技術∼ 第4回 I/
O 仮想化「割り込み編・その1」

Interrupt Affinityについて