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
BareMetalで遊ぶ Raspberry Pi 4 - GIC v2編-/BareMet...
Search
Toshifumi NISHINAGA
February 08, 2020
Programming
6
4.9k
BareMetalで遊ぶ Raspberry Pi 4 - GIC v2編-/BareMetal Raspberry Pi 4 - GICv2 -
KernelVM 関西 10回目の発表資料(省略なし)版です。
BereMetal Raspberry Pi 4のGICv2を使って割り込みを処理する方法をご紹介します。
Toshifumi NISHINAGA
February 08, 2020
Tweet
Share
More Decks by Toshifumi NISHINAGA
See All by Toshifumi NISHINAGA
BareMetalで遊ぶRaspberry Pi 5 PCIe編/KernelVM Tokyo17
tnishinaga
0
1.7k
probe-rsの紹介と最近の貢献紹介/CELF-02-03
tnishinaga
1
340
SecurityCamp2023基板作るコース講義資料/Security Camp 2023 Lecture Materials
tnishinaga
8
2.5k
RP2040のPIOを使う話/KernelVM Hokuriku 6
tnishinaga
3
1.2k
JTAGでArmプロセッサをデバッグする方法のつづき/KernelVM_Tokyo16
tnishinaga
0
380
CMSIS-DAPの概要と使い方/KernelVM Online5
tnishinaga
0
1.7k
JTAGでarmプロセッサをデバッグする話/KernelVM Online4
tnishinaga
4
3k
ARM入門/arm introduction
tnishinaga
15
12k
俺の仮想マシンルーターがこんなに遅いはずはない/ KernelVM online 1
tnishinaga
0
2.7k
Other Decks in Programming
See All in Programming
Stackless и stackful? Корутины и асинхронность в Go
lamodatech
0
690
As an Engineers, let's build the CRM system via LINE Official Account 2.0
clonn
1
670
ソフトウェアの振る舞いに着目し 複雑な要件の開発に立ち向かう
rickyban
0
890
Monixと常駐プログラムの勘どころ / Scalaわいわい勉強会 #4
stoneream
0
270
CQRS+ES の力を使って効果を感じる / Feel the effects of using the power of CQRS+ES
seike460
PRO
0
110
テストケースの名前はどうつけるべきか?
orgachem
PRO
0
130
Zoneless Testing
rainerhahnekamp
0
120
Fibonacci Function Gallery - Part 1
philipschwarz
PRO
0
210
Go の GC の不得意な部分を克服したい
taiyow
2
770
複雑な仕様に立ち向かうアーキテクチャ
myohei
0
170
testcontainers のススメ
sgash708
1
120
17年周年のWebアプリケーションにTanStack Queryを導入する / Implementing TanStack Query in a 17th Anniversary Web Application
saitolume
0
250
Featured
See All Featured
A Philosophy of Restraint
colly
203
16k
Rails Girls Zürich Keynote
gr2m
94
13k
Designing Experiences People Love
moore
138
23k
Designing on Purpose - Digital PM Summit 2013
jponch
116
7k
The Power of CSS Pseudo Elements
geoffreycrofte
73
5.4k
How GitHub (no longer) Works
holman
311
140k
Distributed Sagas: A Protocol for Coordinating Microservices
caitiem20
330
21k
Code Reviewing Like a Champion
maltzj
520
39k
Docker and Python
trallard
42
3.1k
Let's Do A Bunch of Simple Stuff to Make Websites Faster
chriscoyier
507
140k
Faster Mobile Websites
deanohume
305
30k
GraphQLとの向き合い方2022年版
quramy
44
13k
Transcript
BareMetalで遊ぶ Raspberry Pi 4 - GIC v2編- 2020/02/08 KernelVM Kansai@10
@tnishinaga 1
今日のコード https://github.com/tnishinaga/baremetal_pi4_irq_sample 2
動機と目的 3
2019/11/26 Raspberry Pi 4 日本販売開始 4
Q. Pi 4でなにがしたい? 5
A. Pi 4でBareMetal開発したい!! 6
過去の実績 • 初代Raspberry Pi(BCM2835) ◦ ARMv6での自作コード起動、 GPIO、UART、SPI、I2C、割り込みまでBareMetal開発をした ◦ やり方をまとめて本を出した ▪
https://tatsu-zine.com/books/raspi-bm • Raspberry Pi 2(BCM2836) ◦ 割愛 • Raspberry Pi 3(BCM2837) ◦ ARMv8 64bitモードで起動、GPIO、UART、割り込みまでBareMetal開発をした ↑ Pi4でも動かしたい ◦ やり方をまとめてセキュリティ・キャンプ 2019の教材として配布 7
• Pi 4で追加された割り込みコントローラGICv2への対応が必要 • 参考 ◦ dtsの目diff結果 https://docs.google.com/spreadsheets/d/1e51SxsiOClDed5u0zteMjrxNY6Pgj7kWrGNz7XM0o ek/edit?usp=sharing ◦
BCM2711について @eggman https://qiita.com/eggman/items/402d8ba20fa021cc4531 Pi 4でも既存のコードを動かすには 8
発表の目標 9 読んだ人がBareMetal Raspberry Pi 4 でGICv2使った割り込みをできるようにする
割り込みコントローラ 10
割り込みコントローラとは • 大体以下の機能をもつもの ◦ ペリフェラル等からの割り込みをフィルタ ◦ 適切なプロセッサに割り込みをルーティング 11 Interrupt Controller
Processor Peripheral N 1 N 1
Raspberry Piの割り込みコントローラ • BCM2835(初代), BCM2836-BCM2837(Pi2-Pi3), BCM2711(Pi4)で異なる 12
BCM2835の割り込みアーキテクチャ • コントローラはbcm2835-armctrl-icのみ 13 bcm2835-a rmct-ic Processor Peripheral N 1
1 1
Raspberry Pi 2登場 • マルチコアになった • BCM2835-armctrl-icはマルチコア対応していない • Q. どうしたか?
• A. 14
Raspberry Pi 2登場 • マルチコアになった • BCM2835-armctrl-icはマルチコア対応していない • Q. どうしたか?
• A. もう一つ割り込みコントローラを追加した ◦ https://www.raspberrypi.org/documentation/hardware/raspberrypi/bcm2836/QA7_rev3.4.pdf 15
BCM2836/BCM2837の割り込み • bcm2835-armctrl-ic (arm_control) で割り込みをフィルタ • bcm2836-arm-l1-intc (IRQ routing) でルーティング
16 図は「BCM2836 ARM-local peripherals, 3.2 Interrupt routing, pp.4」より引用 https://www.raspberrypi.org/documentation/hardware/raspberrypi/bcm2836/Q A7_rev3.4.pdf
BCM2711の割り込み • GICv2だけになったはず ◦ 割り込みの親はすべて GICv2のはず ◦ 一応bcm2836-arm-l1-intcも搭載 (armstubでプリスケーラの設定などに使ってる) •
GICv2でフィルタとルーティング 17 GICv2 Processor Peripheral N 1 N 1
GICv2 18
Generic Interrupt Controller version 2(GICv2)とは • arm社の作った割り込みコントローラ • 仮想化支援機能あり •
セキュリティ機能あり ◦ 一部レジスタアクセス制限など 19
• ARM® Generic Interrupt Controller Architecture version 2.0 Architecture Specification
◦ https://static.docs.arm.com/ihi0069/c/IHI0069C_gic_architecture_specification.pdf ◦ GICv2全体の仕様が書いてある。基本これだけで良い。 • CoreLink GIC-400 Generic Interrupt Controller Technical Reference Manual ◦ http://infocenter.arm.com/help/topic/com.arm.doc.ddi0471a/DDI0471A_gic400_r0p0_trm.pdf ◦ Pi 4に乗ってるGICの実装。実装依存の機能を扱いたい場合に読む。 マニュアルの場所 20
その他情報源 21 • TOPPERSプロジェクト 設計メモ GIC(ARM Generic Interrupt Controller)に関す るメモ
◦ https://dev.toppers.jp/trac_user/contrib/export/306/asp3_wo_tecs/trunk/arch/arm_gcc/doc/gic_ memo.txt ◦ GICv2の説明が日本語で箇条書きで書かれている。わかりやすい。 • GIC(汎用割り込みコントローラ)|Cortex-A編 - APS ◦ https://www.aps-web.jp/academy/ca/08/ ◦ 多分GICv1の説明。レジスタ名などが異なるが大まかな部分は同じ。
用語説明 22 • 割り込みタイプ ◦ SGI ◦ PPI ◦ SPI
• Interrupt ID • GICの機能ブロック ◦ Distributor ◦ CPU Interface ◦ Virtual CPU Interface ▪ Virtual interface control ▪ Virtual CPU interface
割り込みタイプ • Software Generated Interrupt(SGI) ◦ ソフトウェア割り込み ◦ GICD_SGIRレジスタに書き込むと発生させられる ◦
interprocessor communication(IPC)に使う • Private Peripheral Interrupt(PPI) ◦ 特定プロセッサ用のペリフェラル割り込み • Shared Peripheral Interrupt(SPI) ◦ プロセッサを指定しないペリフェラル割り込み ◦ どのプロセッサに割り込みを送るかは要設定 23
割り込みID • 割り込み要因に割り当てられたID • IDの割当は実装依存 • IDの範囲は0 - 1023 •
割り込みタイプによって番号の割当範囲が決まってる ◦ SGI : 0 - 15 ◦ PPI : 16 - 31 ◦ SPI : 32 - 1019 ◦ 特殊用途: 1020 - 1023 24
GICの機能ブロック • Distributor ◦ 割り込み優先度や割り込みのルーティングを設定する • CPU Interface ◦ 各プロセッサに届いた割り込みを処理するためのブロック
◦ プロセッサ毎にあるらしい(試せてない) • Virtual CPU Interface ◦ 仮想マシンで使うらしい ◦ 今回は扱わないので省略 25 Distributor CPU Interfaces Peripherals Processors GIC
GICv2のレジスタ • 機能ブロックごとにレジスタのブロックが分かれている • レジスタ名にはブロック名前が入る ◦ Distributor(GICD_*) ◦ CPU Interface(GICC_*)
◦ Hypervisor(GICH_*) ◦ Virtual CPU Interface(GICV_*) 26
セキュアアクセスとノンセキュアアクセス • 一部レジスタへのアクセスを制限できる • Pi 4のカーネルはEL2で動くのでノンセキュアアクセスしかできない ◦ Raspberry Piはkernel起動前にEL3(secure)からEL2(non-secure)に移行するため •
今回はノンセキュア時の設定のみ紹介 27
GICv2の初期設定 (Raspberry Pi 4の場合) 28
• GICv2を理解するために UART入力割り込みを受けて、 入力を出力におうむ返しするプログラムを作る 目標 29
やること • GICv2レジスタのベースアドレス調査 • UARTの割り込みIDの調査 • armstubで行っている初期設定確認 • GIC初期化コード記述 •
割り込み処理コード記述 30
GICv2レジスタのベースアドレス調査 • ベースアドレスは0xff841000 ◦ rangesで0x40000000が0xff800000に変換 • 各レジスタのアドレス ◦ GICD: 0xff841000
◦ GICC: 0xff842000 ◦ GICH: 0xff844000 ◦ GICV: 0xff846000 31 https://github.com/raspberrypi/linux/blob/rpi-4.19.y/ arch/arm/boot/dts/bcm2838.dtsi より引用
UARTの割り込みID調査 • 割り込みIDは153 ◦ dtsに書かれているのは SPIの中で何番目かの値 ◦ GICではその前にSGIとPPIがいるので32を加算した 値がGICの割り込みIDになる ◦
詳しくはマニュアル参照 https://github.com/raspberrypi/linux/blob/rpi-4.19.y/Documentation /devicetree/bindings/interrupt-controller/arm,gic.txt 32 https://github.com/raspberrypi/linux/blob/rpi-4.19.y/ arch/arm/boot/dts/bcm2838.dtsi より引用
armstubで行なっている初期設定確認 • Raspberry Pi はEL3でarmstubを実行し、EL2に降りてカーネルを起動する ◦ https://github.com/raspberrypi/tools/blob/master/armstubs/armstub8.S • armstubで以下のGIC設定を行ってから起動する ◦
GICD_CTLRでGroup1とGroup0の割り込みを有効化 ◦ GICC_CTLRでGroup関係なくIRQをGICで制御するよう設定 ◦ GICC_PMRで割り込み優先度マスクを 0xff(全レベル)に設定 ◦ GICD_IGROUPRで全割り込みIDをGroup1に設定 33
Pi4での割り込み初期設定コード 1. ペリフェラルの割り込み設定 a. UART入力割り込みを有効化 2. 割り込みコントローラ設定 a. 後述 3.
プロセッサの割り込み設定 a. ベクタテーブル設定 b. 割り込みのルーティング設定( EL1以外では必要) c. IRQ割り込みの有効化(DAIFレジスタ) 34
Pi4での割り込み初期設定コード 1. ペリフェラルの割り込み設定 a. UART入力割り込みを有効化 2. 割り込みコントローラ設定 a. 後述 3.
プロセッサの割り込み設定 a. ベクタテーブル設定 b. 割り込みのルーティング設定( EL1以外では必要) c. IRQ割り込みの有効化(DAIFレジスタ) 35
GICv2の初期設定(non-secure, Pi 4の場合) • GICD_TYPERで割り込みIDの最大値を調べる • GICD_ISENABLERで割り込みを有効するIDを設定 • GICD_PRIORITYRで割り込み優先度を設定 •
GICD_ITARGETSRで送り先プロセッサ設定 • GICD_CTLRでDistributorを有効化 • GICC_CTLRで割り込みを許可するグループを設定 36
GICv2の初期設定(non-secure, Pi 4の場合) • GICD_TYPERで割り込みIDの最大値を調べる • GICD_ISENABLERで割り込みを有効するIDを設定 • GICD_PRIORITYRで割り込み優先度を設定 •
GICD_ITARGETSRで送り先プロセッサ設定 • GICD_CTLRでDistributorを有効化 • GICC_CTLRで割り込みを許可するグループを設定 37
GICD_TYPERで割り込みIDの最大値を調べる • 全割り込みを初期設定するためにはIDの総数は必須 • 割り込みIDの数は実装依存 • GICD_TYPERレジスタの下位5bit(= ITLinesNumber)を以下の式で計算 • 割り込みIDの数
= (2 ^ ITLinesNumber) - 1 38 ITLinesN umber LSPI Reserved 16|15 11 9 8 10 7 5 4 0 Reserved SecurityExtn CPU Number
GICv2の初期設定(non-secure, Pi 4の場合) 39 • GICD_TYPERで割り込みIDの最大値を調べる • GICD_ISENABLERで割り込みを有効するIDを設定 • GICD_PRIORITYRで割り込み優先度を設定
• GICD_ITARGETSRで送り先プロセッサ設定 • GICD_CTLRでDistributorを有効化 • GICC_CTLRで割り込みを許可するグループを設定
GICD_ISENABLERで割り込みを有効するIDを設定 • 割り込みを有効に設定するレジスタたち • 対応するビットを1にすると有効化 • 例:割り込みIDがmの割り込みを有効化 ◦ GICD_ISENABLER [
m / 32 ] |= 1 << m mod 32 ◦ (GICD_ISENABLERの型はuint32_t) 40 Set-enable bits 31 0
GICv2の初期設定(non-secure, Pi 4の場合) • GICD_TYPERで割り込みIDの最大値を調べる • GICD_ISENABLERで割り込みを有効するIDを設定 • GICD_PRIORITYRで割り込み優先度を設定 •
GICD_ITARGETSRで送り先プロセッサ設定 • GICD_CTLRでDistributorを有効化 • GICC_CTLRで割り込みを許可するグループを設定 41
GICD_PRIORITYRで割り込み優先度を設定 • 割り込みの優先度(0 - 255)を設定するレジスタたち • 1つのIDあたり8bitで設定 • 優先度は0が最高、255が最低 •
例:割り込みIDがmの割り込み優先度を最高にする ◦ GICD_PRIORITYR[ m / 4 ] &= ~(0xff << ((m mod 4) * 8)) ◦ (GICD_PRIORITYRの型はuint32_t) 42 31 0 Priority Priority Priority Priority 8|7 16|15 24|23
GICv2の初期設定(non-secure, Pi 4の場合) • GICD_TYPERで割り込みIDの最大値を調べる • GICD_ISENABLERで割り込みを有効するIDを設定 • GICD_PRIORITYRで割り込み優先度を設定 •
GICD_ITARGETSRで送り先プロセッサ設定 • GICD_CTLRでDistributorを有効化 • GICC_CTLRで割り込みを許可するグループを設定 43
• 割り込みルーティング先プロセッサ(複数可らしい)を指定するレジスタ • 2の冪数で指定する • 例:割り込みIDがmの割り込みをプロセッサxに送る ◦ GICD_ITARGETSR[ m /
4 ] |= (1 << x) << ((m mod 4) * 8) ◦ (GICD_ITARGETSRの型はuint32_t, レジスタ内はクリアされてるものとする ) GICD_ITARGETSRで送り先プロセッサ設定 44 31 0 CPU targets CPU targets CPU targets CPU targets 8|7 16|15 24|23
GICv2の初期設定(non-secure, Pi 4の場合) • GICD_TYPERで割り込みIDの最大値を調べる • GICD_ISENABLERで割り込みを有効するIDを設定 • GICD_PRIORITYRで割り込み優先度を設定 •
GICD_ITARGETSRで送り先プロセッサ設定 • GICD_CTLRでDistributorを有効化 • GICC_CTLRで割り込みを許可するグループを設定 45
GICD_CTLRでDistributorを有効化 • 有効化するとCPU Interfaceに割り込みが送られるようになる • non-secure時は最下位ビットを1にするとDistributorが有効化 46
GICv2の初期設定(non-secure, Pi 4の場合) • GICD_TYPERで割り込みIDの最大値を調べる • GICD_ISENABLERで割り込みを有効するIDを設定 • GICD_PRIORITYRで割り込み優先度を設定 •
GICD_ITARGETSRで送り先プロセッサ設定 • GICD_CTLRでDistributorを有効化 • GICC_CTLRで割り込みを許可するグループを設定 47
GICC_CTLRで割り込みを許可するグループを設定 • 一部レジスタアクセス時の挙動やIRQ, FIQのバイパス設定、特定グループの割り 込み有効化ができるレジスタ • Pi4の場合は最下位ビットのEnableGrp1を1にすると割り込みがプロセッサに送ら れる 48
コントローラ設定コード • GICDを停止 • 割り込みID数を確認 • UART割り込みを有効化 • 優先度を最高(0)に設定 •
宛先プロセッサを0に設定 • GICCを有効化 • GICDを有効化 49
Pi4での割り込み処理(発生から復帰まで) 50 レジスタ保存 レジスタ復旧 割り込みベクタ IRQ GIC:割り込みID確認 割り込み処理 割り込みハンドラ GIC:割り込み終了
eret
Pi4での割り込み処理(発生から復帰まで) 51 レジスタ保存 レジスタ復旧 割り込みベクタ IRQ GIC:割り込みID確認 割り込み処理 割り込みハンドラ GIC:割り込み終了
eret
• GICC_IARで最優先割り込みIDを取得 • 割り込みを処理 • GICC_IARの値をGICC_EOIRに書いて割り込みを完了 GICv2の割り込み処理手順(non-secure) 52
• GICC_IARで最優先割り込みIDを取得 • 割り込みを処理 • GICC_IARの値をGICC_EOIRに書いて割り込みを完了 GICv2の割り込み処理手順(non-secure) 53
GICC_IARで最優先割り込みIDを取得 • 現在入っている最も優先度の高い割り込みIDが得られるレジスタ • このレジスタを読んで適切な割り込み処理を呼び出す 54 Interrupt ID CPU ID
Reserved 13|12 0 10|9
• GICC_IARで最優先割り込みIDを取得 • 割り込みを処理 ◦ 割愛 • GICC_IARの値をGICC_EOIRに書いて割り込みを完了 GICv2の割り込み処理手順(non-secure) 55
• GICC_IARで最優先割り込みIDを取得 • 割り込みを処理 • GICC_IARの値をGICC_EOIRに書いて割り込みを完了 GICv2の割り込み処理手順(non-secure) 56
GICC_EOIRで最優先割り込みIDを取得 • 割り込みIDを書き込むと、その割り込み処理を完了できる • GICC_IARで読んだ内容をそのまま書き込めば良い 57 Interrupt ID CPU ID
Reserved 13|12 0 10|9
割り込み処理 • GICC_IARで割り込みID取得 • UART割り込みか確認 • UART受信&送信 • UART割り込みフラグクリア •
GICC_EOIRで割り込み完了 58
デモ 59
まとめ 60
まとめ • Pi 4から割り込みコントローラがGICv2(GIC-400)になった • Pi 4上でGICv2の割り込み制御を行う方法を解説した ◦ Pi4ではnon-secureモードの設定を行えば良い ◦
(dtsに書かれたSPIのID + 32)がGICでのInterrupt IDになる 61