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
KOZOS/RasPi移植してみた
Search
Toshifumi NISHINAGA
July 02, 2017
Programming
0
3.6k
KOZOS/RasPi移植してみた
2017/07/02に第7回自作OSもくもく会で発表したKOZOSをRasPiに移植した発表資料です。
Toshifumi NISHINAGA
July 02, 2017
Tweet
Share
More Decks by Toshifumi NISHINAGA
See All by Toshifumi NISHINAGA
BareMetalで遊ぶRaspberry Pi 5 PCIe編/KernelVM Tokyo17
tnishinaga
0
1.9k
probe-rsの紹介と最近の貢献紹介/CELF-02-03
tnishinaga
1
390
SecurityCamp2023基板作るコース講義資料/Security Camp 2023 Lecture Materials
tnishinaga
8
2.5k
RP2040のPIOを使う話/KernelVM Hokuriku 6
tnishinaga
3
1.3k
JTAGでArmプロセッサをデバッグする方法のつづき/KernelVM_Tokyo16
tnishinaga
0
420
CMSIS-DAPの概要と使い方/KernelVM Online5
tnishinaga
0
1.8k
JTAGでarmプロセッサをデバッグする話/KernelVM Online4
tnishinaga
4
3.2k
ARM入門/arm introduction
tnishinaga
14
12k
俺の仮想マシンルーターがこんなに遅いはずはない/ KernelVM online 1
tnishinaga
0
2.8k
Other Decks in Programming
See All in Programming
CSS Linter による Baseline サポートの仕組み
ryo_manba
1
150
たのしいSocketのしくみ / Socket Under a Microscope
coe401_
8
1.2k
pylint custom ruleで始めるレビュー自動化
shogoujiie
0
150
密集、ドキュメントのコロケーション with AWS Lambda
satoshi256kbyte
1
210
CDK開発におけるコーディング規約の運用
yamanashi_ren01
2
250
Honoをフロントエンドで使う 3つのやり方
yusukebe
7
3.5k
パスキーのすべて ── 導入・UX設計・実装の紹介 / 20250213 パスキー開発者の集い
kuralab
3
880
5分で理解する SOLID 原則 #phpcon_nagoya
shogogg
1
300
Djangoアプリケーション 運用のリアル 〜問題発生から可視化、最適化への道〜 #pyconshizu
kashewnuts
1
260
React 19アップデートのために必要なこと
uhyo
8
1.5k
Open source software: how to live long and go far
gaelvaroquaux
0
660
ML.NETで始める機械学習
ymd65536
0
230
Featured
See All Featured
Art, The Web, and Tiny UX
lynnandtonic
298
20k
Creating an realtime collaboration tool: Agile Flush - .NET Oxford
marcduiker
27
1.9k
The Myth of the Modular Monolith - Day 2 Keynote - Rails World 2024
eileencodes
21
2.5k
Music & Morning Musume
bryan
46
6.4k
Java REST API Framework Comparison - PWX 2021
mraible
29
8.4k
Building Better People: How to give real-time feedback that sticks.
wjessup
367
19k
Refactoring Trust on Your Teams (GOTO; Chicago 2020)
rmw
33
2.8k
Dealing with People You Can't Stand - Big Design 2015
cassininazir
366
25k
Large-scale JavaScript Application Architecture
addyosmani
511
110k
Building an army of robots
kneath
303
45k
Making the Leap to Tech Lead
cromwellryan
133
9.1k
Save Time (by Creating Custom Rails Generators)
garrettdimon
PRO
29
1k
Transcript
KOZOS/RasPi 移植してみた Toshifumi NISHINAGA(@tnishinaga) 2017/07/02 第7回自作OSもくもく会
自己紹介 • なまえ ◦ Toshifumi NISHINAGA(@tnishinaga) • さいきんやったこと ◦ セキュリティキャンプ講師
(2016 - 2017) ◦ Google Sumber of Code 2016(Linux Foundation) ▪ STM32F7マイコンでブートローダー (U-Boot)移植してLinux動くようにしました • すきなこと ◦ 組み込みいじり(ARM64勉強中) ◦ アニメ、ゲーム ◦ ロードバイク 2
cpsie if @ IRQ, FIQ interrupt enable 3
目次 • KOZOSとは • 移植作戦 4
KOZOSとは • 非常に小さな教育用組み込みOS ◦ ブートローダー&OS本体で2700行程度(書籍版) • 対応アーキテクチャ ◦ H8(書籍版) ◦
移植版:PowerPC/SH2/Arduino(AVR) • 持っている機能 ◦ スレッド管理 ◦ メモリ管理 ◦ I/O管理 5
KOZOSとは • 非常に小さな教育用組み込みOS ◦ ブートローダー&OS本体で2700行程度(書籍版) • 対応アーキテクチャ ◦ H8(書籍版) ◦
移植版:PowerPC/SH2/Arduino(AVR) • 持っている機能 ◦ スレッド管理 ◦ メモリ管理 ◦ I/O管理 6
Raspberry Piでも動かしたいっ!! 7
移植しちゃいました • URL ◦ https://github.com/tnishinaga/kozos-rpi • 作業期間 ◦ 2017年4月に2週間程度 ◦
(1日1時間程度作業) • とりあえず以下は動く ◦ スレッドの切り替え動作 ◦ シリアル出力 8
移植作戦 • 方針 ◦ とりあえず少しずつ動くようにしていく • 手順 ◦ 全体をなんとなく把握する ◦
ARMクロス環境でビルド(だけ)できるようにする ◦ JTAGデバッグできるようにする ◦ main関数まで動くようにする ◦ 割り込みハンドラを作ってみる ◦ ディスパッチャを作ってみる ◦ Serialを動くようにする ◦ バグ潰し 9
移植作戦 • 方針 ◦ とりあえず少しずつ動くようにしていく • 手順 ◦ 全体をなんとなく把握する ◦
ARMクロス環境でビルド(だけ)できるようにする ◦ JTAGデバッグできるようにする ◦ main関数まで動くようにする ◦ 割り込みハンドラを作ってみる ◦ ディスパッチャを作ってみる ◦ Serialを動くようにする ◦ バグ潰し 10
全体をなんとなく把握する • 「12ステップで作る 組み込みOS自作入門」を読む • コードをなんとなく眺める 画像は以下より引用 http://kozos.jp/books/makeos/ 11
なんとなく把握したこと • ブートローダーとOS本体(KOZOS)がある • 起動時はFLASHに書かれたブートローダーが立ち上がる • ブートローダーはシリアル経由でKOZOSをRAM読み込む ◦ ※直接KOZOS起動するようにすればブートローダーは必要なさそう •
KOZOSにはスレッドと優先度スケジューリング、メモリ管理がある • KOZOSのコンテクストスイッチは以下の理由で起こる ◦ シリアル受信などの外部割り込み ◦ システムコール関数呼び出しによるソフトウェア割り込み ◦ 謎の例外 • echoコマンドが動けばKOZOSの移植は完了 ◦ シリアル割り込みによるスレッド切り替えの動作が確認できる 12
移植作戦 • 方針 ◦ とりあえず少しずつ動くようにしていく • 手順 ◦ 全体をなんとなく把握する ◦
ARMクロス環境でビルド(だけ)できるようにする ◦ JTAGデバッグできるようにする ◦ main関数まで動くようにする ◦ 割り込みハンドラを作ってみる ◦ ディスパッチャを作ってみる ◦ Serialを動くようにする ◦ バグ潰し 13
ARMクロス環境でビルド(だけ)できるようにする • とりあえずARMのクロスコンパイラでビルドが全部走るようにする • Makefileを書き換える ◦ ARCHの部分(クロスコンパイラのprefix)をarm-none-eabiにする ◦ CFLAGSのarm gccでは無いオプションを消す
• アセンブリ部はコメントアウトしたり、nopに変えたり • コミットはこのあたり ◦ https://github.com/tnishinaga/kozos-rpi/commit/0f11825d4e81f2af3c311d595292d6617d32 b7a1 14
移植作戦 • 方針 ◦ とりあえず少しずつ動くようにしていく • 手順 ◦ 全体をなんとなく把握する ◦
ARMクロス環境でビルド(だけ)できるようにする ◦ JTAGデバッグできるようにする ◦ main関数まで動くようにする ◦ 割り込みハンドラを作ってみる ◦ ディスパッチャを作ってみる ◦ Serialを動くようにする ◦ バグ潰し 15
JTAGデバッグできるようにする • デバッグできないと辛いのでJTAGデバッグできるようにする • RasPiのJTAGは特定のGPIOポートのモードをAlternativeモードにして有効化する • JTAGデバッグソフトはOpenOCDを利用 • JTAGアダプタは以下を利用 ◦
http://akizukidenshi.com/catalog/g/gM-06545/ • コミットはこのあたり ◦ https://github.com/tnishinaga/kozos-rpi/commit/0 31f8dcd9a39ba41e9d7e6fa5fa4387b9314948f ◦ https://github.com/tnishinaga/kozos-rpi/commit/5 de931245aec2a55b99bee2740bb789a11049615 16
動作確認 • JTAGアダプタとRaspberry Piを接続する ◦ 接続先等は「BareMetalで遊ぶ RaspberryPi」等を参照 • OpenOCDを立ち上げる ◦
openocd -f raspi_with_ngxtech.cfg • GDBを立ち上げる ◦ arm-none-eabi-gdb kozos.elf • GDBをOpenOCDのGDB Serverと接続する ◦ target remote localhost:3333 • 一旦プログラムを走らせてから止める ◦ continue してから Ctrl + C • プログラムをロードして実行再開し、動けばOK ◦ load して continue 17
移植作戦 • 方針 ◦ とりあえず少しずつ動くようにしていく • 手順 ◦ 全体をなんとなく把握する ◦
ARMクロス環境でビルド(だけ)できるようにする ◦ JTAGデバッグできるようにする ◦ main関数まで動くようにする ◦ 割り込みハンドラを作ってみる ◦ ディスパッチャを作ってみる ◦ Serialを動くようにする ◦ バグ潰し 18
main関数まで動くようにする • リンカスクリプトを修正してramの先頭を0x8000にする ◦ 0x8000はRasPi起動時のエントリポイント • スタートアップコード(_start)を書く ◦ CPUのモードを設定する ▪
cps命令で割り込み不可にする ◦ BSSの初期化をする ◦ スタックポインタの初期値を設定する ▪ RasPiはGPUがRAMがマップされているアドレスの末尾から 64MB使うのに注意 ◦ main関数を呼ぶ ◦ sleepさせる ▪ ARMの場合はwfi(割り込み待ち)でsleepできる 19
動作確認 • gdbでmain関数にbreakpointを仕込む ◦ break main • プログラムをloadし、breakpointまでたどり着くか調べる 20
移植作戦 • 方針 ◦ とりあえず少しずつ動くようにしていく • 手順 ◦ 全体をなんとなく把握する ◦
ARMクロス環境でビルド(だけ)できるようにする ◦ JTAGデバッグできるようにする ◦ main関数まで動くようにする ◦ 割り込みハンドラを作ってみる ◦ ディスパッチャを作ってみる ◦ Serialを動くようにする ◦ バグ潰し 21
割り込みハンドラ(だけ)を作ってみる • KOZOSで使う割り込み要因のハンドラだけ作る ◦ IRQ割り込み(外部割り込み) ◦ SVC割り込み(ソフトウェア割り込み) • 割り込みハンドラに飛ばすベクタテーブルを作成する ◦
IRQとSVC以外はsleepするようにする 22
ベクタテーブル • CPUが例外発生時に適切な例外ハンドラに処理を移すための命令やアドレス 等を記録しておくテーブル • 基本的にはメモリの先頭(0x00000000)に配置する Reset Undefined SVC Prefetch
Abort Data Abort Reserved IRQ FIQ 0x00 0x04 0x08 0x0C 0x10 0x14 0x18 0x1C 23
• ベクタテーブルは再配置が必要 ◦ RasPiのプログラムは0x8000に読み込まれるので • スタートアップコード内でプログラムの何処か に置かれたVector Tableをメモリの先頭にコ ピーする ◦
set_vector_table関数が担当 ベクタテーブルの設置 _start Vector Table メモリ 0x0000 0x8000 24
一般的なIRQ割り込みの動き Vector Table main IRQ Handler IRQ interrupt 1. ベクタテーブルの
IRQ欄の命令を実行 2. IRQハンドラに飛ぶ 3. 割り込み処理が終 わったら元の場所に戻る メモリ 25
移植作戦 • 方針 ◦ とりあえず少しずつ動くようにしていく • 手順 ◦ 全体をなんとなく把握する ◦
ARMクロス環境でビルド(だけ)できるようにする ◦ JTAGデバッグできるようにする ◦ main関数まで動くようにする ◦ 割り込みハンドラを作ってみる ◦ ディスパッチャを作ってみる ◦ Serialを動くようにする ◦ バグ潰し 26
ディスパッチャを作ってみる • ディスパッチャ ◦ タスクやスレッドを切り替え CPU資源を与える機構のこと • KOZOSのディスパッチャ ◦ スレッド状態(現在のレジスタ値たち
)の保存 ▪ 割り込みハンドラ内で行う ◦ スレッド状態の復元 ▪ dispatch関数で行う 27
KOZOSのディスパッチャ(H8の場合) • スレッド状態の保存 ◦ 現在のスレッドのスタックにレジスタをすべて 保存 ◦ 割り込み要因とスタックポインタ(er7)の値(保 存したスレッド状態の先頭アドレス)を interrupt関数に渡す
• スレッド状態の復元(dispatch関数) ◦ 与えられたスタックポインタの値をスタックポイ ンタ(er7)にセット ◦ スタックポインタからレジスタの状態を復元 レジスタ スタック レジスタ Push sp interrupt(type, sp) dispatch(sp) スタック レジスタ レジスタ Pop sp 28
ARM移植の課題 • ARMはバンクレジスタがあるためH8のように単一のスタックにスレッド状態を保存 するのが難しい 29
バンクレジスタ(レジスタバンク) • ARMには複数のCPUモードがある • 一部レジスタはCPUのモードが変わると勝手に退避される(バンク切り替え) ◦ この退避される一部レジスタのことをバンクレジスタという 図はhttp://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0211k/ch02s08s01.html より引用 30
割り込み応答とバンク切り替えの例 (SystemからIRQ) 1. SystemのCPSRがIRQのSPSRにコピーされ る 2. CPUモードを切り替える a. この例だとSystemからIRQへ 3.
バンクレジスタを切り替える a. SP, LR, SPSRがIRQのものになる 4. 割り込みを無効化する 5. PC(戻りアドレス)がIRQのLRにセットされる 6. PCに例外ベクタアドレスをセットする 31 R0 - R12 SP_sys LR_sys PC CPSR SPSR_sys System R0 - R12 SP_irq LR_irq PC CPSR SPSR_irq IRQ CPSR: CPUフラグ等の状態が入るレジスタ
割り込み応答とバンク切り替えの例 (SystemからIRQ) 1. SystemのCPSRがIRQのSPSRにコピーされ る 2. CPUモードを切り替える a. この例だとSystemからIRQへ 3.
バンクレジスタを切り替える a. SP, LR, SPSRがIRQのものになる 4. 割り込みを無効化する 5. PC(戻りアドレス)がIRQのLRにセットされる 6. PCに例外ベクタアドレスをセットする 32 R0 - R12 SP_sys LR_sys PC CPSR SPSR_sys System R0 - R12 SP_irq LR_irq PC CPSR SPSR_irq IRQ CPSR: CPUフラグ等の状態が入るレジスタ
割り込み応答とバンク切り替えの例 (SystemからIRQ) 1. SystemのCPSRがIRQのSPSRにコピーされ る 2. CPUモードを切り替える a. この例だとSystemからIRQへ 3.
バンクレジスタを切り替える a. SP, LR, SPSRがIRQのものになる 4. 割り込みを無効化する 5. PC(戻りアドレス)がIRQのLRにセットされる 6. PCに例外ベクタアドレスをセットする 33 R0 - R12 SP_sys LR_sys PC CPSR SPSR_sys System R0 - R12 SP_irq LR_irq PC CPSR SPSR_irq IRQ CPSR: CPUフラグ等の状態が入るレジスタ
割り込み応答とバンク切り替えの例 (SystemからIRQ) 1. SystemのCPSRがIRQのSPSRにコピーされ る 2. CPUモードを切り替える a. この例だとSystemからIRQへ 3.
バンクレジスタを切り替える a. SP, LR, SPSRがIRQのものになる 4. 割り込みを無効化する 5. PC(戻りアドレス)がIRQのLRにセットされる 6. PCに例外ベクタアドレスをセットする 34 R0 - R12 SP_sys LR_sys PC CPSR SPSR_sys System R0 - R12 SP_irq LR_irq PC CPSR SPSR_irq IRQ CPSR: CPUフラグ等の状態が入るレジスタ Change
割り込み応答とバンク切り替えの例 (SystemからIRQ) 1. SystemのCPSRがIRQのSPSRにコピーされ る 2. CPUモードを切り替える a. この例だとSystemからIRQへ 3.
バンクレジスタを切り替える a. SP, LR, SPSRがIRQのものになる 4. 割り込みを無効化する 5. PC(戻りアドレス)がIRQのLRにセットされる 6. PCに例外ベクタアドレスをセットする 35 R0 - R12 SP_sys LR_sys PC CPSR SPSR_sys System R0 - R12 SP_irq LR_irq PC CPSR SPSR_irq IRQ CPSR: CPUフラグ等の状態が入るレジスタ
割り込み応答とバンク切り替えの例 (SystemからIRQ) 1. SystemのCPSRがIRQのSPSRにコピーされ る 2. CPUモードを切り替える a. この例だとSystemからIRQへ 3.
バンクレジスタを切り替える a. SP, LR, SPSRがIRQのものになる 4. 割り込みを無効化する 5. PC(戻りアドレス)がIRQのLRにセットされる 6. PCに例外ベクタアドレスをセットする 36 R0 - R12 SP_sys LR_sys PC CPSR SPSR_sys System R0 - R12 SP_irq LR_irq PC: 0x18 CPSR SPSR_irq IRQ CPSR: CPUフラグ等の状態が入るレジスタ
ARM移植の課題 • ARMはバンクレジスタがあるためH8のように単一のスタックにスレッド状態を保存 するのが難しい ◦ そのままではソフトウェア割り込み (SVCモード)とIRQ割り込み(IRQモード)で異なるスタックに保存さ れてしまう ◦ 単一のスタックに保存するにはどうすれば?
37
ARM移植の課題 • ARMはバンクレジスタがあるためH8のように単一のスタックにスレッド状態を保存 するのが難しい ◦ そのままではソフトウェア割り込み (SVCモード)とIRQ割り込み(IRQモード)で異なるスタックに保存さ れてしまう ◦ 単一のスタックに保存するにはどうすれば?
38 A. KOZOSを常にSystemモードで動かす。 どちらの割り込みが入ってもすぐにSystemモードに切り替え、 Systemモードのスタックにスレッドを保存する (H8のようにスタックを一元化する)
KOZOS/RasPiのスレッド状態保存(IRQ割り込み) 1. R0-R3までをIRQのスタックに保存 2. SP_irqをR0に、SPSR_irqをR1に、LR_irqをR3に退避 3. cps命令でSystemモードに変更(バンク切り替えが起こる) 4. SP_sysをR2に保存(SP_bak) 5.
R3(LR_irq)をスタックにpush 6. R4-R12をスタックにpush 7. SP_irqに保存したR0-R3をR4-R7に復元 8. R0-R3をスタックにpush 9. R1(SPSR_irq)をスタックにpush 10. R2(SP_bak)とLR_sysをスタックにpush 39
保存された状態の構造 40 SPSR R0-R3 R4-R12 LR_irq SP_bak, LR_sys sp SP_bak
スレッド状態の復元 • SVCモードに切り替え、コンテキストを逆順にもどしていく • ldmfd sp!, {pc}^ のように^を付けるとCPUが勝手にSPSRからCPSRを復元してから PCの命令に戻ってくれる 41
移植作戦 • 方針 ◦ とりあえず少しずつ動くようにしていく • 手順 ◦ 全体をなんとなく把握する ◦
ARMクロス環境でビルド(だけ)できるようにする ◦ JTAGデバッグできるようにする ◦ main関数まで動くようにする ◦ 割り込みハンドラを作ってみる ◦ ディスパッチャを作ってみる ◦ Serialを動くようにする ◦ バグ潰し 42
シリアルが動くようにする • やるだけ。 • 「BareMetalで遊ぶ Raspberry Pi」のコードからMMIOのアドレス定義だけもらってく ると楽 • FIFOを切るとH8と同じ使い方ができるので移植しやすい
• IRQ割り込みの設定するのも忘れずに ◦ 割り込みに関する説明は「 BareMetalで遊ぶ Raspberry Pi」参照 43
移植作戦 • 方針 ◦ とりあえず少しずつ動くようにしていく • 手順 ◦ 全体をなんとなく把握する ◦
ARMクロス環境でビルド(だけ)できるようにする ◦ JTAGデバッグできるようにする ◦ main関数まで動くようにする ◦ 割り込みハンドラを作ってみる ◦ ディスパッチャを作ってみる ◦ Serialを動くようにする ◦ バグ潰し 44
ばぐつぶし • BSS領域のアライメントがあって無くてBSSクリアに失敗してた ◦ リンカスクリプトにアライン設定を追加 • GPUから謎のIRQ割り込みが入りまくり処理できずに落ちてた ◦ UART以外のIRQ割り込みをさせないよう修正 •
そのほか色々 ◦ 未処理 45
デモ echoコマンドがうごくよ 46
TODO • コミットを勉強用に整理する • コードをもう少しきれいにする • FBSD等のコンテクストスイッチを参考に改善する • 既知のバグを何とかする ◦
これはセキュキャン受講生がやってくれそう 47
まとめ • Raspberry PiでKOZOSが動くようになった • 使用するモードをSystemモードに限定してH8と動作をあわせて問題を解決 • とりあえずechoが動きます 48