🦔
OSを作るための落書き
chiaskです。
xv6という教育用のOSをRustで書き換えてみたいので、
なんかおもろいことがあるなら、ここでメモする。
Github: https://github.com/sun-jacobi/rxv6
設定
Link
知っている限りでは三つの方法がある:
- static libにコンパイルして、gccでリンクする
- build.rsでgccを呼び出す(1と本質的に同じ
- 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