🦔

OSを作るための落書き

2023/03/21に公開

chiaskです。
xv6という教育用のOSをRustで書き換えてみたいので、
なんかおもろいことがあるなら、ここでメモする。
Github: https://github.com/sun-jacobi/rxv6

設定

知っている限りでは三つの方法がある:

  1. static libにコンパイルして、gccでリンクする
  2. build.rsでgccを呼び出す(1と本質的に同じ
  3. cargo configを使う

ここでは3を用いた。.cargoというディレクトリの中に、configというを作る

[build]
target = "riscv64gc-unknown-none-elf"
rustflags = [
    "-C", "link-args=-Tsrc/ld/kernel.ld -z max-page-size=4096",
]

riscv64の公式のtargetは普通にあるので、それを使おう。
linker argumentsもできる。
assemblyは

core::arch::global_asm!(include_str!("../asm/entry.S"));

のような形でincludeする必要がある

cargo buildすると、

target/riscv64gc-unknown-none-elf/debug/

というディレクトリにelfファイルがあるはず。
vscodeを使うならsetting.jsonの編集もしたほうがいいかも。
(e.g.

{
  "rust-analyzer.cargo.target": "riscv64gc-unknown-none-elf",
  "rust-analyzer.check.targets" : "riscv64gc-unknown-none-elf",
  "rust-analyzer.checkOnSave.allTargets": false
}

GDB

gdb stubでQEMUの中に動くプログラムをデバッグすることができる。
QEMUを起動する時に、

 -s -S

を添えると、そのまま動き始めるのでなくて、gdbの指令を待つみたいな感じ。
そして、gdbで

target remote localhost:1234

したら、デバッグすることができる。
gdb stubの仕組みはなんかrpcに近いかも(知らないが

gdb scriptで

define hook-quit
    kill
end

にすると、gdbをquitすると同時にqemuからexitできる。

Bare Metal Rust

最低限として、

#[panic_handler]
fn panic(_panic: &PanicInfo<'_>) -> ! {
    loop {}
}

が必要。

実装

バーチャルメモリ

特に実装する必要なのは、

  • Page allocator
  • Page Table
    だね。
    どちらもデバッグしにくいので、mockテストをやるのは楽。

コードの大きさは変わるので、linker scriptで変数(アドレス)を定義するのが多い。
Rustでそう言う変数を呼び出すためには

extern "C" {
    static mut end: u64; // the first address after the kernel
}

のようなFFIを使うことができる。ただし、ここのendはその変数の値ではなく、そのlocationでendが置かれたから、実際にそのアドレスを知るためには.

(&end as *const u64) as u64;

にすれば良い。

Discussion