livaの雑記帳

livaの雑記帳

OSとか作ってみたい

Rump Kernelの起動コードを読む

Rump Kernelのソースコードを読んでいく。

unikernel版(?)で、platformはhw(ベアメタル上で動作する版)

 

ベースとなるコードはここ。

GitHub - rumpkernel/rumprun: The Rumprun unikernel and toolchain for various platforms

 

僕はアーキテクチャspecificな部分から攻めていくのが好きなので、とりあえずx86依存なブート処理を読んでいく。

 

リンカスクリプトはこれ

rumprun/kern.ldscript at master · rumpkernel/rumprun · GitHub

 

ブートはmultiboot経由で行われる。

multibootのエントリポイントがここ

rumprun/locore.S at master · rumpkernel/rumprun · GitHub

 

やってる事は64bitへの遷移。

cr3レジスタはcpu_pml4tというシンボルを代入している。

ページ構造体は以下にstaticに作られている。

rumprun/pagetable.S at master · rumpkernel/rumprun · GitHub

凄いコードだ。。。

あんまりOSのコードを読んだことが無いから分からないのだけど、staticに作るのって一般的なのだろうか?動的に生成するのが普通かと思っていたけども。。。

 

64bit遷移後はx86_bootへジャンプする。

rumprun/boot.c at master · rumpkernel/rumprun · GitHub

ここでやっている事は、諸々の初期化。

cons_initはコンソールの初期化。putcした時に、vgaコンソール使う場合はvgacons_putcを呼ぶようにするし、シリアルを使う場合はserialcons_putcを呼ぶようにする。

 

cpu_initはTSS、IDT、PICの設定をした上で、タイマを初期化する。

実機だったらtscを用いる。(tscがあれば)これは8254でtscのfrequencyを測定しているコード。

rumprun/clock.c at master · rumpkernel/rumprun · GitHub

 

ところで、8254を使い終わった後も、とりあえず適当なハンドラを登録して、割り込みが来ると握りつぶすようにしてるようなんだけど、これはなぜ?

rumprun/clock.c at master · rumpkernel/rumprun · GitHub

 

multibootではコマンドラインオプションを取得(moduleで指定されている場合はmoduleを読む) し、parsememで使用可能なメモリを登録する。で、なぜかここでintr_initを読んでいる。intr_initはdoisrをスケジュールしている。別にmultibootから呼ばなくて良くないか?と思うが、何か深い理由があるのだろうか。

 

doisrはイマイチよく分からない。

thread context we use to deliver interrupts to the rump kernel

 だそうで。

rumprun/intr.c at master · rumpkernel/rumprun · GitHub

とりあえずリンクだけ貼っておく。

 

multibootを抜けたら、割り込みを許可して、bmk_sched_startmainを開始する。

 

 

雑感。

一通り読んで分かったけど、マルチコアの初期化は一切やってない。そりゃそうだよね。まあユニカーネルなんだし複数コアとかいらないのかな。

今回は出てこなかったが、rump kernelを動かすにはスケジューラとかが必要という話があって、既存のOS上で動かす場合はホストOSが面倒を見るのだけど、ベアメタルで動かす場合は自分で実装しなければならない。そういった部分はlib/libbmk_core内にあるっぽい。アーキテクチャ非依存だからね。