[ TOP | Recently ]

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。
メモリマップは以下のようになっている場合を考えます。

	    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