平台:Xilinx Zynq SoC上的ARM Cortex A9上的Linux。
我问了一个问题:Why is kernel boot starting too late
基本上我试图了解并最小化这两个事件之间的延迟:
[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语句放在很多地方但是所有的thsoe都在上面"启动内核......"或者在#34;在物理CPU 0x0和#34上启动Linux,所以我在这个讨论中忽略它。我也使用ftrace来查看热点,但它没有报告u-boot功能)。
我在bootm.c"中的boot_jump_linux中观察到"在kernel_entry下面。永远不会打印在日志消息中的任何位置。这表明在函数kernel_entry(0,machid,r2)之后控件不会返回;之所以被调用,是因为linux现在已经控制并正在执行。
所以我的目标是知道在这两个事件中正在执行哪个功能。
现在要了解发生了什么(即使在插入我的printf / printk消息后仍未清楚)我问了以下问题:
1- In u-boot, kernel_entry points to which function?
2- Trying to understand the usage of function pointer
基于那里的答案,我怀疑我的热点,即花费很多时间的代码位于以下文件之一:
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
完整日志为here。
有人可以在这方面让我高兴吗?
非常感谢提前!!
答案 0 :(得分:3)
我的目标是尽可能快地进行切换 您是否认为使用早期的printk我可以更快地启动,因为切换会很早?
你的问题和你的计算方法"快速"或者"延迟"基于有缺陷的数据。
您认为0.5秒"延迟"实际上是U-Boot在 实时 中输出"启动内核..." ,而内核 缓冲 和 推迟 输出"引导Linux" 直到系统和控制台已初始化。这是将苹果与橙子进行比较 至少你必须通过启用早期printk 让内核以 实时 (就像U-Boot)输出。然后您的时间戳将更好地指示实际经过的时间。
摘自chapter 18 of the Linux Kernel Map(我强调):
确实存在printk()的坚固性。 它在内核启动过程中的某个点之前无法使用,在控制台初始化之前。实际上,如果控制台未初始化,输出应该在哪里?< / p>
这通常不是问题,除非您在引导过程中很早就调试问题(例如,在setup_arch()中执行特定于体系结构的初始化)。这样的调试是一个挑战,并且缺少任何类型的打印方法只会使问题复杂化。
有一些希望,但不是很多。硬核架构黑客使用可以工作的硬件(比如串口)与外界进行通信。相信我这对大多数人来说并不好玩。一些受支持的架构确实实现了一个理智的解决方案,然而其他(包括i386)有可用的补丁,也可以节省一天。
解决方案是一个printk()变种,可以在启动过程的早期输出到控制台:early_printk()。行为与printk()相同,只有名称及其名称早期工作的能力发生了变化。然而,这不是可移植的解决方案,因为并非所有支持的体系结构都实现了这样的方法。但是,如果确实如此,它可能会成为你最好的朋友。
有关启用早期printk 的详细信息,请参阅this answer相同的问题(由您的双胞胎?)。
所以不,使用早期printk 不会改善&#34;切换&#34;或整体开机时间 但它应该有助于防止您查找幻像阻塞。
答案 1 :(得分:0)
我想知道可以发生什么
。您通过指向其他功能的函数指针显示直接函数调用。
我不知道除了中断代码之外的任何事情都会干扰它。
所花费的时间是600毫秒,这不是很多,但当然在很多情况下都很明显(特别是在Zynq相关的地方)。
要调查的事项:
[Sat Apr 12 19:33:51.298 2014] I am the first statement in start_kernel in main.c
&#34; (82字节)到9600 bps的阻塞串行端口大约需要83 ms。