2008年8月4日星期一

where to place ARM linux kernel

Uncompressed Kernel Image
在ARM体系中,下面这条是定理
ZRELADDR == virt_to_phys(PAGE_OFFSET + TEXT_OFFSET)
PAGE_OFFSET + TEXT_OFFSET定义了内核image的起始虚拟地址。ARM中定义PAGE_OFFSET为0xC000,0000,很明显这是虚地址。arch\arm下的makefile中定义
TEXT_OFFSET := $(textofs-y)
textofs-y的默认值定义如下
textofs-y := 0x00008000
ZRELADDR是对应的物理地址,它在makefile.boot中定义为
zreladdr-y := 0x10008000
这里以OMAP1为例,这个地址就是DRAM的所在的区域
由此可见,这里就是一次MMU mapping,0x10008000==>0xC0008000,那么我们的kernel就应该放在物理地址0x10008000 上,这些都是默认设置我们没必要修改。
如果只是要得到Uncompressed kernel image,就是用make Image命令build kernel,上面的常识就足够了。
Compressed Kernel Image
但是如果你使用make zImage命令build kernel,那么你一定想得到一个Compressed kernel image,这样kernel体积小,节省flash空间.
zImage有两部分组成,前段是自解压代码,后段是被压缩过的kernel image。因此自解压代码也是需要一个放置地址的。
它的起始地址是TEXT_START,TEXT_START默认为0。这段代码是地址无关的,所以可以被安排在任何地址上,解压后的地址由上面的zreladdr决定,这里就是0x10008000。
解压前后内存可能重叠
为了避免内存块重叠,linux建议我们最好这样安排:
1.解压缩后的image起始地址,在压缩image的后面
2.解压缩后的image的结束地址,在压缩image的前面
对于这两条,我觉得第一条更容易做到
解压缩后的image大小如何计算
linux kernel image是用gzip压缩的,压缩基本比例为3:1,那么在计算解压缩后的image大小时,用压缩image大小 x 4计算比较安全。
跳转到kernel
call_kernel: bl cache_clean_flush
bl cache_off
mov r0, #0 @ must be zero
mov r1, r7 @ restore architecture number
mov r2, r8 @ restore atags pointer
mov pc, r4 @ call kernel
这是跳转到解压缩的image的动作。这里可以看出ARM linux规定的向kernel的参数传递规则。
r0为0
r1为architecture的识别号
r2是指针,指向atags参数表
然后跳转到uncompressed image的起始地址上。这里r7,r8寄存器在开始就被备份过,这里做一次恢复。