少し期間が空きましたが、メモリ割り当てを実装します。
リンカスクリプト修正
メモリを割り当てるにあたって、自由に割り当てて良いメモリ領域を定義します。
__stack_top = .; . = ALIGN(4096); __free_ram = .; . += 64 * 1024 * 1024; /* 64MB */ __free_ram_end = .;
目印としてstack_topを載せていますが、更新しているのはstack_top以下の4行です。
_free_ramとして、メモリ割り当て用領域のスタート位置を確保しています。
その前に4096バイト(4KB)境界にするためのアライメントを行っています。
4KB境界である理由は調査したところ以下のようです。 * 典型的なページサイズが4KB * ページ途中をまたがるメモリフラグメンテーションを防ぐことができる。
ページングアルゴリズム
extern char __free_ram[], __free_ram_end[]; paddr_t alloc_pages(uint32_t n) { static paddr_t next_paddr = (paddr_t) __free_ram; paddr_t paddr = next_paddr; next_paddr += n * PAGE_SIZE; if (next_paddr > (paddr_t) __free_ram_end) PANIC("out of memory"); memset((void *) paddr, 0, n * PAGE_SIZE); return paddr; }
上記ページングアルゴリズムでは、next_paddrによって指定される物理アドレスの位置からページ割り当てを行います。 next_paddrは__free_ramの位置を定義していますが、staticで定義されているのでalloc_pages関数の呼び出しごとに、未割り当てのメモリにページ割り当てを行うことができます。
ページングのスタート位置から、割り当てるメモリをすべて0クリアするというロジックです。PAGE_SIZEは4KBととして、kernel.hで定義する必要があります。
実験として、2つのページ割り当てを行い、ページングの開始アドレスを確認しましたが、以下のようになっています。
alloc_pages test: paddr0=80231000 alloc_pages test: paddr1=80235000
paddr0に4ページ割り当てましたが、4KB * 4 メモリ分先の位置にページ割り当てが行われていることが確認できました。