如何优化U-boot到内核的交接代码? [英] How to optimize U-boot to kernel hand-off code?

查看:79
本文介绍了如何优化U-boot到内核的交接代码?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

平台:Xilinx Zynq SoC上的ARM Cortex A9上的Linux.

我问了一个问题:为什么内核启动开始得太晚了

基本上,我试图理解然后最小化这两个事件之间的延迟:

[Sat Apr 12 19:33:50.692 2014] Starting kernel ...
[Sat Apr 12 19:33:50.692 2014] 
[Sat Apr 12 19:33:51.298 2014] Booting Linux on physical CPU 0x0

第一行告诉我们现在正在将控件提供给内核,而第二行告诉我们现在该控件与内核一起并由CPU执行.

这种从u-boot到内核的过渡对我们的应用程序来说花费了太多时间.

要了解这两个事件之间发生了什么,我在以下位置插入了printf语句:

1- bootm.c

我将以下行放在函数static void boot_jump_linux(bootm_headers_t *images, int flag)

的末尾

         }
        if (!fake)
               {printf("above kernel_entry in boot_jump_linux in bootm.c\n");
                kernel_entry(0, machid, r2);
                printf("below kernel_entry boot_jump_linux in bootm.c\n");

               }
}

2- main.c

我将这样的语句放在start_kernel函数中:

asmlinkage void __init start_kernel(void)
{
  printk("I am the first statement in start_kernel in main.c" );
        char * command_line;
        extern const struct kernel_param __start___param[], __stop___param[];

然后我编译了u-boot和内核,新的日志消息包含以下几行:

[Sat Apr 12 19:33:50.692 2014] Starting kernel ...
[Sat Apr 12 19:33:50.692 2014] above kernel_entry in boot_jump_linux in bootm.c

[Sat Apr 12 19:33:51.298 2014] I am the first statement in start_kernel in main.c 
[Sat Apr 12 19:33:51.298 2014] Booting Linux on physical CPU 0x0

(事实上,我在许多地方都放置了printf语句,但是所有这些消息都在启动内核..."上方或在物理CPU 0x0上引导Linux"下方出现,因此在本次讨论中我将其忽略.我也使用了ftrace查看热点,但未报告u-boot函数).

我观察到在bootm.c的boot_jump_linux中的kernel_entry下面"从未在日志消息中的任何位置打印.这表明控件在函数kernel_entry(0,machid,r2);之后不会返回;之所以称为,是因为linux现在具有控件并正在执行.

所以我的目的是要知道在这两个事件中正在执行哪个功能.

现在要了解发生了什么(即使在插入我的printf/printk消息后仍不清楚),我问了以下问题:

1- 在u-boot,kernel_entry指向哪个功能?

2- 尝试了解函数的用法指针

基于答案,我怀疑我的热点(即花费大量时间的代码)位于以下文件之一中:

1- https://github .com/Xilinx/linux-xlnx/blob/master/arch/arm/kernel/head.S

2- https://github.com/Xilinx/linux-xlnx/blob/master/arch/arm/kernel/head-common.S

3- https://github.com/Xilinx/linux-xlnx/blob/master/arch/arm/boot/compressed/head.S

我的问题:

1-我的理解是否正确,我应该专注于上述文件?

2-调用kernel_entry(0, machid, r2);后,控制转到上面的代码和哪一行?

我怀疑文件 https://github.com/Xilinx/linux-xlnx/blob/master/arch/arm/boot/compressed/head.S 对我来说这是没有用的,因为这是解压缩所必需的,但是我的内核已经解压缩了,因为可以在u-boot日志中很早地看到以下行:

[Sat Apr 12 19:33:50.596 2014]    Uncompressing Kernel Image ... OK

完整日志位于此处.

有人可以在这方面启发我吗?

非常感谢!!

解决方案

我的目标是尽可能快地进行交接.
您是否认为使用早期的printk可以更快地启动,因为交接会更早?

您的问题和计算快速"或延迟"的方法均基于有缺陷的数据.

您认为0.5秒的延迟"实际上是U-Boot在 实时 中输出正在启动内核..." ,而内核 缓冲区 推迟 输出其启动Linux" 直到系统和控制台已初始化.那是将苹果与桔子进行比较.
至少必须通过启用 early printk 使内核能够 实时 输出(就像U-Boot一样).然后,您的时间戳会更好地指示实际经过的时间.

摘录自 Linux内核映射的第18章(重点由我添加):

确实存在printk()的鲁棒性缺陷. 在控制台启动之前控制台初始化之前,它是不可用的.确实,如果未初始化控制台,输出应该放在哪里? /p>

通常这不是问题,除非您在引导过程的早期就调试问题(例如,在setup_arch()中执行特定于体系结构的初始化).首先,这样的调试是一个挑战,而缺少任何一种打印方法只会使问题更加复杂.

有一些希望,但没有很多.核心架构黑客使用确实有效的硬件(例如,串行端口)与外界进行通信.相信我,这对于大多数人来说不是一件好事.一些受支持的体系结构确实实现了合理的解决方案,但是,其他(包括i386)具有可用的补丁程序,这些补丁程序也可以节省时间.

解决方案是一个printk()变体,可以在启动过程的早期就输出到控制台:early_printk().该行为与printk()相同,只是名称和名称相同.较早工作的能力已更改.但是,这不是便携式解决方案,因为并非所有受支持的体系结构都实现了这种方法.如果可以的话,它可能成为您最好的朋友.

对于同一问题,请参见此答案(由您的双胞胎?)以了解有关启用早期printk 的详细信息.

因此,不可以,使用早期printk 不会改善移交"或总体启动时间.
但这应该有助于防止您寻找 phantom 障碍物.

Platform: Linux on ARM Cortex A9 on Xilinx Zynq SoC.

I asked a question : Why is kernel boot starting too late

Basically I am trying to understand and then minimize the delay between these two events:

[Sat Apr 12 19:33:50.692 2014] Starting kernel ...
[Sat Apr 12 19:33:50.692 2014] 
[Sat Apr 12 19:33:51.298 2014] Booting Linux on physical CPU 0x0

The first line tells that the control is being given to the kernel now, while thesecond line tells that the control is now with the kernel and is being executed by the CPU.

This hand-off from u-boot to kernel is taking too much time for our application.

To understand what is going on between these two events I inserted printf statements in:

1- bootm.c

I put the following line at the end of the function static void boot_jump_linux(bootm_headers_t *images, int flag)

         }
        if (!fake)
               {printf("above kernel_entry in boot_jump_linux in bootm.c\n");
                kernel_entry(0, machid, r2);
                printf("below kernel_entry boot_jump_linux in bootm.c\n");

               }
}

