linux head.s 编译,浅析armlinux2.4.19启动程序[head-armv.s文件]

str    r9, [r6]//将r9处理器ID值转存入变量processor_id中,供c程序调用

str    r1, [r7]//将r7体系结构指针的machine_desc转存入变量__machine_arch_type中,供c程序调用

#ifdef CONFIG_ALIGNMENT_TRAP

orr    r0, r0, #2//r0为cp15协处理器c1中控制值

#endif

bic    r2, r0, #2//取消掉故障校验后的数值存入r2

stmia  r8, {r0, r2}//cr_alignment = r0;其后存储(init_task_union)+8192数值的空间存入r2

b    SYMBOL_NAME(start_kernel)

//好了,我的分析到此结束,由u-boot1.1.5完成解压的启动部分,转入c代码start_kernel,作更复杂的启动[gliethttp 2007-07-25]

__create_page_tables:

//通过前面的分析已知r5 = 体系结构指针下对应的machine_desc->phys_ram物理内存地址

//但pgtbl宏并没有使用到r5,而是直接使用stext,

pgtbl  r4, r5

//所以此时r4=物理地址=0x2000

mov    r0, r4

mov    r3, #0

add    r2, r0, #0x4000//r2=0x20008000

1:  str    r3, [r0], #4

str    r3, [r0], #4

str    r3, [r0], #4

str    r3, [r0], #4//将0x20004000~0x20008000这16k空间清0

teq    r0, r2

bne    1b

//ok,清0结束[gliethttp]

krnladr r2, r4, r5//bic r2,r4,#0x000ff000;将ff处对应的1数据清0

//所以r2 = 0x20000000

//通过前面的分析r8=0x00000c1e

//在进行下面的分析之前,最好先看看另一篇文章

//《linux2.4.19下__ioremap函数中remap_area_pages虚拟地址映射建立函数的代码分析》[http://gliethttp.cublog.cn]

//熟悉一下MMU的表结构

//MMU对4种大小进行映射管理,

//1)微页:构成1k的存储区

//2)小页:构成4k的存储区

//3)大页:构成64k的存储区

//4)节:构成1M的存储区

add    r3, r8, r2

//r2=0x20000000

//r3=0x20000000+0x00000c1e=0x20000c1e

//r4=0x20004000

//r2>>18剩下的高14位,即16K地址,4k个4字节组地址单元,用于一级表映射bit31~bit20节基址匹配

