RustでOSを書くログ
Vibe codingでモノづくりもいいけど、生成AIのsuper teacher付きでCSを学ぶのもとても良い。
最終目標はOS/kernelの基本的な足回りを最低限整えた後にnetwork protocol stackを書くこととしてRustでOSを書きはじめてみる。
minimumなweb APIサーバーと競プロ周りでしかRustを書いていなかったため、システムプログラミングを通じてRustの強みを感じつつ理解を深めたいという狙いもある。
どういう方針で進めていくかの段取りなどは生成AIと協業しつつ、codeの記述はすべて自分で行う方針で進めていく。趣味プロにおいてくらいコーディングの楽しみは奪わせたくないし、コード生成させていては勉強にもならないため。(AGENTS.md)
repository: https://github.com/puppypepper/papi_os
~2026/03/31
https://os.phil-opp.com/の最序盤を参考にしつつQEMUからのhello worldまでを済ませる。no_stdやno_mangleなど、最低限開発を始めるまでのハードルを高く感じていたため大変助かった。
2026/03/31
commit: https://github.com/puppypepper/papi_os/commit/28ce3bbdaac6e7295f8a0bd045fd060c49676a9b
VGA text bufferの改行実装
VGA text bufferは昔のx86互換機で使われていた文字表示モードで、0xb8000から始まるアドレスにデータを書き込むことによって画面上に対応する文字を横80 x 縦25で表示することができる。QEMUがこれをエミュレートしているためQEMUで起動した場合でも同じように使用することができる。初期の表示確認としては便利なのでRustで自作OSをしている例だとほとんどの初期段階で使用されているかも?
VGA text bufferはmemory mapped IOに対応するため、Rustで扱う際にはVolatileでwrapすることでcompilerの最適化によってメモリ書き込み外としない形に変更されることを防いでいる。
2026/04/01
commit: https://github.com/puppypepper/papi_os/commit/fea65b69df31725e99115536319ffeae347a0cc0
簡易的なシリアル出力の実装を行った。
QEMUのserial0に出力することでpanic時にも情報を出すことができる。
2026/04/02
commit: https://github.com/puppypepper/papi_os/commit/270541ddd3361b06f9629222c4f1f1852cfe9085
ただのloop {}をインラインアセンブリ経由のhltに変える。
#[inline]
fn hlt() {
unsafe { asm!("hlt"); }
}
pub fn hlt_loop() -> ! {
loop {
hlt();
}
}2026/04/03
(現状整形がかなり見づらい)
commit: https://github.com/puppypepper/papi_os/commit/e92e11664798dbd31f8548e15debb3a5836fe984
breakpoint例外とpage fault例外の例外ハンドラの雛形を用意。
IDT自体はx86_64クレートの物を使用。
2026/04/04
今度からは小さくてもPRにしていこうかな。
double fault例外のハンドラをGDT, TSSを定義しながら実装。
2026/04/13
PR: https://github.com/puppypepper/papi_os/pull/1
I/O port経由でPICを制御することによってTimerに対する割り込みハンドラを定義。ついでにCargo.tomlを調整してcargo runでqemuを起動するように変更。
2026/04/18
PR: https://github.com/puppypepper/papi_os/pull/3
キーボード割り込み用のI/Oポートを読むことによって最低限のキー入力検知を実装。0x60のI/Oポートを読みにいかないといけないことはAIに聞きつつ、実装自体は今までの割り込み実装を参考にscratchで書けたのでちょっと進歩している。
そろそろclippyなどのlint CI整備もしていきたいな。
2026/04/21
PR: https://github.com/puppypepper/papi_os/pull/4
メモリアロケータ周りの実装を進めていく。
起動方法を_start関数から、bootloader crateのentry_point!() macro経由に変更。
bootloaderがカーネルに渡すmemory map情報をシリアル出力するようにした。
ついでにcargo check, rustfmt, clippyをCIでチェックするように変更。
2026/04/24
PR: https://github.com/puppypepper/papi_os/pull/5/changes
UsableなMemory Regionから、一つずつFrameを取得する愚直なアロケータを実装。
x64_64 crateへの依存がちょっと気になってきた。
2026/04/28
PR: https://github.com/puppypepper/papi_os/pull/6
bootloaderのmap_physical_memoryを有効化し、bootloaderから渡されるphysical_memory_offsetの情報を使って、x86_64 long modeで有効化されているlevel 4 page tableを参照できるPageMapperを初期化。
x86_64 crateへの依存はmemory.rs内に留め、main.rsなど他の部分から利用する際にはPageMapperなどのFacade経由とする。後に依存を取り除きたくなったときに有利に働くはず。
2026/05/06
PR: https://github.com/puppypepper/papi_os/pull/7
PageMapper に map_page関数を追加し、指定した仮想アドレスを含む 4KiB 仮想ページを、物理フレームにマッピングする。bootloader が用意した x86_64 long mode の page table を kernel から更新できるようになった。
2026/05/19
PR: https://github.com/puppypepper/papi_os/pull/10
heap_allocatorをfacadeを用意しつつ初期化してglobal allocatorとして利用する。
global allocatorを初期化したことによりBoxやVecなどalloc crateの型を使用することができるようになった。
実際にinit_heap前でBox::new()を実行するとheap allocationのpanicが発生し、init_heap後には適切にBoxが使用できていることを確認した。