2- main.c

I put my statement like this in the start_kernel function:

asmlinkage void __init start_kernel(void)
{
  printk("I am the first statement in start_kernel in main.c" );
        char * command_line;
        extern const struct kernel_param __start___param[], __stop___param[];

Then I compiled the u-boot and kernel and the new log message has the following lines:

[Sat Apr 12 19:33:50.692 2014] Starting kernel ...
[Sat Apr 12 19:33:50.692 2014] above kernel_entry in boot_jump_linux in bootm.c

[Sat Apr 12 19:33:51.298 2014] I am the first statement in start_kernel in main.c 
[Sat Apr 12 19:33:51.298 2014] Booting Linux on physical CPU 0x0

(In fact I put printf statements at many places but all thsoe are comming either above "starting kernel..." or below "Booting Linux on physical CPU 0x0", so I am ignoring it in this discussion. I also used ftrace to see the hotspot, but it is not reporting u-boot functions).

I observed that "below kernel_entry in boot_jump_linux in bootm.c" is never printed anywhere in the log message. This shows that the control will not return after function kernel_entry(0, machid, r2); is called because the linux has now the control and is being executed.

So my aim is to know which function is being executed during these two events.

Now to understand what is happening (which not yet clear even after inserting my printf/printk messages) I asked the following questions:

1- In u-boot, kernel_entry points to which function?

2- Trying to understand the usage of function pointer

Based on the answers there I am suspecting that my hot spot i.e the code taking much time is located in one of the following files:

1- https://github.com/Xilinx/linux-xlnx/blob/master/arch/arm/kernel/head.S

2- https://github.com/Xilinx/linux-xlnx/blob/master/arch/arm/kernel/head-common.S

3- https://github.com/Xilinx/linux-xlnx/blob/master/arch/arm/boot/compressed/head.S

My questions:

1- Is my understanding correct that I should focus on the above files ?

2- After the call to kernel_entry(0, machid, r2); is made, the control goes to which of the above code and which line?

I am suspecting the file https://github.com/Xilinx/linux-xlnx/blob/master/arch/arm/boot/compressed/head.S is of no use to me since this is required for decompression, but my kernel is already decompressed, since the following line can be seen much early in u-boot log:

[Sat Apr 12 19:33:50.596 2014]    Uncompressing Kernel Image ... OK

The full log is here.

Can someone enlight me in this regard ?

Many thanks in advance!!

解决方案

My aim is to have the handoff as fast as possible.
Do you think using early printk I can boot faster as the handoff will be early?

Your question and your method of calculating "fast" or "delayed" are based on flawed data.

What you think is a 0.5 sec "delay" is actually U-Boot outputting "Starting kernel ..." in real time, while the kernel buffers and postpones outputting its "Booting Linux" until the system and console are initialized. That's comparing apples to oranges.
At the very least you have to get the kernel to output in realtime (just like U-Boot) by enabling early printk. Then your timestamps will better indicate actual elapsed time.

An excerpt from chapter 18 of the Linux Kernel Map (emphasis added by me):

A chink in the armor of printk()'s robustness does exist. It is unusable before a certain point in the kernel boot process, prior to console initialization. Indeed, if the console is not initialized, where is the output supposed to go?

This is normally not an issue, unless you are debugging issues very early in the boot process (for example, in setup_arch(), which performs architecture-specific initialization). Such debugging is a challenge to begin with, and the absence of any sort of print method only compounds the problem.

There is some hope, but not a lot. Hardcore architecture hackers use the hardware that does work (say, a serial port) to communicate with the outside world. Trust me this is not fun for most people. Some supported architectures do implement a sane solution, however and others (i386 included) have patches available that also save the day.

The solution is a printk() variant that can output to the console very early in the boot process: early_printk(). The behavior is the same as printk(), only the name and its capability to work earlier are changed. This is not a portable solution, however, because not all supported architectures have such a method implemented. It might become your best friend, though, if it does.

See this answer to the identical question (by your twin?) for details on enabling early printk.

So no, using early printk will not improve the "handoff" or overall boot time.
But it should help prevent you from looking for phantom blockages.

这篇关于如何优化U-boot到内核的交接代码?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