linux内核源码启动流程一

文章讲述了Linux内核启动时如何通过分步骤建立段式和细页表进行内存管理,先用段式页表粗略映射,然后在后期启用细页表以实现更精细的内存控制。

linux内核本身被链接在虚拟地址处,因此kernel希望尽快建立页表并且启动MMU进入虚拟地址工作状态,但是kernel本身工作起来后页表体系是非常复杂的,建立起来也不是那么容易的。因此kernel想了一个好办法,就是:建立页表分两步走。第一步,kernel先建立一个段式页表(和uboot之前建立的页表一样,页表以1MB为单位来区分的),这里的函数就是建立段式页表。段式页表本身比较好建立(段式页表1MB一个映射,4GB的空间需要4096个页表项,每个页表项4字节,因此一共需要16KB内存来做页表),坏处是比较粗不能精细管理内存;第二步,再去建立一个细页表(以4KB为单位),然后启动新的细页表,废除第一步建立的段式映射页表。(Linux内核分段分页进行内存管理

在内核启动的早期,建立的段式页表,并在内核启动的前期使用;在内核启动的后期,就会再次建立细页表并启用。等内核启动工作起来之后就只有细页表了。

                                                       start_kernel函数前执行流程图

第91行:初始化栈基指针fp

第92~94:清空bss段数据

第96行:重新设置寄存器值

R4=processor_id(cpu处理器ID地址,其变量定义在arch/arm/kernel/setup.c中)

R5=__machine_arch_type(machine id地址,其变量定义在arch/arm/kernel/setup.c中)

R6=__atags_pointer(dtb指针的地址,其变量定义在arch/arm/kernel/setup.c中)

R7=cr_alignment(cp15的c1寄存器的值的地址,也就是mmu控制寄存器的值,其变量定义在arch/arm/kernel/entry-armv.S中)

sp=init_thread_union + THREAD_START_SP(init_thread_union可在System.map中获取,笔者的是0x809e6000,这样一来相当于SP的初值是0x809e6000 + 0x2000 - 8)

第97~98行:thumb指令的实现,意义同第86行,同时只有一处生效

第99行:把cpu处理器id(r9)放到processor_id变量中

第100行:把mechine id(r1)存放到__machine_arch_type变量中

第101行:把dtb的地址指针(r2)存放到__atags_pointer变量中(此地址为物理地址,使用需转换)

第102~103行:把cp15的c1的寄存器的值(r0)存放到cr_alignment变量中

第104行:跳转到start_kernel开始启动内核

注:系统一复位就处于SVC模式。CPSR当前程序状态寄存器来切换ARM模式。ARM有9种模式:

User:用户模式,非特权模式,大部分程序运行的时候就处于此模式

FIQ:快速中断模式,进入 FIQ 中断异常

IRQ:一般中断模式,进入 IRQ 中断异常

Supevisor(SVC):超级管理员模式,复位或者一个 Supervisor 指令调用

Monitor(MON):监听模式,用户安全扩展模式

Abort(ABT):数据访问中止模式,用户虚拟存储及存储保护

Hyp(HYP):用于虚拟化扩展

Undef(UND):未定义的指令终止模式

System(SYS):系统模式,用于运行特权级的操作系统任务

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值