GAIAとxv6におけるbootloader
SRAM
GAIAで使ってる基盤は4MB(222)のSRAMを積んでる。 rom.vhd
は実際には sram.vhd
をラップしてるに過ぎず、いわゆるDRAMは一切使用していない。(BlockRamというのもSRAMの一種らしい?)
sram.vhd
の中では、入ってきたアドレスの上位10bitは見ておらず、下位22bitだけを見ている。(これが単純な仮想アドレス変換として機能している?ページテーブルやTLBの実装等は見当たらないため)
xv6
nyuichi/xv6
kernelmemfs: $(MEMFSASMS) initcode _min-rt fs.img ./tools/gen_binary_blobs 0x80002000 initcode _min-rt fs.img $(AS) $(ASFLAGS) -c -o _kernelmemfs -e 0x80002000 -start _start $(MEMFSASMS) _binary_blobs.s $(UCCLIBS) -f __UCC_HEAP_START ./tools/gen_binary_blobs `ruby -e "print open('_kernelmemfs').size + 0x80002000"` initcode _min-rt fs.img $(AS) $(ASFLAGS) -c -o _kernelmemfs -e 0x80002000 -start _start $(MEMFSASMS) _binary_blobs.s $(UCCLIBS) -f __UCC_HEAP_START cat _kernelmemfs initcode _min-rt fs.img > kernelmemfs rm _kernelmemfs ./tools/attach_boot_header kernelmemfs
- 公式のようなリンカスクリプトは使っていない。よくみるとハードコーディングで
0x80002000
を使っており、これがkernelが配置されている先頭仮想アドレスである。0x8010_0000
を使ってないのは、無駄に0 - 1MB空間を空けないようにするため? - そして、GAIAではプロセスごとのアドレス空間切り替えをどうやって実装しているのか。MIPSでいうASID的なものが見当たらないが...
memlayout.h
// Memory layout #define EXTMEM 0x2000 // Start of extended memory #define PHYSTOP (4*1024*1024) // Top physical memory #define DEVSPACE 0xFE000000 // Other devices are at high addresses // Key addresses for address space layout (see kmap in vm.c for layout) #define KERNBASE 0x80000000 // First kernel virtual address #define KERNLINK (KERNBASE+EXTMEM) // Address where kernel is linked // [0x80000000, 0x80001FFF] is special memory mapped area. // Kernel MUST guarantee that this memory area is directly mapped to the physical same area. #define VAENABLE 0x80001200 #define PDADDR 0x80001204 #define INTHANDLER 0x80001100 #define INTENABLE 0x80001104 #define EPC 0x80001108 #define CAUSE 0x8000110C #define SERIAL 0x80001000 #define SERIALWE 0x80001004
ここで、だいたい分かる。このへんのアドレス設定はGAIAのアーキテクチャと密結合な感じで、GAIAのソースコード内にもがっつりハードコーディングで書かれている。
* EXTMEM : 物理アドレスのどこにkernel先頭が配置されてるのか示す。 * PHYSTOP : 詰んでるSRAMの容量に合わせる(実質的な物理メモリ容量) * その他 : I/Oで使うメモリマップドのアドレス。例えば、シリアル通信は0x80001000, 0x80001004。uart.cで使用している
mips移植を考える場合
xv6-mips
では上記のような考慮はされていないため、適宜パラメタを書き換える必要がある。特にEXTMEM
はkernellをSRAMに載せるにしろDRAMに載せるにしろ書き換えないとまともに動かない。オリジナルのxv6, xv6-mipsでは memlayout.h
はシンプルで、定数は各クラスファイル内に書かれているケースが多い。(uart.c, mips.hなど)
// Memory layout #define EXTMEM 0x100000 // Start of extended memory #define PHYSTOP 0xE000000 // Top physical memory #define DEVSPACE 0xFE000000 // Other devices are at high addresses // Key addresses for address space layout (see kmap in vm.c for layout) #define KERNBASE 0x80000000 // First kernel virtual address #define KERNLINK (KERNBASE+EXTMEM) // Address where kernel is linked #define V2P(a) (((uint) (a)) - KERNBASE) #define P2V(a) (((void *) (a)) + KERNBASE) #define V2P_WO(x) ((x) - KERNBASE) // same as V2P, but without casts #define P2V_WO(x) ((x) + KERNBASE) // same as P2V, but without casts