找对了入口,才有可能找对出口 – 佚名
在前面几节内容中我简单将Linux ,以及Linux Kernel的概念做了总结,然后又将编译以及内核镜像也做了也总结! 从本节内容开始,我将真正的进入到内核代码中去!加油吧,Keven!
从上一节中我已经知道了vmlinux.lds链接文件中指定了内核的入口函数kernel_entry,此函数被定义在head.S文件中!,请跟着我去看看此函数到底做了什么!
1、head.S - kernel_entry
NESTED(kernel_entry, 16, sp) # kernel entry point
kernel_entry_setup # cpu specific setup
setup_c0_status_pri
/* We might not get launched at the address the kernel is linked to,
so we jump there. */
PTR_LA t0, 0f #Loading 数字标号0中的地址
jr t0
0:
PTR_LA t0, __bss_start #Loading __bss_start(0xffffffff80dc0000) 到 t0
LONG_S zero, (t0) #对0xffffffff80dc0000这个地址内容清零(清除bss)
PTR_LA t1, __bss_stop - LONGSIZE #Loading __bss_stop(0xffffffff80dc0000 + 0x00cc2ac0 - unsinged(8)<0x40> 8*8) =
0xffffffff80106ae8 此地址就是kernel_entry函数地址 到 t1
1:
PTR_ADDIU t0, LONGSIZE #t0 = t0 + LONGSIZE (64位操作) = 0xffffffff80dc0000 + 0x40
LONG_S zero, (t0) #清零地址内容
bne t0, t1, 1b #判断 t0 是否等于 t1,如果不等于到当前位置前面的第一个标号1,循环加到等于后,执行下面指令
# firmware arguments
LONG_S a0, fw_arg0 #子程序的前4个参数存到a0~a3中
LONG_S a1, fw_arg1
LONG_S a2, fw_arg2
LONG_S a3, fw_arg3
MTC0 zero, CP0_CONTEXT # clear context register 清除 寄存器CP0的$4,这个寄存器保存的是页表的起始地址
PTR_LA $28, init_thread_union #将init_thread_union地址Loading $28中(Ps.$28是全局指针寄存器),关于全局指针见 Note 1:
/* Set the SP after an empty pt_regs. */
PTR_LI sp, _THREAD