6.828: Operating System Engineering (94)
ええと、load_icode 検討の前にこないだスケッチした segment_alloc 手続きを控えておきます。
static void segment_alloc(struct Env *e, void *va, size_t len) { // LAB 3: Your code here. // (But only if you need it for load_icode.) // // Hint: It is easier to use segment_alloc if the caller can pass // 'va' and 'len' values that are not page-aligned. // You should round va down, and round len up. int i; struct Page *pp; va = ROUNDDOWN(va, PGSIZE); len = ROUNDUP(len, PGSIZE); for(i = 0; i < len; i += PGSIZE, va += PGSIZE) { if (!page_alloc(&pp)) panic("cannot page allocate"); if (!page_insert(e->env_pgdir, pp, va, PTE_U)) panic("cannot page insert"); } }
本当かなぁ。とりあえずこれで良いってことにしといて次。
# あ、コメントに Pages should be writable by user and kernel. ってあるな
load_icode 手続き
static void load_icode(struct Env *e, uint8_t *binary, size_t size)
を踏まえると ELF バイナリの先頭アドレスとサイズが渡されるのか。あとなんとなくヘッダのエラーチェックとかしなくてよさげ。
そーゆー意味では手順としては
- binary + e_phoff がプログラムヘッダの先頭アドレス
- ELF ヘッダの e_phnum 属性の値の回数繰り返し
- プログラムヘッダの先頭アドレスは binary + e_phoff + (e_phentsize * i) で取得できる
- プログラムヘッダの p_type 属性が ELF_PROG_LOAD が処理対象
あら? これ、どうやってコピィすりゃ良いのかな。あ、ここで segment_alloc が出てくるのか。page_lookup して NULL が戻ってこなければ確保すれば良い?
あまり細かいこと気にせずにヤッツケれば OK かなぁ。処理対象であれば
- segment_alloc でページ確保
- p_filesz な領域を確保すりゃ良いか
確保した領域を 0 で memset して p_memsz 分 memcpy すれば良いんだとは思うのですが、どこにコピーするんだろ。ちょっと頭が混乱してるカンジ。
ええと、page_lookup で page table entry 取得できるってことはそこプラス PGOFF(va) な要素が該当する位置にあたると思うんですが、ページを跨ぐ場合どうなるんでしょ。
落ち着け
なんとなくページング周辺なリハビリ不足 (つーか理解不足) をなんとかしないと。てゆーかページが連続してる保証はどこにも無いのでこのあたりは頑張って、ということになるのかどうなのか。
まずどうやって 0 で memset するか、ということから考えてみましょう。
- page_lookup すれば va から該当する page table entry が分かる
- そこに格納可能なのは PGSIZE - PGOFF(va) になる?
- PGOFF(va) に p_filesz を加えた値が PGSIZE を超えたらページ跨がり
- 跨がる場合 va + (PGSIZE - PGOFF(va)) を page_lookup に渡して戻ってくるソレが次のページの先頭?
- 跨がる場合の残サイズは PGSIZE - (PGOFF(va) + p_filesz) になるのか
- む、これは繰り返しになるのか
もう少し Hints なコメント読んで実装書いてみる方向。なんとなくループが沢山ネストしそうで嫌だなぁ。