Chinaunix首页 | 论坛 | 博客
  • 博客访问: 35262
  • 博文数量: 10
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 117
  • 用 户 组: 普通用户
  • 注册时间: 2013-10-16 17:17
个人简介

_勇

文章分类
文章存档

2013年(10)

我的朋友

分类: LINUX

2013-10-16 17:53:58

linux内核运行前先运行bootloader。龙芯启动时,是从地址0xbfc00000处开始执行,bootloader就是位于此处。
bootloader将内核文件(例如,zImage)拷贝到内存,然后跳转到这个内存中的内核处运行。
/**************************************************************************************/
1b-linux-3.0的内核第一个运行的文件是arch\mips\boot\compressed\head.S。
LEAF(start)
start:
/* 保存bootloader传递的四个函数参数a0,a1,a2,a3 */
move s0, a0
move s1, a1
move s2, a2
move s3, a3
 /* 将地址从_edata到_end的BSS段清零 */
PTR_LA a0, _edata
PTR_LA a2, _end
1: sw zero, 0(a0)
bne a2, a0, 1b
addiu a0, a0, 4
PTR_LA a0, (.heap)          /* 堆地址 */
PTR_LA  sp, (.stack + 8192)  /* 栈地址,供C函数用 */
PTR_LA ra, 2f    /* 函数返回地址是下面的 2: 处 */
/*调用C函数decompress_kernel解压kernel*/
PTR_LA k0, decompress_kernel 
jr k0
nop
/*将保存的bootloader参数恢复到a0,a1,a2,a3寄存器*/

2:
move a0, s0
move a1, s1
move a2, s2
move a3, s3
/*跳转到解压后的kernel_entry入口(在arch\mips\kernel\head.S文件)*/
PTR_LI k0, KERNEL_ENTRY
jr k0
nop
/*循环*/
3:
b 3b
nop
END(start)
/**************************************************************************************/

arch\mips\kernel\head.S文件:
NESTED(kernel_entry, 16, sp) #kernel_entry
kernel_entry_setup #cpu specific setup
setup_c0_status_pri #配置CP0状态寄存器
/* We might not get launched at the address the kernel is linked to,so we jump there.  ? */
PTR_LA t0, 0f
jr t0
0:
/*clear .bss*/
PTR_LA t0, __bss_start
LONG_S zero, (t0)
PTR_LA t1, __bss_stop - LONGSIZE
1:
PTR_ADDIU t0, LONGSIZE
LONG_S zero, (t0)
bne t0, t1, 1b

/*保存启动参数*/
LONG_S a0, fw_arg0
LONG_S a1, fw_arg1
LONG_S a2, fw_arg2
LONG_S a3, fw_arg3

MTC0 zero, CP0_CONTEXT # clear context register

/*配置和保存堆栈寄存器sp*/

PTR_LA $28, init_thread_union /*$28--gp寄存器*/
PTR_LI sp, _THREAD_SIZE - 32 - PT_SIZE
PTR_ADDU sp, $28
back_to_back_c0_hazard /*但是由于乱序执行的特点,很容易出现非预期行为,称为CP0 hazard。软件解决方法:(1)插入足够多的nop指令(2)ehb指令(3)SSNOP指令也值得注意,它可以自动知道需要停顿的周期数*/
set_saved_sp sp, t0, t1
PTR_SUBU sp, 4 * SZREG # init stack pointer
 
/*跳转到start_kernel()*/
j start_kernel
END(kernel_entry)

/**************************************************************************************/
/*与back_to_back_c0_hazard有关的定义*/
#define ASMMACRO(name, code...) \
__asm__(".macro " #name "; " #code "; .endm"); \
\
static inline void name(void) \
{ \
__asm__ __volatile__ (#name); \
}

ASMMACRO(_ssnop,
sll $0, $0, 1
)

ASMMACRO(back_to_back_c0_hazard,
_ssnop; _ssnop; _ssnop;
)

阅读(1300) | 评论(0) | 转发(0) |
0

上一篇:linux

下一篇:linux系统初始化-start_kernel()

给主人留下些什么吧!~~