2014-09-20 about KERNEL_BASE_* on evbarm
evbarmの移植してるとこんがらがってくるのが KERNEL_BASE_PHYS、KERNEL_BASE_VIRT、KERNEL_BASE_EXT です。
KERNEL_BASE_PHYS カーネルの物理開始アドレス
KERNEL_BASE_VIRT カーネルの論理開始アドレス
KERNEL_BASE_EXT カーネルが使用可能な論理開始アドレス
です。
例えば、とあるボードは物理実装メモリが512Mbyte。
メモリマップは以下のようになっている場合を考えます。
uboot等のROMモニタが0x10000000にロードされ動作すると、ユーザプログラム
(この場合カーネル)のロードアドレスは(ubootの都合により)0x10080000等の
半端なアドレスとなります。そのため、netbsdのカーネルは0x10080000にロード
され、0x10080000から実行されることになります。
この場合、
とします。
KERNEL_BASE_VIRT は、カーネルの論理アドレスなので、netbsd側でつじつまが
あっていれば他のアドレスの場合もありえます(※)
「あれ、kernel が 0x10800000 = 0x80800000 にロードされるならば、メモリが
実装されているはずの 0x10000000〜0x10800000 の領域は無駄になるんじゃないの?」
と思った人はなかなかスルドイです。
この領域も当然もったいないので、実は当然ちゃんと使われます。
そのへんは arm32_bootmem_init() がうまくやってくれて、
arm32_bootmem_init() に、実メモリ実装範囲 0x10000000〜0x30000000、および
kernelの開始番地 0x10800000 を渡すと、実メモリの先頭からkernel開始番地の
空き領域 0x10000000〜0x10800000 をフリーページとして登録してくれて、
malloc(9)等で使えるようになります。VERBOSE_INIT_ARM を付けてコンパイルすると
起動時にそのへんの情報が表示されます。
さて、(※) で指摘した、kernelの論理アドレスを0x80000000ではなく他のアドレスに
したい場合はKERNEL_BASE_EXT を定義します。
例えば KERNEL_BASE_EXT = 0xC0000000 にすると、netbsd の userland プログラムの
論理アドレスは 0x00000000〜、kernel の開始アドレスが 0xC0000000〜 になります。
この場合、netbsd kernelで使える論理メモリ領域は
となり、この領域がkernelのtext、stackやMMU用のテーブル、malloc(9)、bus_space_map、
pool allocator等で使われます。
evbarmの場合、KERNEL_BASE は sys/arch/evbarm/include/vmparam.h でデフォルトでは
0x80000000 に定義されています。上記のようにこれを 0xC0000000 に変えたい場合は、
#define KERNEL_BASE_EXT 0xC0000000 すると、
のように定義されなおすわけです。
KERNEL_BASE_PHYS カーネルの物理開始アドレス
KERNEL_BASE_VIRT カーネルの論理開始アドレス
KERNEL_BASE_EXT カーネルが使用可能な論理開始アドレス
です。
例えば、とあるボードは物理実装メモリが512Mbyte。
メモリマップは以下のようになっている場合を考えます。
0x00000000 +----------------+ | I/O、ROM等 | | | 0x10000000 +----------------+ | メインメモリ | | 512Mbyte | | | | | 0x30000000 +----------------+ | | | 未使用 | | | 〜〜〜〜〜〜〜〜〜 〜〜〜〜〜〜〜〜〜 | | | | 0xA0000000 +----------------+ | I/O、ROM等 | | | 0xFFFFFFFF +----------------+
uboot等のROMモニタが0x10000000にロードされ動作すると、ユーザプログラム
(この場合カーネル)のロードアドレスは(ubootの都合により)0x10080000等の
半端なアドレスとなります。そのため、netbsdのカーネルは0x10080000にロード
され、0x10080000から実行されることになります。
この場合、
KERNEL_BASE_PHYS =0x10800000 KERNEL_BASE_VIRT =0x80800000 KERNEL_BASE =0x80000000
とします。
KERNEL_BASE_VIRT は、カーネルの論理アドレスなので、netbsd側でつじつまが
あっていれば他のアドレスの場合もありえます(※)
「あれ、kernel が 0x10800000 = 0x80800000 にロードされるならば、メモリが
実装されているはずの 0x10000000〜0x10800000 の領域は無駄になるんじゃないの?」
と思った人はなかなかスルドイです。
この領域も当然もったいないので、実は当然ちゃんと使われます。
そのへんは arm32_bootmem_init() がうまくやってくれて、
arm32_bootmem_init() に、実メモリ実装範囲 0x10000000〜0x30000000、および
kernelの開始番地 0x10800000 を渡すと、実メモリの先頭からkernel開始番地の
空き領域 0x10000000〜0x10800000 をフリーページとして登録してくれて、
malloc(9)等で使えるようになります。VERBOSE_INIT_ARM を付けてコンパイルすると
起動時にそのへんの情報が表示されます。
NetBSD/evbarm (nitrogen6) booting ... initarm: Configuring system (4 cpus, hatched 0xe), CLIDR=1110000003 CTR=0x83338003 arm32_bootmem_init: memstart=0x10000000, memsize=0x40000000, kernelstart=0x10800000 arm32_bootmem_init: kernelend=0x10e50000 arm32_bootmem_init: adding 129240 free pages: [0x10e50000..0x4fffffff] (VA 0x80e50000) arm32_bootmem_init: adding 1024 free pages: [0x10000000..0x107fffff] (VA 0x80000000) arm32_kernel_vm_init: 0 L2 pages are needed to map 0x6a0000 kernel bytes
さて、(※) で指摘した、kernelの論理アドレスを0x80000000ではなく他のアドレスに
したい場合はKERNEL_BASE_EXT を定義します。
例えば KERNEL_BASE_EXT = 0xC0000000 にすると、netbsd の userland プログラムの
論理アドレスは 0x00000000〜、kernel の開始アドレスが 0xC0000000〜 になります。
この場合、netbsd kernelで使える論理メモリ領域は
0xC0000000〜0xFFFFFFFFの0x40000000=1Gbyte
となり、この領域がkernelのtext、stackやMMU用のテーブル、malloc(9)、bus_space_map、
pool allocator等で使われます。
evbarmの場合、KERNEL_BASE は sys/arch/evbarm/include/vmparam.h でデフォルトでは
0x80000000 に定義されています。上記のようにこれを 0xC0000000 に変えたい場合は、
#define KERNEL_BASE_EXT 0xC0000000 すると、
=== sys/arch/evbarm/include/vmparam.h === /* * The line between user space and kernel space * Mappings >= KERNEL_BASE are constant across all processes */ #ifdef KERNEL_BASE_EXT #define KERNEL_BASE KERNEL_BASE_EXT #else #define KERNEL_BASE 0x80000000 #endif
のように定義されなおすわけです。
EOF