run_init_process 挂死,请教大侠!!

weileng 2007-04-03 09:12:09
在移植Linux 2.6.17的内核到PNX8950(MIPS架构)上,出现Init程序挂死。
文件系统采用CPIO格式,由BusyBox 1.2.1得到,编译到内核中。
交叉工具链由Buildroot构建,采用uClib库。

单板启动到“Freeing unused kernel memory: 972k freed”后,挂死;

跟踪Linux 2.6.17的内核启动代码:

static int init(void * unused)
{
。。。。。。

if (sys_open((const char __user *) "/dev/console", O_RDWR, 0) < 0) <------运行正常
printk(KERN_WARNING "Warning: unable to open an initial console.\n");

。。。。。。

if (execute_command) {
run_init_process(execute_command); <--------挂死位置, execute_command值“/init", 在BusyBox做文件系统时,init已链接到/sbin/init;
printk(KERN_WARNING "Failed to execute %s. Attempting "
"defaults...\n", execute_command);
}

run_init_process("/sbin/init");
run_init_process("/etc/init");
run_init_process("/bin/init");
run_init_process("/bin/sh");

panic("No init found. Try passing init= option to kernel.");
}

经过定位,调用关系如下:

run_init_process->execve->sys_execve->do_execve->search_binary_handler->load_elf_binary

