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
試して理解 ARMv6 MMU/kernelvm hokuriku4
Search
Toshifumi NISHINAGA
November 10, 2018
Programming
4
1.2k
試して理解 ARMv6 MMU/kernelvm hokuriku4
Toshifumi NISHINAGA
November 10, 2018
Tweet
Share
More Decks by Toshifumi NISHINAGA
See All by Toshifumi NISHINAGA
BareMetalで遊ぶRaspberry Pi 5 PCIe編/KernelVM Tokyo17
tnishinaga
0
1.2k
probe-rsの紹介と最近の貢献紹介/CELF-02-03
tnishinaga
1
260
SecurityCamp2023基板作るコース講義資料/Security Camp 2023 Lecture Materials
tnishinaga
8
2.3k
RP2040のPIOを使う話/KernelVM Hokuriku 6
tnishinaga
3
1k
JTAGでArmプロセッサをデバッグする方法のつづき/KernelVM_Tokyo16
tnishinaga
0
330
CMSIS-DAPの概要と使い方/KernelVM Online5
tnishinaga
0
1.5k
JTAGでarmプロセッサをデバッグする話/KernelVM Online4
tnishinaga
4
2.8k
ARM入門/arm introduction
tnishinaga
15
11k
俺の仮想マシンルーターがこんなに遅いはずはない/ KernelVM online 1
tnishinaga
0
2.6k
Other Decks in Programming
See All in Programming
iOSの隠されたAPIを解明し、開発効率を向上させる方法/iOSDC24
noppefoxwolf
2
120
大公開!iOS開発の悩みトップ5 〜iOSDC Japan 2024〜
ryunakayama
0
180
Mastering AsyncSequence - 使う・作る・他のデザインパターン(クロージャ、Delegate など)から移行する
treastrain
3
1.4k
Scala におけるコンパイラエラーとの付き合い方
chencmd
1
160
ECMAScript仕様を読むのに必要な知識 - ダイジェスト版
syumai
4
2.5k
Modular Monolith Go Server with GraphQL Federation + gRPC
110y
1
550
Go Code Generation at newmo / 2024-08-27 #newmo_layerx_go
genkey6
0
520
『ドメイン駆動設計をはじめよう』中核の業務領域
masuda220
PRO
5
850
数値を文字列に整形する際の落とし穴とその解決策(iOSDC2024 ルーキーズLT) / iOSDC Japan 2024 Formatting Floating-Point Numbers
glassfiber
0
250
Ebitengineの1vs1ゲーム WebRTCの活用
ponyo877
0
340
私の考える初学者がBlazorできるまでの学習方法
tomokusaba
1
250
開発を加速する共有Swift Package実践
elmetal
PRO
0
300
Featured
See All Featured
Save Time (by Creating Custom Rails Generators)
garrettdimon
PRO
22
580
実際に使うSQLの書き方 徹底解説 / pgcon21j-tutorial
soudai
165
48k
Fight the Zombie Pattern Library - RWD Summit 2016
marcelosomers
230
17k
StorybookのUI Testing Handbookを読んだ
zakiyama
25
5k
Six Lessons from altMBA
skipperchong
26
3.3k
Building a Scalable Design System with Sketch
lauravandoore
458
32k
Principles of Awesome APIs and How to Build Them.
keavy
125
16k
How GitHub Uses GitHub to Build GitHub
holman
472
290k
Intergalactic Javascript Robots from Outer Space
tanoku
268
26k
Building Applications with DynamoDB
mza
89
5.9k
Sharpening the Axe: The Primacy of Toolmaking
bcantrill
33
1.7k
Debugging Ruby Performance
tmm1
72
12k
Transcript
試して理解 ARMv8 MMU Toshifumi NISHINAGA(@tnishinaga) 2018/11/10 KernelVM Hokuriku@4 コードはこちら https://github.com/tnishinaga/kernelvm_hokuriku4
v6 まにあわなかった
$ who • Name: Toshifumi NISHINAGA • Attribute: Hobby embedded
programmer • Activities: ◦ Google Summer of Code 2016(Linux foundation) ▪ https://summerofcode.withgoogle.com/archive/2016/projects/661784 9892175872/ ▪ Porting Linux to ARM Cotex-M7 microcontroller. ◦ U-Boot contributor(not active recently…) • link: ◦ https://github.com/tnishinaga ◦ https://speakerdeck.com/tnishinaga 3
ARMとは • 今最もアツい(個人の感想です) ARM社の RISC CPU • 組み込み機器で多く利用 • 最近はサーバー向けにも進出
• 今買うならSynQuacerってマシン がおすすめ 4
今回のお話 • MMUの概要と実際の設定方法をご紹介 5
もくじ • MMUの概要 ◦ MMUとは ▪ アクセス制御 ▪ アドレス変換 ◦
実践:アクセス制御 • 実践:MMUを動かしてみる ◦ アドレス変換の仕組み ◦ アドレス変換テーブル ◦ MMU Discriptor • 実践:アドレス変換 6
もくじ • MMUの概要 ◦ MMUとは ▪ アクセス制御 ▪ アドレス変換 ◦
実践:アクセス制御 • 実践:MMUを動かしてみる ◦ アドレス変換の仕組み ◦ アドレス変換テーブル ◦ MMU Discriptor • 実践:アドレス変換 7
Memory Management Unit(MMU)とは • 仮想メモリの管理やアクセス制御などを行うユニット • Linuxなどの最近の一般的なOSは基本的にMMUがあること前提 ◦ NOMMU Linuxもあるけどできることがかなり限られる
▪ forkが使えないなど ▪ (MMUがないとアドレス空間が分けられないから?) 8
MMUがあるとできること • 読み書き実行アクセス制御 • メモリアドレス変換(VA -> PA) • その他(キャッシュ可否など。説明skip) 9
読み書き実行アクセス制御 • 特定メモリ領域の読み書き実行可否設定ができる • セキュリティ対策に使える。 • • 例:スタックのメモリを実行不可にする ◦ スタックにコードを置いて実行する攻撃を防げる
▪ Buffer over flow攻撃など 10
アドレス変換 • 仮想アドレス(Virtual Address, VA)を物理アドレス(Physical Address, PA)に変換する機能 • プロセスごとに独立したメモリ空間を用意できる ◦
プログラマやコンパイラがプログラムがどのアドレスに配置されるか気にしなく て良い ◦ メモリ空間がプロセスごとに分かれているので、他プロセスのデータにアクセス はできない 11 proc1の メモリ空間 proc1 proc2の メモリ空間 proc2 仮想メモリ 0x00 0x00 0xff.. 0xff.. proc1の メモリ空間 proc2の メモリ空間 0x00 0xff.. 物理メモリ
もくじ • MMUの概要 ◦ MMUとは ▪ アクセス制御 ▪ アドレス変換 ◦
実践:アクセス制御 • 実践:MMUを動かしてみる ◦ アドレス変換の仕組み ◦ アドレス変換テーブル ◦ MMU Discriptor • 実践:アドレス変換 12
実践: アクセス制御 • 確かめたいこと ◦ メモリに対するアクセス制御ができることを調べたい • 検証方法 ◦ 実行不可としたスタック上にコードを入れて動かしてみる
◦ /proc/self/maps を覗いてstackの読み書き実行フラグ状態を調べる • 期待する動作 ◦ 実行フラグがOFFなっている ◦ SEGVする 13
検証コード • stackに置くコード ◦ https://github.com/tnishinaga/kernelvm_hokuriku4/blob/master/stack_exe c_test/ret1.S • stackのメモリ属性を参照して、stackのコードを実行するコード ◦ https://github.com/tnishinaga/kernelvm_hokuriku4/blob/master/stack_exe
c_test/stack_exec.c 14
実行結果 15 pi@raspberrypi:~/kernelvm_hokuriku/stack_exec_test $ ./stack_noexec.elf buf address: 0xbeaf3490 bead3000-beaf4000 rw-p
00000000 00:00 0 [stack] ret1 addr: 0x106d0 ret1_fin addr: 0x106d8 Segmentation fault 実行権限xがつ いてない
結果 • 実行不可としたスタック上でコードが動かないことを確認した • メモリの属性も実行不可となっているのを確認した 16
Tips: stack実行可否の制御 • 一部例外を除いてstackは実行不可になっている • 例外: ◦ コンパイルオプションに-z execstackをつける(リンカのお仕事) ◦
-z noexecstack をつけずに.cと.Sの混ぜてビルドする ▪ 参考: https://qiita.com/rarul/items/e1920e7ae5d5a28eec03 17
もくじ • MMUの概要 ◦ MMUとは ▪ アクセス制御 ▪ アドレス変換 ◦
実践:アクセス制御 • 実践:MMUを動かしてみる ◦ アドレス変換の仕組み ◦ アドレス変換テーブル ◦ MMU Discriptor • 実践:アドレス変換 18
MMUを動かしてみる ここからはARMv6 MMU(VMSAv6)を実際に設定しつつ、MMUの動作を手を 動かしながら学びます 簡単のため、設定するMMUの仕様は以下 • 変換レベルは1段 • ストレートマップ(VA =
PA) • 解説は基本アドレス変換のみに絞る。その他はskip 19
アドレス変換の仕組み • アドレス変換は変換表を見て対応するアドレスに変換してる • アドレス変換はある程度まとまった単位で行われる ◦ 1byteづつで変換するとメモリと同じサイズの変換テーブルが必要 • ARMではVAの上位n bit(変換段数で変化)を使って変換
• それ以下はVA = PAとしてアドレスを作る CCCC 0xAA CCCC 0xBB 0xBB 0xAA 0x00 0x.. 変換テーブル Virtual Address Physical Address 20
アドレス変換テーブル • アドレス変換はアドレス変換テーブルを参照して行われる • 変換テーブルはメモリ上に置かれる • 場所をTTBRレジスタにセットするとアドレス変換に使われる ◦ TTBR0とTTBR1の2つあるが、簡単のためTTBR0を利用 メモリ
変換テーブル 0xAA 0xAA TTBR0 21
TTBR0への変換テーブル設定コード • TTBR0はシステムレジスタなのでMCR命令で書き込む • テーブルのアドレスは16KiB alignである必要がある • ARMv8前のシステムレジスタ指定は難しい ◦ マニュアルから探すしか無い
◦ http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0211k/Bhcbiigc.html 22 static inline void set_ttbr0(uint32_t *pagetable) { __asm__ volatile("mcr p15, 0, %[p], c2, c0, 0" : : [p] "r" (pagetable) : ); }
MMU Descriptor • 変換テーブルにはMMU Descriptorが詰まっている • 変換するアドレスの情報を記す • descriptorの形式は複数ある。1段めには以下の2種が作れる ◦
セクション ◦ ページテーブル • 簡単のために今回はセクションを使う ◦ 1段で変換できるので簡単 23
MMU Descriptorのセクション • セクションはVAの上位12bitを変換する ◦ 1セクション1MBを変換できる ◦ 4096エントリで全メモリを変換可能 • •
ディスクリプタ構造の詳細は以下参考 ◦ http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0301h/ch06s12s02.html ◦ Figure 6.12. Translation for a 1MB section, ARMv6 format 24
セクション作成コード void vmsav6_set_mmu_section( uint32_t va, uint32_t pa, uint32_t options )
{ uint32_t idx = va >> 20; uint32_t entry = (pa & 0xfff00000) | (options & 0x7ffc) | VMSAv6_SECTION_FLAG; ttbr0_lv1_section[idx] = entry; return; } 25 void create_straight_section(void) { uint32_t entry = 0; uint32_t peri_base = 0x10000000; uint32_t entry_peri_base = peri_base >> 20; for (entry = 0; entry < 4096; entry++) { uint32_t addr = entry << 20; vmsav6_set_mmu_section( addr, addr, VMSAv6_SECTION_AP_FULLACCESS ); } }
MMUの有効化 • ARMv6ではControl Registerを制御してMMUを有効化する • 1bit目を1にするとMMUが有効になる • 参考 ◦ http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0301h/Bgbciiaf.html
• 26 図はARM1176JZF-S Technical Reference Manual(Revision: r0p7)のFigure 3.26から引用 http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0301h/Bgbciiaf.html
MMUを有効化するコード static inline void enable_mmu(void) { volatile uint32_t mmu_en_mask =
0; mmu_en_mask |= 1; // M = 1 mmu_en_mask |= 1 << 2; // C = 1 mmu_en_mask |= 1 << 16; // I = 1 __asm__ volatile( "mrc p15, 0, r0, c1, c0, 0;" "orr r0, r0, %[x];" "mcr p15, 0, r0, c1, c0, 0;" : : [x] "r" (mmu_en_mask) : "r0" ); } 27
その他 • MMU有効化前に以下も行う必要があるが説明省略 ◦ キャッシュのinvalidate ◦ TLBのinvalidate ◦ ドメインの設定 28
実践: MMUの有効化 • 確かめたいこと ◦ これまでの手順でMMUの有効化ができることを確認する • 検証方法 ◦ MMUを有効化してもコードの実行が止まらなければOK
▪ MMUの設定に失敗すると落ちるので…… 29
コード int main(void) { set_vector_table(0); pl011_init(STDIO, UART_CLOCK); my_puts(STDIO, "HelloWorld!\n"); init_mmu();
// MMU有効化 my_puts(STDIO, "Hello MMU World!\n"); return 0; } 30 全コードはこちら https://github.com/tnishinaga/kernelvm_hokuriku4/tree/master/mmu_enable_test 設定が正しければこの文が出てくる
実行結果 tnishinaga@tx230> ./run_qemu.sh HelloWorld! Hello MMU World! 31
結果 • MMUを有効化はうまく行った • でもVA=PAだと効果がよくわからない • もっとわかりやすい実験はできないものか? ◦ 次の実践でやろう! 32
もくじ • MMUの概要 ◦ MMUとは ▪ アクセス制御 ▪ アドレス変換 ◦
実践:アクセス制御 • 実践:MMUを動かしてみる ◦ アドレス変換の仕組み ◦ アドレス変換テーブル ◦ MMU Discriptor • 実践:アドレス変換 33
実践: アドレス変換 • 確かめたいこと ◦ VAに対応するPAが自由に変換できることを確認する • 検証方法 ◦ メモリ上のアドレス0x00500000
と 0x00600000 をMMUの機能を使って入れ 替えてみる ◦ 予めそれぞれのアドレスに値を入れ、MMU有効後に値を確認する 34 VA 0x00500000 0x00600000 PA 0x00500000 0x00600000 0x00500000 0x00600000
コード *addr_0x00500000 = 0x00500000; *addr_0x00600000 = 0x00600000; (skip) uint32_t tmp
= ttbr0_lv1_section[5]; ttbr0_lv1_section[5] = ttbr0_lv1_section[6]; ttbr0_lv1_section[6] = tmp; init_mmu(); my_puts(STDIO, "\nMMU enabled:\n"); show_5_6(); // 0x00500000と0x00600000の中身を表示 35 全コードはこちら https://github.com/tnishinaga/kernelvm_hokuriku4/blob/master/mmu_exchange_test Entry 5と6を入れ替えて PAとVAの対応を入れ替える
実行結果 MMU disabled: 0x00500000 = 00500000 0x00600000 = 00600000 Create
straight section Exchange entry 5 with 6 MMU enabled: 0x00500000 = 00600000 0x00600000 = 00500000 36 入れ替わった
結果 • 変換テーブルを入れ替えることでVAとPAの対応を変更できることが分かっ た 37
まとめ • MMUはアドレス変換とアクセス制御の機能を提供する • 昨今のOSには無くてはならない機能 • ARMのMMU有効化は基本は以下の手順でできる ◦ セクション作成 ◦
変換テーブル登録 ◦ MMUのON 38