Upgrade to Pro — share decks privately, control downloads, hide ads and more …

RustでOS開発はじめの一歩

nasa
December 19, 2023

 RustでOS開発はじめの一歩

nasa

December 19, 2023
Tweet

More Decks by nasa

Other Decks in Technology

Transcript

  1. RustでOS開発はじめの一歩
    UV Study: Rust LT会
    Dec. 19 2023 - nasa

    View full-size slide

  2. 発表のモチベ
    ● 最近RustでOSを書いている
    ● これまでCLIツールやライブラリをRustで実装してきた
    ● OSだと普段書いているコードが普通には動作しない
    ● どんな違いがあるのか話したい

    View full-size slide

  3. 動作環境
    ● platform: QEMU riscv64
    ● build target: riscv64gc-unknown-none-elf
    # .cargo/config.toml
    [build]
    target = "riscv64gc-unknown-none-elf"
    [target.riscv64gc-unknown-none-elf]
    runner = """
    qemu-system-riscv64 \
    -machine virt \
    -bios default \
    --no-reboot \
    -nographic \
    -serial mon:stdio \
    -kernel
    """

    View full-size slide

  4. ベアメタル環境
    ● OSによりプログラムがホスティングされない
    ● 自分の書いたプログラムを動かし始めるまでの環境がない
    ● time, io, fsなどOSの上に構成されている標準機能が使えない
    ● メモリアロケーターも無いのでVec, String等が使えない

    View full-size slide

  5. ベアメタル環境

    View full-size slide

  6. main関数を動かす

    View full-size slide

  7. main関数を動かす
    QEMU riscvのdefault biosは0x80200000を実行する

    View full-size slide

  8. main関数を動かす
    プログラムを0x8020_0000に配置し呼出す

    View full-size slide

  9. main関数を動かす
    リンカースクリプトで任意の
    アドレスにプログラムを配置する
    .entryシンボルを8020_0000に配置
    OUTPUT_ARCH( "riscv" )
    ENTRY( _entry )
    SECTIONS
    {
    . = 0x80200000;
    .text : {
    *(.entry)
    *(.text .text.*)
    }
    .rodata : {
    *(.rdata .rodata .rodata.*)
    }
    .data : {
    *(.data .data.*)
    }
    .bss : {
    *(.bss bss.*)
    }
    }

    View full-size slide

  10. main関数を動かす
    main.rsで.entryを定義
    これで関数_entryが呼ばれる
    // src/main.rs
    #![no_std]
    #![no_main]
    #[no_mangle]
    #[link_section = ".entry"]
    pub fn _entry() {
    main();
    }
    #[inline]
    fn main() {
    loop {}
    }
    #[panic_handler]
    fn panic(_info:
    &core::panic::PanicInfo) -> ! {
    loop {}
    }

    View full-size slide

  11. 関数呼び出しをサポートしたい

    View full-size slide

  12. 関数呼び出し
    みんな大好き関数呼び出し。
    というかプログラムを書く上でほぼ必須
    ● 関数呼び出しが出来ない。。
    ● inlineオプションを付けると呼び出せる
    fn a() {
    b()
    }
    fn b() {
    c()
    }
    pub fn _entry() {
    main();
    }
    #[inline]
    fn main() {
    loop {}
    }

    View full-size slide

  13. 関数呼び出し
    ● 関数呼び出しが出来ない。。
    ● inlineオプションを付けると呼び出せる
    ● (正確には関数を呼ぶとローカル変数の値がおかしくなる)
    なぜこれらが起きるのか

    View full-size slide

  14. 関数呼び出し
    ● 関数呼び出し時にスタック領域が確保される
    ● しかしSPの初期値は0
    ● SPを初期化する必要があった

    View full-size slide

  15. 関数呼び出し
    // src/main.rs
    static INIT_SP: [u8; 4096 * 1024] = [0; 4096 * 1024];
    static STACK_SIZE: usize = 4096 * 1024; // 4MB
    pub unsafe fn _entry() {
    // NOTE: スタックポインタの初期値を設定する
    // NOTE: スタックは下位に伸びていくのでINIT_SP + STACK_SIZEを設定
    しSTACK_SIZE分の領域を確保
    asm!("la sp, INIT_SP", "ld a0, STACK_SIZE", "add sp, sp,
    a0",);
    main();
    }
    SPを初期化
    誰からも変更されないように配列を定義し末尾アドレスを利用

    View full-size slide

  16. 動的メモリ確保したい

    View full-size slide

  17. 動的メモリ確保
    StringやVec,Boxが普通に使いたくなる
    これらはallocクレートに定義されている
    (stdが存在する場合はstdの一部)

    View full-size slide

  18. 動的メモリ確保
    allocを使うにはメモリアロケーターを実装する必要がある
    (heaplessクレートを利用するとアロケーターの実装無しでString, Vec等が使
    える)

    View full-size slide

  19. メモリアロケーターの実装
    global_allocatorディレクティブで登録出来る
    GlobalAllocトレイトを実装している必要がある
    #[global_allocator]
    static mut ALLOCATOR: BumpAllocator = BumpAllocator::new();
    pub struct BumpAllocator {
    arena: RefCell<[u8; ARENA_SIZE]>,
    next: Cell,
    }
    unsafe impl GlobalAlloc for BumpAllocator {
    unsafe fn alloc(&self, layout: Layout) -> *mut u8 {}
    unsafe fn dealloc(&self, _ptr: *mut u8, _layout: Layout) {}
    }

    View full-size slide

  20. メモリアロケーターの実装
    bump allocatorを採用
    heapの始点から終点まで順次割り当
    てていくだけ
    フラグメンテーションを一切考慮してい
    ない
    実装が超簡単なので採用

    View full-size slide

  21. まとめ
    ● 普段Rustを書く時に色んなものに乗っかっている事が分かった
    ● OSの機能以外にブート、メモリアロケーター、スタックポインタを気にする
    必要があった
    「俺の戦いはこれからだ!!」

    View full-size slide

  22. 自己紹介
    HN: nasa (Asan Kondo)
    nasaが欲しい
    ● github: k-nasa
    ● x(twitter): nasa_desu
    お仕事: MLOpsっぽいこと、DSの生産性改善

    View full-size slide

  23. (余談) 遭遇したバグたち
    ● 一度出力した文字が出力できない 「Hel?o W?r?d.」が出力される
    ○ 原因: SP初期化していないから
    ● カーネル起動時に有効化していないタイマ割り込みが発生して死ぬ
    ○ 原因1: エラーコードがズレてた。。本当は`address misaligned`
    ○ 原因2: アライメントを考慮していなかった
    ● プロセス切り替え時にSPが意図通り切り替わらない
    ○ 原因: 調査中。涙

    View full-size slide

  24. ご清聴ありがとうございました!

    View full-size slide