在 load_elf_binary挂掉,仔细分析过程,发现load_elf_binary函数的padzero时挂死,加上调试代码,代码片断如下:
static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
{

。。。。。。
loc->elf_ex.e_entry += load_bias;
elf_bss += load_bias;
elf_brk += load_bias;
start_code += load_bias;
end_code += load_bias;
start_data += load_bias;
end_data += load_bias;

printk(KERN_WARNING "loc->elf_ex.e_entry :0x%8x\n", loc->elf_ex.e_entry);
printk(KERN_WARNING "load_bias: 0x%8x\n", load_bias);
printk(KERN_WARNING "elf_bss: 0x%8x\n", elf_bss);
printk(KERN_WARNING "elf_brk: 0x%8x\n", elf_brk);
printk(KERN_WARNING "start_code: 0x%8x\n", start_code);
printk(KERN_WARNING "end_code: 0x%8x\n", end_code);
printk(KERN_WARNING "start_data: 0x%8x\n", start_data);
printk(KERN_WARNING "end_data: 0x%8x\n", end_data);

/* Calling set_brk effectively mmaps the pages that we need
* for the bss and break sections. We must do this before
* mapping in the interpreter, to make sure it doesn't wind
* up getting placed where the bss needs to go.
*/
retval = set_brk(elf_bss, elf_brk); <-----------mmap成功
printk(KERN_WARNING "retval: 0x%8x\n", retval);

if (retval) {
send_sig(SIGKILL, current, 0);
goto out_free_dentry;
}

if (likely(elf_bss != elf_brk) && unlikely(padzero(elf_bss))) { <-------调用padzero时死掉
send_sig(SIGSEGV, current, 0);
retval = -EFAULT; /* Nobody gets to see this, but.. */
goto out_free_dentry;
}
。。。。。。。。

其中printk是加入的调试代码,调试中显示结果如下:

loc->elf_ex.e_entry :0x 400100
load_bias: 0x 0
elf_bss: 0x 4ed7e0
elf_brk: 0x 507f00
start_code: 0x 400000
end_code: 0x 4a9bf0
start_data: 0x 4ea000
end_data: 0x 4ed7e0
retval: 0x 0

后分析跟踪padzero函数代码,定位到__clear_user函数中在汇编代码处挂掉:

static inline __kernel_size_t
__clear_user(void __user *addr, __kernel_size_t size)
{
__kernel_size_t res;

printk(KERN_WARNING "In Function: %s\n", __FUNCTION__); //debug by ljq
printk(KERN_WARNING "Address_Start: 0x%8x Size: 0x%8x\n", (int)addr, (int)size);

might_sleep();

#if 0
__asm__ __volatile__(
"move\t$4, %1\n\t"
"move\t$5, $0\n\t"
"move\t$6, %2\n\t"
__MODULE_JAL(__bzero)
"move\t%0, $6"
: "=r" (res)
: "r" (addr), "r" (size)
: "$4", "$5", "$6", __UA_t0, __UA_t1, "$31");
#else
{
char *xs = addr;

while (size--)
*xs++ = 0;
}

res = 0;
#endif
printk(KERN_WARNING "res: %d\n", (int)res);
printk(KERN_WARNING "Exit Function: %s\n", __FUNCTION__);

return res;
}

改写__clear_user函数,保持功能一致(也不知道这样改写行不行);并加进调试信息,调试显示信息如下:
In Function: debug__clear_user
Address_Start: 0x 4ed7e0 Size: 0x 820
还是跑飞。

定位分析是在操作地址0x4ed7e0时跑飞,该地址在MIPS架构中KSEG段,处于User Mode状态;
令人感到疑惑的是:
在load_elf_binary函数中set_brk进行页面mmap成功后,应该可以直接访问,而不应该跑飞,请各位大侠给出些帮助,莫大感激,此问题困窘已久。

个人试着进行了以下几个方面试验,但没有得到解决:
1、BusyBox编译时采用静态(以前是动态编译的);
2、完全屏蔽__clear_user代码,虽然最后load_elf_binary可以成功退出,但是run_init_process依旧没有启动shell(/bin/sh),此时串口工作良好;
3、改写BusyBox的Init为简单Hello World程序,可以打印出”Hello World“字符,当时随后就出现系统panic;
...全文
2572 28 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
28 条回复
切换为时间正序
请发表友善的回复…
发表回复
weileng 2010-08-11
  • 打赏
  • 举报
回复
具体问题还得具体分析,我所遇到的挂死是没有异常的或者panic,只是跑飞。如果你能够把Log以及panic的信息贴出来,看能不能帮你分析。

给你一个相应的参考:
http://fixunix.com/kernel/343438-patch-elf-loader-crash-while-zero-filling-bss.html
dfysy 2010-06-28
  • 打赏
  • 举报
回复
你好,我现在往一个ARM处理器上移植Linux遇到和你一样的问题,也是到相同的地方就返回EFAULT了,我想请问一下你说的Kernel TLB初始化是哪里,是paging_init吗?我看那些代码都是ARM公用的,实在无法下手。你能介绍一下你是怎么解决的吗?或者给我一点建议。万分感谢
weileng 2009-02-19
  • 打赏
  • 举报
回复
是Kernel TLB的初始化。
liawcb 2007-06-27
  • 打赏
  • 举报
回复
请问是在bootloader还是kernel TLB的初始化有问题?谢谢!
weileng 2007-04-28
  • 打赏
  • 举报
回复
谢谢大家的关照。该问题终于找到原因了,问题出在TLB的初始化。PNX8550移植过程中对TLB的初始化处理不当,造成这种不稳定。
无知者无谓 2007-04-26
  • 打赏
  • 举报
回复
我也没看你的代码
根据个人经验是你配置的内核跟busybox有冲突了,你可以重新配置一下你的内核,多尝试几次,就OK了
之前我碰到过在启动/bin/sh时会出错,跟踪发现是在setjmp处一直没有返回。一直没有弄明白是什么回事,最后发现是自己更改了一次内核配置,更回来又是可用了。
weileng 2007-04-24
  • 打赏
  • 举报
回复
可能你没有仔细读上面的代码吧,原因在于从内核引导第一个用户进程时出错,这其中包括挂接文件系统以及用户空间的初始化;简单“Hello World”,可以执行,说明用户空间基本正常;造成这个不稳定的因素,可能是MIPS的Cache或者TLB Entry的初始化出问题。你好像还没有分析到要害部位阿。
yrj 2007-04-23
  • 打赏
  • 举报
回复
Application 怎么可以用printk呢?你这个地址又是什么安全吗?
weileng 2007-04-23
  • 打赏
  • 举报
回复
->Application 怎么可以用printk呢?你这个地址又是什么安全吗?

这段代码是内核启动用户进程的阶段,还在内核空间内,故用printk阿;这个地址是在TLB初始化完后,处于KSEG段,属于安全的。
yrj 2007-04-23
  • 打赏
  • 举报
回复
我建议在用户进程测试,你不是能够启动第一个用户经常吗?
weileng 2007-04-20
  • 打赏
  • 举报
回复
To rong818:

我的平台是PNX8950,是MIPS体系结构,在make ARCH=mips CC=${CROSS_COMPILE_GCC} menuconfig,没有这个选项的;对于S3C2410,为ARM 体系结构,make ARCH=arm CC=......, menuconfig时,就会有这个选项。可能MIPS体系结构默认就已经支持Math emulation功能了。
rong818 2007-04-20
  • 打赏
  • 举报
回复
我早些天碰到和你一样的问题,我的平台是S3C2410,也是freeing后就不动了,也是跟踪到这个函数发现跑飞了。但 是后来解决了。就是在对内核进行make menuconfig的时候,你一定要在General Setup中把那个NVFPE math emulation选上。我是这样就跑起来的,你试试吧。
weileng 2007-04-20
  • 打赏
  • 举报
回复
地址和长度为:
addr地址: 0x4ed7e0
size: 0x 820

不是用printf :), 用printk。我就是用printk定位到这个地方的。
yrj 2007-04-20
  • 打赏
  • 举报