str    r3, [r4, r2, lsr #18]//r4为转换表基

//>>18位,剩余14位,而不是12位,是高12位节基址*4字节存储地址的结果,是bit31~bit20节基址索引×4字节的结果

//表示虚拟地址节0x20000000~0x200fffff对应物理地址节0x20000000~0x200fffff

add    r0, r4, #(TEXTADDR & 0xff000000) >> 18

bic    r2, r3, #0x00f00000

//r2 = 0x20000c1e

str    r2, [r0]

//表示虚拟地址节0xc0000000~0xc00fffff对应物理地址节0x20000000~0x200fffff

add    r0, r0, #(TEXTADDR & 0x00f00000) >> 18

//接下来开始依次线性节映射[gliethttp 2007-07-25]

str    r3, [r0], #4

//表示虚拟地址节0xc0000000~0xc00fffff对应物理地址节0x20000000~0x200fffff

//r3=0x20000c1e表项值,r0=r0+4,r0指向下一个连续的虚拟地址1M节基址

add    r3, r3, #1 << 20

//r3=r3+1M指向下一物理地址节基址

str    r3, [r0], #4

//表示虚拟地址节0xc0100000~0xc01fffff对应物理地址节0x20100000~0x201fffff

//r0指向下一个连续的虚拟地址1M节基址

add    r3, r3, #1 << 20

//r3=r3+1M指向下一物理地址节基址

str    r3, [r0], #4

//表示虚拟地址节0xc0200000~0xc02fffff对应物理地址节0x20200000~0x202fffff

//r0指向下一个连续的虚拟地址1M节基址

add    r3, r3, #1 << 20

//r3=r3+1M指向下一物理地址节基址

str    r3, [r0], #4

//表示虚拟地址节0xc0300000~0xc03fffff对应物理地址节0x20300000~0x203fffff

//r0指向下一个连续的虚拟地址1M节基址

//这样0xc0000000~0xc03fffff 4M虚拟地址空间和0x20000000~0x200fffff 1M虚拟地址空间

//都线性的映射到了0x20000000~0x203fffff 4M物理地址空间

bic    r0, r0, #0x01f00000 >> 18//0x1f=32M空间对齐

and    r2, r5, #0xfe000000//对于传递的参数r5-物理内存地址空间

add    r3, r8, r2

str    r3, [r0]//最后还是0x20000000~0x200fffff虚拟地址到0x20000000~0x200fffff物理地址映射

//如果r5的值和内核拷贝到的内存中的位置值不符,真不知会是什么想象,不过还好,他们相等.

bic    r8, r8, #0x0c

#ifdef CONFIG_DEBUG_LL

add    r0, r4, r7//r7为debug串口显示物理寄存器对应的虚拟地址对应的节基址

rsb    r3, r7, #0x4000//r3=0x4000-r3=距离0x3fff还有多少个地址空间

cmp    r3, #0x0800//0xE0000000空间

addge  r2, r0, #0x0800//r7对应的虚拟空间<=0xE0000000,加上0x20000000,

//调整到0xE0000000~0xFFFFFFFF虚拟空间

addlt    r2, r0, r3//r7对应的虚拟空间>0xE0000000,r2=计算出的io虚拟地址映射的大小

orr    r3, r6, r8//r6对应串口物理寄存器的物理地址|| r8这个节标志

1:  str    r3, [r0], #4//将虚拟地址r0所在的1M空间映射到物理地址r3所在的1M空间中,之后r0虚拟地址1M节索引r0+4指向下一节

add    r3, r3, #1 << 20//进入物理地址空间的下一个1M节

teq    r0, r2//是否映射完毕

bne    1b//

#if defined(CONFIG_ARCH_NETWINDER) || defined(CONFIG_ARCH_CATS)

teq    r1, #MACH_TYPE_NETWINDER//非该类型,是MACH_TYPE_AT91RM9200类型

teqne    r1, #MACH_TYPE_CATS//也非该类型

bne    1f//跳到下一个标号1:处

add    r0, r4, #0x3fc0

mov    r3, #0x7c000000

orr    r3, r3, r8

str    r3, [r0], #4

add    r3, r3, #1 << 20

str    r3, [r0], #4

1:

#endif

#endif

#ifdef CONFIG_ARCH_RPC//未定义

add    r0, r4, #0x80

mov    r3, #0x02000000

orr    r3, r3, r8

str    r3, [r0]

add    r0, r4, #0x3600

str    r3, [r0]

#endif

mov    pc, lr//返回

__error:

#ifdef CONFIG_DEBUG_LL//实现了串口输出,那么将错误信息打印到串口终端

mov    r8, r0

adr    r0, err_str

bl    printascii//打印"\nError: "字符串

mov    r0, r8

bl    printch//打印

#endif

#ifdef CONFIG_ARCH_RPC

mov    r0, #0x02000000

mov    r3, #0x11

orr    r3, r3, r3, lsl #8

orr    r3, r3, r3, lsl #16

str    r3, [r0], #4

str    r3, [r0], #4

str    r3, [r0], #4

str    r3, [r0], #4

#endif

1:  mov  r0, r0//系统因为错误halt在此处

b    1b

#ifdef CONFIG_DEBUG_LL

err_str:    .asciz    "\nError: "

.align

#endif

__lookup_processor_type:

adr    r5, 2f//伪指令adr,读取下面第一个2:标号处的和pc相对的物理地址

ldmia  r5, {r7, r9, r10}

//r7=虚拟地址__proc_info_end

//r9=虚拟地址__proc_info_begin

//r10=虚拟地址2b=标号2处的地址值[虚拟地址-反汇编得0xc00081b8]

//所以r5=0x200081b8

sub    r5, r5, r10//计算标号2物理地址和虚拟地址的间距r5 = 0x200081b8-0xc00081b8;

add    r7, r7, r5 //将r7中的线性虚拟地址转换成与之线性对应的物理地址,结果存入r7

add    r10, r9, r5//同样计算r9中存放的虚拟地址,对应的物理地址,结果存入r10

mrc    p15, 0, r9, c0, c0//通过协处理器cp15,获取cpu的型号,对于at91rm9200,r9=0x41129200

//r7 = __proc_info_end结束的物理地址

//r9 = 处理器ID

//r10 = 处理器结构体的指针

1:  ldmia  r10, {r5, r6, r8}//读取编译进r10为起始物理地址的__proc_info_begin结构体信息

//++++++++++++++

//arch/arm/mm/proc-arm9200.S中定义了该结构体信息

//    .section ".proc.info", #alloc, #execinstr

//    .type    __arm920_proc_info,#object

//__arm920_proc_info:

//    .long    0x41009200

//    .long    0xff00fff0

//    .long    0x00000c1e            @ mmuflags

//    b    __arm920_setup

//    .long    cpu_arch_name

//    .long    cpu_elf_name

//    .long    HWCAP_SWP | HWCAP_HALF | HWCAP_THUMB

//    .long    cpu_arm920_info

//    .long    arm920_processor_functions

//    .size    __arm920_proc_info, . - __arm920_proc_info

//--------------

//所以r5 = 0x41009200

//r6 = 0xff00fff0

//r8 = 0x00000c1e

and    r6, r6, r9//r6 = r6 & r9 = 0x41009200

teq    r5, r6

moveq  pc, lr//因为处理器类型匹配,返回

add    r10, r10, #36//如果多处理器,那sizeof(__arm920_proc_info)=0x24=36,r10指向下一个处理器单元

cmp    r10, r7

blt    1b//如果没有遍历所有处理器类型,那么跳到标号1:处,继续匹配

mov    r10, #0//没有找到匹配的处理器

mov    pc, lr

2:  .long    __proc_info_end

.long    __proc_info_begin

.long    2b

.long    __arch_info_begin

.long    __arch_info_end

__lookup_architecture_type:

adr    r4, 2b//伪指令,读取上面第一个2:标号处的和pc相对的物理地址

ldmia  r4, {r2, r3, r5, r6, r7}

//r2 = 虚拟地址__proc_info_end

//r3 = 虚拟地址__proc_info_begin

//r5 = 虚拟地址标号2:

//r6 = 虚拟地址__arch_info_begin

//r7 = 虚拟地址__arch_info_end

sub    r5, r4, r5//和__lookup_processor_type一样,计算虚拟地址和物理地址的线性偏移量

add    r4, r6, r5//r4=__arch_info_begin的物理地址

add    r7, r7, r5//r7=__arch_info_end的物理地址

//++++++++++++++

//arch/arm/mach-at91rm9200/Core.c

//MACHINE_START(AT91RM9200, "ATMEL AT91RM9200")//.nr = MACH_TYPE_##_type=MACH_TYPE_AT91RM9200=251

//与上面从u-boot传到r1中的一样[gliethttp]

//MAINTAINER("SAN People / ATMEL")

//BOOT_MEM(AT91_SDRAM_BASE, AT91C_BASE_SYS, AT91C_VA_BASE_SYS)

//BOOT_PARAMS(AT91_SDRAM_BASE + 0x100)//tag list存放的物理地址0x20000100[gliethttp]

//FIXUP(at91rm9200_fixup)

//MAPIO(at91rm9200_map_io)

//INITIRQ(at91rm9200_init_irq)

//MACHINE_END

//--------------

1:  ldr    r5, [r4]

teq    r5, r1//与r1传入的MACH_TYPE_AT91RM9200=251数值匹配

beq    2f//匹配上,则跳到下一个标号2:处,退出

add    r4, r4, #SIZEOF_MACHINE_DESC//r4+sizeof(machine_desc),指向下一个体系结构体的物理地址

cmp    r4, r7

blt    1b//.arch.info体系结构是否已经遍历结束

mov    r7, #0//没有找到与r1类型匹配的体系结构

mov    pc, lr

2:  ldmib  r4, {r5, r6, r7}//先加后装载

//所以r5 = machine_desc->phys_ram

//r6 = machine_desc->phys_io

//r7 = machine_desc->io_pg_offst

mov    pc, lr

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值