236 Views
October 18, 26
スライド概要
2026年10月17日さくらインターネットさんにて
動画: https://www.youtube.com/watch?v=nGCn2cJcsVM
プログラマー
jus共催 第77回デバイスシェル芸勉強会 個人情報がクリエイティブコモンズ 上田 隆一 2026年10月17日 © 2026 上田隆一 第77回シェル芸勉強会
近況 しぇるげいすきー(招待制シェル芸Misskeyサーバー) 低空飛行 ロボットやさん向けLinuxの本 デバイス難しい・・・本日還元 第77回シェル芸勉強会 2
Software Designの連載 「魅惑の自作シェルの世界」 12月号(49回)の原稿を提出したところ 10月号: パターン削除の実装(後編)とパターン置換の実 装(前編) 11月号: パターン置換の実装(後編)とパラメータの空文 字・未定義チェック(前編) 12月号: パラメータの空文字・未定義チェック(後編) 1月号(第50回)予定: 未定 やっと中途半端前編後編が終わった模様 第77回シェル芸勉強会 3
シェル芸とは マウスも使わず、ソースコードも残さず、GUIツールを立ち上げる間もなく、あらゆる 調査・計算・テキスト処理をCLI端末へのコマンド入力一撃で終わらすこと。あるいは そのときのコマンド入力のこと。 第77回シェル芸勉強会 4
今回の座学と問題 デバイスについて まともにやるとすごいことになるので今回はつまみ食い程度(次回もたぶん デバイス?) 出題 あんまりシェル芸っぽくないかも(と、最初に書いてスライド作ってったら そうでもなくなった) 第77回シェル芸勉強会 5
準備 問題用データのダウンロード https://github.com/ryuichiueda/ShellGeiData $ git clone https://github.com/ryuichiueda/ShellGeiData.git $ cd ShellGeiData/vol.77 $ ls bcm2712-rpi-5-b.dtb 第77回シェル芸勉強会 6
計算機とデバイス 計算機にはCPU、DRAM以外にもいろいろ部品がついている HDD、SSD、NIC、グラフィックカード、ブザー、スピーカー、温度計、PCIe やUSBのホストとデバイス、・・・ ほとんどがCPUやOSから操作できる どうやって? 第77回シェル芸勉強会 7
CPUとデバイスのやりとり(CPU->デバイス) メモリマップドI/O(MMIO)がほとんど ある範囲のメモリの番地が特定のデバイスのレジスタに割り当てられる メモリ操作と同じ方法でデバイスも操作できる ポートマップドI/O 専用のアドレス空間と命令 専用めんどいし、ビデオカードなどにでかいメモリがあるともっと面倒 問題1: PCI(PCI Express)バスに挿すデバイス用に確保されている主要なメモリの 番地の範囲と番地の数を調べてみましょう 範囲の上限は「未満」で表現を 必要に応じてkB、MB、GB単位で よかったら他のデバイスについても 8 第77回シェル芸勉強会
解答例
sudo cat /proc/iomem | grep PCI | sed -ne 1p -e '/^[^ ]/p'
000a0000-000bffff : PCI Bus 0000:00
a0800000-bfffffff : PCI Bus 0000:00
c0000000-cfffffff : PCI ECAM 0000 [bus 00-ff]
2000000000-3fbfffffff : PCI Bus 0000:00
### kB単位 ###
sudo cat /proc/iomem | grep PCI | sed -ne 1p -e '/^[^ ]/p' | sed 's/ *//'| sed 's/-/ 0x/'
| sed 's/^/0x/'| awk '{for(i=1;i<=2;i++)$i=(strtonum($i)+(i-1)%2)/1024;print $0, $2-$1"kB"}'
640 768 : PCI Bus 0000:00 128kB
2629632 3145728 PCI Bus 0000:00 516096kB
3145728 3407872 PCI ECAM 0000 [bus 00-ff] 262144kB
134217728 267386880 PCI Bus 0000:00 133169152kB
### MiB単位 ###
sudo cat /proc/iomem | grep PCI | sed -ne 1p -e '/^[^ ]/p' | sed 's/ *//' | sed 's/-/ 0x/'
| sed 's/^/0x/'| awk '{for(i=1;i<=2;i++)$i=(strtonum($i)+(i-1)%2)/1024**2;print $0, $2-$1"MiB"}'
0.625 0.75 : PCI Bus 0000:00 0.125MiB
2568 3072 PCI Bus 0000:00 504MiB
3072 3328 PCI ECAM 0000 [bus 00-ff] 256MiB
131072 261120 PCI Bus 0000:00 130048MiB
うんちくは次ページ
第77回シェル芸勉強会
9
PCIe関係のメモリの範囲(DRAMの割当ではないことに注意) 項目ごとにkB、MiB、GiBを使い分けて整理 640 768 : PCI Bus 0000:00 128kB 2568 3072 PCI Bus 0000:00 504MiB 3072 3328 PCI ECAM 0000 [bus 00-ff] 256MiB 128 255 PCI Bus 0000:00 127GiB #昔のグラフィック(VRAM)用(PC/ATとかPC-98とかの時代) #32bit領域 #ECAM: Enhanced Configuration Access Mechanism #64bit領域 640kB: 昔のある時期のPCでの自由に使えるメモリの上限。邪魔 32bit領域も邪魔(64bit領域も微妙に邪魔だけどたぶん大丈夫) ECAM: PCIeのデバイスが持つ設定用メモリ(コンフィギュレーション領域) の範囲に割り当てられる 1デバイス4096バイト(昔のPCIデバイスは256バイト) バス 個 デバイス上限 個 ファンクション 個 kB MiB この領域に何か書き込むと飛ぶかも(責任とりませんがどうぞ) 第77回シェル芸勉強会 10
MMIOの番地の情報の所在 x86: ACPI(advanced configuration and power interface)テーブル どこかのROMにあってBIOS(UEFIのものを含む)が読み出す ARMなど: デバイスツリー ラズパイの場合はmicroSDカードのFAT32の領域に これもブートをつかさどるファームウェアが読みに行く あとはプラットフォームごとにカーネルに直書きする方法 ボードファイルと言うらしい 第77回シェル芸勉強会 11
デバイスツリー デバイスの配置をツリー状に記述したデータ データの実物: bcm2712-rpi-5-b.dtb ラズパイ5から拝借 問題2: データを解析して、Bluetoothがどこにぶら下がっているか、わかりやすく 表示してください 出力の例 a -> b -> c -> bluetooth コマンドを使ってテキストに変換します 結構わかりやすいデータなのでこれ以上はヒントなしで 第77回シェル芸勉強会 12
解答例
準備
sudo apt install device-tree-compiler
答え
dtc -I dtb -O dts bcm2712-rpi-5-b.dtb 2> /dev/null | grep '{$'
| awk -F '\t' '{for(i=1;i<=3;i++)a[i]=$i==""?a[i]:$i;for(i=1;i<=3;i++)$i=a[i] ;print}'
| grep blue | sed 's/{/->/g' | sed 's/->$//'
/ -> soc -> serial@7d50c000 -> bluetooth
第77回シェル芸勉強会
13
デバイスツリーに書いてあるメモリの割り当て
64bit、32bit入り乱れてややこしい
dtc -I dtb -O dts bcm2712-rpi-5-b.dtb | less
・・・
/ {
・・・
#address-cells = <0x02>; <-番地は32bitの数値2つで表現(64bit)
#size-cells = <0x01>;
<-メモリのサイズは32bitの数値1つで表現
・・・
soc {
compatible = "simple-bus";
#address-cells = <0x01>;
#size-cells = <0x01>;
ranges = <0x7c000000 0x10 0x7c000000 0x4000000>;
・・・ # ↑子の番地 ↑2個で親の番地 ↑サイズ
serial@7d50c000 { #↑子の 32bitの番地 0x7c000000 を親の 64bit の番地 0x107c000000 に対応づけ
compatible = "brcm,bcm7271-uart";
・・・
bluetooth {
・・・
第77回シェル芸勉強会
14
ACPIテーブル これも木構造でハードウェアのデバイスの構成を記述したもの 様々なテーブルで構成される RSDT(root system description table)から辿っていく 64bitの場合はXSDT(extended system description table) ファームウェアやOSが問い合わせるための関数が中心 たぶんLinux的な発想ならもっと静的になってるんじゃなかろうか 電源管理(特にサスペンド機能が重要なノートPC)のためにできた 発起人: Intel(CPU No.1)、東芝(ノートPC No.1)、Microsoft(商用OS No.1)。1997年当時 第77回シェル芸勉強会 15
読み出し方 /sys から持ってくる ueda@x1gen13:/tmp sudo apt install acpica-tools #準備 ueda@x1gen13:/tmp mkdir acpi ueda@x1gen13:/tmp cd acpi/ ueda@x1gen13:/tmp/acpi cp /sys/firmware/acpi/tables/* ./ ueda@x1gen13:/tmp/acpi sudo rsync -av /sys/firmware/acpi/tables/* ./ ueda@x1gen13:/tmp/acpi sudo iasl -d * ueda@x1gen13:/tmp/acpi ls *.dsl APIC.dsl DMAR.dsl FACS.dsl MSDM.dsl SSDT10.dsl SSDT15.dsl SSDT2.dsl BATB.dsl DSDT.dsl FPDT.dsl NHLT.dsl SSDT11.dsl SSDT16.dsl SSDT20.dsl BGRT.dsl DTPR.dsl HPET.dsl PHAT.dsl SSDT12.dsl SSDT17.dsl SSDT21.dsl DBG2.dsl ECDT.dsl LPIT.dsl SDEV.dsl SSDT13.dsl SSDT18.dsl SSDT22.dsl DBGP.dsl FACP.dsl MCFG.dsl SSDT1.dsl SSDT14.dsl SSDT19.dsl SSDT23.dsl SSDT24.dsl SSDT25.dsl SSDT26.dsl SSDT3.dsl SSDT4.dsl SSDT5.dsl SSDT6.dsl SSDT7.dsl SSDT8.dsl SSDT9.dsl TPM2.dsl UEFI.dsl WSMT.dsl 他、 acpidump というコマンドを使う方法も 一部のテーブルは出てこない模様 第77回シェル芸勉強会 16
ACPIテーブルの読み方 のようなパス(ACPIパス) \ : ルート、 PC00 : PCIバス、 XHCI : USBホストコントローラ、 RHUB : ルート ハブ、 HS06 : USBポート(6番)、 BTTM : Bluetoothモジュール MMIOの番地の範囲 _CRS (current resource settings)という関数から得られる 番地が関数にベタ書きされていない限りそこだけ読んでも分からない (つらい) ACPIテーブルの他のどこかにある(かも。未調査) 問題3: HPET(high precision event timer)というデバイスの番地の範囲と、接続場 所を特定してください ワンライナーというよりコマンドを使って調査を \_SB_.PC00.XHCI.RHUB.HS06.BTTM 第77回シェル芸勉強会 17
解答例
grep HPET *.dsl
DMAR.dsl:[088h 0136 001h]
Device Scope Type : 04 [Message-capable HPET Device]
DSDT.dsl:
Device (HPET) /* この下にありそう */
・・・
ueda@x1gen13:/tmp/acpi
less DSDT.dsl
・・・
Device (HPET)
{
Name (_HID, EisaId ("PNP0103") /* HPET System Timer */) // _HID: Hardware ID
Name (_UID, Zero) // _UID: Unique ID
Name (BUF0, ResourceTemplate ()
//BUF0というデータを定義
{
Memory32Fixed (ReadWrite,
0xFED00000,
// Address Base
***番地の始点***
0x00000400,
// Address Length ***長さ***
_Y3E)
})
・・・
Method (_CRS, 0, Serialized) // _CRS: Current Resource Settings
{
If (HPTE)
{
CreateDWordField (BUF0, \_SB.PC00.LPCB.HPET._Y3E._BAS, HPT0) // _BAS: Base Address ***接続の情報(\_SB.PC00.LPCB.HPET)***
HPT0 = HPTB /* \HPTB */
}
Return (BUF0) /* \_SB_.PC00.LPCB.HPET.BUF0 */ //BUF0を返す
}
}
第77回シェル芸勉強会
18
MMIOの番地の伝達 OSはメモリをたくさん使う前にデバイスが使う番地を把握しないといけない データをその番地に置けないので どうやって早期に把握しているか: BIOSなどからもらう 問題4: 番地の情報をもらっている形跡、そのあと番地をOSがいじっている形 跡を探してください 第77回シェル芸勉強会 19
解答例(1/2) 「 BIOS 」で dmesg の出力に検索 先頭のほうにメモリの受け渡しのログ ueda@x1gen13:~ sudo dmesg | grep BIOS [ 0.000000] BIOS-provided physical RAM map: [ 0.000000] BIOS-e820: [mem 0x0000000000000000-0x000000000009efff] [ 0.000000] BIOS-e820: [mem 0x000000000009f000-0x00000000000fffff] [ 0.000000] BIOS-e820: [mem 0x0000000000100000-0x000000004f2fefff] [ 0.000000] BIOS-e820: [mem 0x000000004f2ff000-0x0000000051ffffff] [ 0.000000] BIOS-e820: [mem 0x0000000052000000-0x0000000086e2efff] [ 0.000000] BIOS-e820: [mem 0x0000000086e2f000-0x000000008d32efff] [ 0.000000] BIOS-e820: [mem 0x000000008d32f000-0x000000008df2efff] [ 0.000000] BIOS-e820: [mem 0x000000008df2f000-0x000000008dffefff] [ 0.000000] BIOS-e820: [mem 0x000000008dfff000-0x000000008dffffff] [ 0.000000] BIOS-e820: [mem 0x000000008e000000-0x00000000a07fffff] [ 0.000000] BIOS-e820: [gap 0x00000000a0800000-0x00000000bfffffff] [ 0.000000] BIOS-e820: [mem 0x00000000c0000000-0x00000000cfffffff] [ 0.000000] BIOS-e820: [gap 0x00000000d0000000-0x00000000fed1ffff] [ 0.000000] BIOS-e820: [mem 0x00000000fed20000-0x00000000fed7ffff] [ 0.000000] BIOS-e820: [gap 0x00000000fed80000-0x00000000ffffffff] [ 0.000000] BIOS-e820: [mem 0x0000000100000000-0x00000001044fffff] [ 0.000000] BIOS-e820: [mem 0x0000000104500000-0x000000085f7fffff] [ 0.000000] efi: ... 第77回シェル芸勉強会 System RAM device reserved System RAM device reserved System RAM device reserved ACPI NVS ACPI data System RAM device reserved device reserved device reserved device reserved System RAM 20
解答例(2/2) その後のOSによるメモリの操作( [mem で検索をかければおそらく全部出てく る) sudo dmesg | grep '\[mem' [ 0.000000] BIOS-e820: [mem 0x0000000000000000-0x000000000009efff] System RAM ・・・ [ 0.000000] e820: remove [mem 0xc0000000-0xcfffffff] device reserved [ 0.000007] e820: update [mem 0x00000000-0x00000fff] System RAM ==> device reserved [ 0.000008] e820: remove [mem 0x000a0000-0x000fffff] System RAM [ 0.004351] e820: update [mem 0x7f0e1000-0x7f0e1fff] System RAM ==> device reserved ・・・ [ 1.390688] pci 0000:00:15.0: BAR 0 [mem 0x202c000000-0x202c000fff 64bit]: assigned [ 1.390708] pci 0000:00:15.3: BAR 0 [mem 0x202c001000-0x202c001fff 64bit]: assigned [ 1.390728] pci 0000:00:1f.5: BAR 0 [mem 0xa0800000-0xa0800fff]: assigned ・・・ 第77回シェル芸勉強会 21
PCI Express(PCIe) PCIバスの新しいやつ(雑) バスといってるのにシリアライズされている 1つのデバイスでシリアライズされた線(レーン)を複数使える PCI Express x1, x2, x4, x8, x16, ... おじさんすぎてよく分からんけどGPUはx16にささってるらしい おじさんすぎてよく分からないので速度はネットで調べてくだしあ CPUのチップ中のルートコンプレックスというところから出ている CPUとDRAMとPCIeがつながっているところ 昔のノースブリッジ PCIeにぶら下がっているデバイスはコンピュータからは未知 番地の割当どうする? 第77回シェル芸勉強会 22
PCIeのデバイスの確認方法 lspci を使う lspci -tv -[0000:00]-+-00.0 Intel Corporation Device 6400 +-02.0 Intel Corporation Lunar Lake [Intel Arc Graphics 130V / 140V] ・・・ +-0d.0 Intel Corporation Lunar Lake-M Thunderbolt 4 USB Controller ・・・ +-1c.0-[1c]-+-1c.4-[04]----00.0 Sandisk Corp SN8000S NVMe SSD +-1f.0 Intel Corporation Device a807 +-1f.3 Intel Corporation Lunar Lake-M HD Audio Controller +-1f.4 Intel Corporation Lunar Lake-M SMbus Controller \-1f.5 Intel Corporation Lunar Lake-M SPI Controller 番号 、 [1c] 、 [04] 、...: ドメイン番号(4桁)とバス番号(2桁) 1c.0 など: デバイス番号とファンクション番号 23 [0000:00] 第77回シェル芸勉強会
各デバイスの情報 例: WiFiのコントローラー sudo lspci -v -s 00:14.3 00:14.3 Network controller: Intel Corporation BE201 320MHz (rev 10) Subsystem: Intel Corporation Device 00e0 Flags: bus master, fast devsel, latency 0, IRQ 18, IOMMU group 10 Memory at 204fd5c000 (64-bit, non-prefetchable) [size=16K] #番地の割り当て #non-prefetchable: 普通のメモリのように先読みするとレジスタの状態変わるからヤメロという意味 ・・・これ以下はまたあとで・・・ 実際の番地の割り当てと一致 sudo cat /proc/iomem | grep 204fd5c000 204fd5c000-204fd5ffff : 0000:00:14.3 204fd5c000-204fd5ffff : iwlwifi ただしこの番地は最初から決まっているわけではない 仕組みを覗いていきましょう 第77回シェル芸勉強会 24
コンフィギュレーション領域の観察 でコンフィギュレーション領域の最初の64バイトを出力可能 最初の64バイト: ヘッダーの領域 lspci -x sudo lspci -x -s 00:14.3 00:14.3 Network controller: Intel Corporation BE201 320MHz (rev 10) 00: 86 80 40 a8 06 04 10 00 10 00 80 02 00 00 80 00 #ベンダIDとか 10: 04 c0 d5 4f 20 00 00 00 00 00 00 00 00 00 00 00 #BAR0〜3 20: 00 00 00 00 00 00 00 00 00 00 00 00 86 80 e0 00 #BAR4〜5他 30: 00 00 00 00 c8 00 00 00 00 00 00 00 ff 03 00 00 から バイト: BAR0〜5 BAR: ベースアドレスレジスタ 64bitの場合は0と1、2と3、4と5をペアで使う 最初から番地が決まっているわけではなく、BIOSやOSが書き込む 0x10 第77回シェル芸勉強会 25
問題5 小問1 なにかのデバイス、ファンクションについて、BAR0〜5に記録されている2進 数を次例のように出力してください(リトルエンディアンです) BAR1 00000020 BAR0 4fd5c004 # 下の桁の余計なデータはフラグです。小問2、3が終わったら調査を BAR3 00000000 BAR2 00000000 BAR5 00000000 BAR4 00000000 小問2 すべてのPCIeのデバイスについて上記のように出力してください。ただし、各 行の頭にバス、デバイス、ファンクション番号をつけてください 小問3(おまけ) BARの数値自体には使う番地の範囲の情報がありませんが、コンピュータは BARから特定できます。どういうことでしょう? 第77回シェル芸勉強会 26
解答例(小問1)
sudo lspci -x -s 00:14.3 | sed -n /[12]0:/p | sed 's/.*: //' | fold -w12 | head -n 6
| awk '{printf "BAR"(NR-1)%6" "; for(i=4;i>=1;i--)printf $i;print ""}' | xargs -n 4
| awk '{print $3,$4,$1,$2}'
BAR1 00000020 BAR0 4fd5c004 #開始の番地: 0x204fd5c000 と読める
BAR3 00000000 BAR2 00000000
BAR5 00000000 BAR4 00000000
末尾の ( 0100 ): フラグ
0 : プリフェッチ不可 / 10 : 64bit / 0 : MMIOの番地
dmesg の出力から BAR で検索すると設定の状況を確認できる
[
sudo dmesg | grep BAR | grep 14.3
0.269733] pci 0000:00:14.3: BAR 0 [mem 0x204fd5c000-0x204fd5ffff 64bit]
第77回シェル芸勉強会
27
解答例(小問2)
lspci | awk '{print $1}' | while read d ; do sudo lspci -x -s $d | sed -n /[12]0:/p | sed 's/.*: //'
| fold -w12 | head -n 6 |awk '{printf "BAR"(NR-1)%6" "; for(i=4;i>=1;i--)printf $i;print ""}'
| xargs -n 4 | awk '{print "'$d'",$3,$4,$1,$2}' ; done
00:02.0 BAR1 00000020 BAR0 4e00000c #フラグ: 1100(先頭の1はプリフェッチ可の意味)
00:02.0 BAR3 00000020 BAR2 0000000c
00:02.0 BAR5 00000000 BAR4 00000000
・・・
00:07.0 BAR1 00000000 BAR0 00000000 #ブリッジなのでメモリを持たない(別の情報が書いてある)
00:07.0 BAR3 00002020 BAR2 00492000
00:07.0 BAR5 2bf11001 BAR4 bc10b000
・・・
00:1f.4 BAR1 00000020 BAR0 4fd60004
00:1f.4 BAR3 00000000 BAR2 00000000
00:1f.4 BAR5 00000000 BAR4 0000efa1 #ポートマップI/Oの番地指定(0xEFA0)
00:1f.5 BAR1 00000000 BAR0 a0800000 #0000: プリフェッチ不可、32bit、MMIO
00:1f.5 BAR3 00000000 BAR2 00000000
00:1f.5 BAR5 00000000 BAR4 00000000
・・・
第77回シェル芸勉強会
28
PCIデバイスへの番地の割り当て(小問3) BIOSなどがデバイスを列挙し、対応するコンフィグレーション領域のBARに開始 の番地を書き込む OSもBARをいじれる 番地の範囲の要求方法(メモリがデバイス側にあるからできる芸当) 実はBARのいくつかのビットは書き込み禁止で0に固定してある BIOSなどがBARに1を埋めて読み出す 0の場所で範囲が分かる ビット目からフラグ直前の ビット目: バイト分の幅が必要 参考: https://osdev.jp/wiki/PCI-Memo 第77回シェル芸勉強会 29
割り込み 基本的にCPUが割り込みピンから受付 基本は「割り込みたい」という信号しか受け付 けない データはMMIOやポートマップドI/Oで 割り込みピン(基本) マイコン: CPUから直接何本が出ている PC/AT互換機: 割り込みコントローラが代理で何 本も持っている(例: 右図) 最近: CPU多い。デバイスもたくさん&抜き差し とりあえず最近のx86について次ページからお さえていきましょう 第77回シェル芸勉強会 30
割り込みの観察 /proc/interrupts cat /proc/interrupts CPU0 CPU1 1: 0 0 8: 0 0 9: 82149 0 12: 0 0 14: 0 0 27: 0 0 30: 0 0 ・・・ にカウンタ CPU2 0 0 0 0 0 0 19117577 CPU3 0 0 0 1745040 0 0 0 ... ... ... ... ... ... ... ... CPU7 0 IR-IO-APIC 0 IR-IO-APIC 0 IR-IO-APIC 0 IR-IO-APIC 638653 IR-IO-APIC 0 IR-IO-APIC 0 IR-IO-APIC 1-edge 8-edge 9-fasteoi 12-edge 14-fasteoi 27-fasteoi 30-fasteoi i8042 rtc0 acpi i8042 INTC105D:00, INTC105D:01, (略) idma64.0, i2c_designware.0 idma64.1, i2c_designware.1 問題6: /proc/interrupts の特定の行の割り込みについて、割り込みの秒速の回 数を出力してください(計測は3秒ほど) ワンライナーで生じる割り込みについては気にしないことにします 第77回シェル芸勉強会 31
解答例
IRQ=LOC ; cat <( cat /proc/interrupts | awk '$1=="'$IRQ':"'
| awk '{for(i=2;i<=9;i++)s+=$i; print s}' ) <( sleep 3 ;cat /proc/interrupts
| awk '$1=="'$IRQ':"' | awk '{for(i=2;i<=9;i++){s+=$i;$i=""}; print s, $0}' )
| xargs | awk '{print ($2-$1)/3"回/s", $0}'
1639.67回/s 225869280 225874199 LOC: Local timer interrupts
第77回シェル芸勉強会
32
割り込みの方式(1/2) 番号の小さいほうはI/O APICが受け付ける割り込み cat /proc/interrupts CPU0 CPU1 1: 0 0 8: 0 0 9: 82149 0 12: 0 0 14: 0 0 27: 0 0 30: 0 0 ・・・ CPU2 0 0 0 0 0 0 19117577 CPU3 0 0 0 1745040 0 0 0 ... ... ... ... ... ... ... ... CPU7 0 IR-IO-APIC 0 IR-IO-APIC 0 IR-IO-APIC 0 IR-IO-APIC 638653 IR-IO-APIC 0 IR-IO-APIC 0 IR-IO-APIC 1-edge 8-edge 9-fasteoi 12-edge 14-fasteoi 27-fasteoi 30-fasteoi i8042 #キーボード rtc0 #時計 acpi #なんだっけ? i8042 #↓たぶん古いPCIの割り込み機能 INTC105D:00, INTC105D:01, (略) idma64.0, i2c_designware.0 idma64.1, i2c_designware.1 APIC: advanced programmable interrupt controller 現行の割り込みコントローラ IO-APIC: I/O APIC 昔ながらの割り込みを受け付ける部分(詳しい記事) IR: interrupt remapping 仮想化の仕組みが間にいてリマッピングしているという意味 第77回シェル芸勉強会 33
割り込みの方式(2/2) そのあとはPCIe関係の割り込み 120: ・・・ 130: 138: 146: 147: ・・・ 163: 164: 179: 180: 181: ・・・ 0 0 0 0 0 ... 0 DMAR-MSI 1-edge dmar1 0 0 5317 0 0 0 0 5303 0 0 0 0 0 77769 0 0 0 0 0 0 ... 0 IR-PCI-MSI-0000:00:0d.0 ... 0 IR-PCI-MSI-0000:00:14.0 ... 0 IR-PCI-MSIX-0000:00:0d.2 ... 0 IR-PCI-MSIX-0000:00:0d.2 0-edge 0-edge 0-edge 1-edge xhci_hcd xhci_hcd thunderbolt thunderbolt 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 5325 0 34 0 39811 0 5300 0 0 0 ... 0 IR-PCI-MSIX-0000:00:0d.3 ... 0 IR-PCI-MSIX-0000:00:0d.3 ... 0 IR-PCI-MSI-0000:00:16.0 ... 0 IR-PCI-MSIX-0000:04:00.0 ... 0 IR-PCI-MSIX-0000:04:00.0 0-edge 1-edge 0-edge 0-edge 1-edge thunderbolt thunderbolt mei_me nvme0q0 nvme0q1 MSI / MSI-X: message signaled interrupt MMIOされたレジスタの特定の番地にフラグを立てることで割り込みを入 れる方式 I/O APICではなく、各CPU(にあるlocal APIC)に直接届く lspci での確認方法) 設定はコンフィグレーション領域に(次ページに 34 第77回シェル芸勉強会
MSI / MSI-Xの確認方法 コンフィグレーション領域の「ケイパビリティー」に記述される sudo lspci -vvv -s 00:14.3 00:14.3 Network controller: Intel Corporation BE201 320MHz (rev 10) ・・・ Capabilities: [d0] MSI: Enable- Count=1/1 Maskable- 64bit+ #使われてない Address: 0000000000000000 Data: 0000 ・・・ Capabilities: [80] MSI-X: Enable+ Count=32 Masked- #最大32個(/proc/interruptsを見るとコアに1つずつ割り当てしている) Vector table: BAR=0 offset=00002000 #割り込みベクタテーブル(割り込み時の処理のポインタ)の場所 PBA: BAR=0 offset=00003000 ・・・ Kernel driver in use: iwlwifi Kernel modules: iwlwifi 第77回シェル芸勉強会 35
まとめ デバイスについてちょっと齧った おもにMMIOまわりと割り込みちょっと 新しい(特にUEFIまわりの)情報が少なく勉強が難しい カーネルが立ち上がる前のログがわずか 本が少ない・仕様書読むしかない 勉強方法? OS自作、デバイスドライバ作成の本を読む 技術評論社から今度出る自作OS本の改訂版が参考になりそう https://www.amazon.co.jp/dp/429715921X Kindleの自費出版のも探したけどやっぱり出版社通さないと・・・ LLMに聞く(検証が必要だが結構むずかしい) 第77回シェル芸勉強会 36