回复
{
char *xs = addr;

while (size--)
*xs++ = 0; <-------- 此处跑飞
}

addr是什么地址?不要用这样的程序去测试啊,还是用printf的方式去测试吧。
weileng 2007-04-19
  • 打赏
  • 举报
回复
->怎么判断是你的内核跑飞了?你写一个APP,循环调用printf看能不能正常工作

在上面的代码中:

{
char *xs = addr;

while (size--)
*xs++ = 0; <-------- 此处跑飞
}

res = 0;

如果改写为:

{
char *xs = addr;

while (size--)
*xs++;
}

res = 0;

就会运行正常,相应的调试信息也会输出的。
yrj 2007-04-18
  • 打赏
  • 举报
回复
怎么判断是你的内核跑飞了?你写一个APP,循环调用printf看能不能正常工作
weileng 2007-04-18
  • 打赏
  • 举报
回复
->那你关掉TLB试试
该地址在MIPS架构中KSEG段,处于User Mode状态;而访问这个地址的前提是必须初始化TLB,不能关掉TLB的。

->我觉得是你作为console的串口驱动可能有问题,看看你的串口的中断处理,entry-macro.S中对串口的中断逻辑号的判断是否正确。

可能我的表述有问题吧,不是串口死掉了,是串口没有信息输出,串口中断处理是好的。只是内核跑飞了。
yrj 2007-04-18
  • 打赏
  • 举报
回复
那你关掉TLB试试,我觉得是你作为console的串口驱动可能有问题,看看你的串口的中断处理,entry-macro.S中对串口的中断逻辑号的判断是否正确。
weileng 2007-04-17
  • 打赏
  • 举报
回复
谢谢你的回复。

实验的结果表示Timer时钟没有死掉,但是串口死掉了。

BTW,怀疑TLB出问题是因为在mmap操作成功之后,系统对地址的访问就转化为虚拟地址到物理地址转换的过程,而TLB是这一转换的关键,如果此时出错,就会和TLB有关了。让人望洋兴叹的是,Mips的TLB操作甚是麻烦,不知道从何分析起。
yrj 2007-04-17
  • 打赏
  • 举报
回复
一般来说不会是TLB这种级别的问题,Port linux不用关心和具体SOC没有直接关系的代码
加载更多回复(8)

4,465

社区成员

发帖
与我相关
我的任务
社区描述
Linux/Unix社区 内核源代码研究区
社区管理员
  • 内核源代码研究区社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