試して理解 ARMv6 MMU/kernelvm hokuriku4

試して理解 ARMv6 MMU/kernelvm hokuriku4

Bdd3fb3269e67bbc512f2530c409a926?s=128

Toshifumi NISHINAGA

November 10, 2018
Tweet

Transcript

  1. 2.

    $ 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
  2. 5.

    もくじ • MMUの概要 ◦ MMUとは ▪ アクセス制御 ▪ アドレス変換 ◦

    実践:アクセス制御 • 実践:MMUを動かしてみる ◦ アドレス変換の仕組み ◦ アドレス変換テーブル ◦ MMU Discriptor • 実践:アドレス変換 6
  3. 6.

    もくじ • MMUの概要 ◦ MMUとは ▪ アクセス制御 ▪ アドレス変換 ◦

    実践:アクセス制御 • 実践:MMUを動かしてみる ◦ アドレス変換の仕組み ◦ アドレス変換テーブル ◦ MMU Discriptor • 実践:アドレス変換 7
  4. 10.

    アドレス変換 • 仮想アドレス(Virtual Address, VA)を物理アドレス(Physical Address, PA)に変換する機能 • プロセスごとに独立したメモリ空間を用意できる ◦

    プログラマやコンパイラがプログラムがどのアドレスに配置されるか気にしなく て良い ◦ メモリ空間がプロセスごとに分かれているので、他プロセスのデータにアクセス はできない 11 proc1の メモリ空間 proc1 proc2の メモリ空間 proc2 仮想メモリ 0x00 0x00 0xff.. 0xff.. proc1の メモリ空間 proc2の メモリ空間 0x00 0xff.. 物理メモリ
  5. 11.

    もくじ • MMUの概要 ◦ MMUとは ▪ アクセス制御 ▪ アドレス変換 ◦

    実践:アクセス制御 • 実践:MMUを動かしてみる ◦ アドレス変換の仕組み ◦ アドレス変換テーブル ◦ MMU Discriptor • 実践:アドレス変換 12
  6. 12.

    実践: アクセス制御 • 確かめたいこと ◦ メモリに対するアクセス制御ができることを調べたい • 検証方法 ◦ 実行不可としたスタック上にコードを入れて動かしてみる

    ◦ /proc/self/maps を覗いてstackの読み書き実行フラグ状態を調べる • 期待する動作 ◦ 実行フラグがOFFなっている ◦ SEGVする 13
  7. 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がつ いてない
  8. 17.

    もくじ • MMUの概要 ◦ MMUとは ▪ アクセス制御 ▪ アドレス変換 ◦

    実践:アクセス制御 • 実践:MMUを動かしてみる ◦ アドレス変換の仕組み ◦ アドレス変換テーブル ◦ MMU Discriptor • 実践:アドレス変換 18
  9. 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) : ); }
  10. 22.

    MMU Descriptor • 変換テーブルにはMMU Descriptorが詰まっている • 変換するアドレスの情報を記す • descriptorの形式は複数ある。1段めには以下の2種が作れる ◦

    セクション ◦ ページテーブル • 簡単のために今回はセクションを使う ◦ 1段で変換できるので簡単 23
  11. 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
  12. 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 ); } }
  13. 25.

    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
  14. 26.

    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
  15. 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 設定が正しければこの文が出てくる
  16. 32.

    もくじ • MMUの概要 ◦ MMUとは ▪ アクセス制御 ▪ アドレス変換 ◦

    実践:アクセス制御 • 実践:MMUを動かしてみる ◦ アドレス変換の仕組み ◦ アドレス変換テーブル ◦ MMU Discriptor • 実践:アドレス変換 33
  17. 33.

    実践: アドレス変換 • 確かめたいこと ◦ VAに対応するPAが自由に変換できることを確認する • 検証方法 ◦ メモリ上のアドレス0x00500000

    と 0x00600000 をMMUの機能を使って入れ 替えてみる ◦ 予めそれぞれのアドレスに値を入れ、MMU有効後に値を確認する 34 VA 0x00500000 0x00600000 PA 0x00500000 0x00600000 0x00500000 0x00600000
  18. 34.

    コード *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の対応を入れ替える
  19. 35.

    実行結果 MMU disabled: 0x00500000 = 00500000 0x00600000 = 00600000 Create

    straight section Exchange entry 5 with 6 MMU enabled: 0x00500000 = 00600000 0x00600000 = 00500000 36 入れ替わった