如何解决“致命的:内核太老了"?在syscall仿真SE模式下运行gem5时? [英] How to solve "FATAL: kernel too old" when running gem5 in syscall emulation SE mode?

查看:94
本文介绍了如何解决“致命的:内核太老了"?在syscall仿真SE模式下运行gem5时?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

Ubuntu 17.10,C程序:

#include <stdio.h>
#include <stdlib.h>

int main(void) {
    puts("hello");
    return EXIT_SUCCESS;
}

gem5版本:da79d6c6cde0fbe5473ce868c9be4771160a003b 2017年12月

GCC版本:

$ sudo apt-get install gcc-arm-linux-gnueabi
$ arm-linux-gnueabi-gcc --version
arm-linux-gnueabi-gcc (Ubuntu/Linaro 7.2.0-6ubuntu1) 7.2.0

编译并运行:

./gem5/gem5/build/ARM/gem5.opt ./gem5/gem5/configs/example/se.py -c ./a.out
arm-linux-gnueabi-gcc -static kernel_module/user/hello.c

结果:

gem5 Simulator System.  http://gem5.org             
gem5 is copyrighted software; use the --copyright option for details.                                    

gem5 compiled Feb 23 2018 05:25:49                  
gem5 started Feb 24 2018 04:10:38                   
gem5 executing on ciro-p51, pid 3092                
command line: ./gem5/gem5/build/ARM/gem5.opt ./gem5/gem5/configs/example/se.py -c ./a.out                

Global frequency set at 1000000000000 ticks per second                                                   
warn: DRAM device capacity (8192 Mbytes) does not match the address range assigned (512 Mbytes)          
0: system.remote_gdb.listener: listening for remote gdb #0 on port 7000                                  
**** REAL SIMULATION ****                           
info: Entering event queue @ 0.  Starting simulation...                                                  
FATAL: kernel too old                               
warn: ignoring syscall rt_sigprocmask(...)          
      (further warnings will be suppressed)         
fatal: syscall gettid (#224) unimplemented.         
Memory Usage: 659680 KBytes 

类似于X86.

这个问题已经在邮件列表中一遍又一遍地询问,所以让我们在这里集中讨论并确定最佳解决方案.

https://www.mail-archive.com/gem5-users@gem5.org/msg12385.html 提供了一个很好的问题描述:

_start()开始之后不久,C库发出了uname() syscall验证最低内核版本. 如果您查看gem5/src/arch/arm/linux/process.cc http://process.cc ,将要 看到在32位模式下,仿真的syscall返回"3.0.0",而在64位模式下, "3.7.0+". 在crosstool-ng中配置工具链时,有一个选项 "CT_LIBC_GLIBC_MIN_KERNEL_VERSION". 如果该值大于模拟的uname()报告的值,则glibc将致命().

我注意到,如果我使用魔术树内斑点:

tests/test-progs/hello/bin/arm/linux/hello

那么那个blob有什么特别之处,以及它是如何产生的?

允许在源代码上使用源版本

823d9d177fded16af07114d70b5c26caaec6aa00告诉我们,伪造的内核版本定义的x86点是

类似的grepping告诉我们,第32组的臂数为3.0,而第64组的臂数为3.7.0.

crosstool-ng次尝试

一种有前途的可能性是使用crosstool-ng https://github.com/crosstool- ng/crosstool-ng 生成编译器,这使事情得到了更好的控制.

从ab3c204aee88f08481f1f63825d0e94b082ef84e开始,我尝试了以下两个配置:

  • ./ct-ng arm-cortex_a15-linux-gnueabihf
  • ./ct-ng aarch64-unknown-linux-gnu

使用GCC 8.1为内核4.16编译,然后在gem5 49f96e7b77925837aa5bc84d4c3453ab5f07408e上的静态编译失败,分别为:

fatal: syscall openat (#322) unimplemented.

和:

panic: Attempted to execute unimplemented instruction 'mrs' (inst 0x4d5380000)

但是我真的不理解任何失败:

尝试使用不同的crosstool-ng设置(特别是目标内核版本)也很有趣,该版本在该版本中默认为最新的v4.16,以查看是否解决了系统调用问题.

已于2018年5月在gem5 49f96e7b77925837aa5bc84d4c3453ab5f07408e上进行测试.

解决方案

更新gem5 May 2019

合并补丁后 https://gem5-review .googlesource.com/c/public/gem5/+/17849 现在可以通过以下方式简单地解决"该问题:

gem5.opt se.py --param 'system.cpu[0].workload[:].release = "4.18.0"'

然后,您应该设置与您的工具链或更高版本匹配的内核版本.

我不知道如何轻松找到Ubuntu预构建跨工具链的最小值,但是您可以尝试设置最新的内核版本,或者也许是99.99.99.

版本太新可能会导致glibc使用尚未在gem5中实现的可选新内核功能,但这是不常见的.

Ubuntu 18.04 with gem5 Oct 2018

最近对gem5进行了一些更新之后,所有x86,arm,aarch64的C hello世界都可以与预包装的Ubuntu工具链一起使用.有关详细信息,请参见:如何在带有se.py的gem5 syscall仿真模式下编译和运行可执行文件?

当然,在更复杂的程序上的其他未实现的系统调用注定会失败.

Ubuntu 17.10, C program:

#include <stdio.h>
#include <stdlib.h>

int main(void) {
    puts("hello");
    return EXIT_SUCCESS;
}

gem5 version: da79d6c6cde0fbe5473ce868c9be4771160a003b dec 2017

GCC version:

$ sudo apt-get install gcc-arm-linux-gnueabi
$ arm-linux-gnueabi-gcc --version
arm-linux-gnueabi-gcc (Ubuntu/Linaro 7.2.0-6ubuntu1) 7.2.0

Compile and run:

./gem5/gem5/build/ARM/gem5.opt ./gem5/gem5/configs/example/se.py -c ./a.out
arm-linux-gnueabi-gcc -static kernel_module/user/hello.c

Outcome:

gem5 Simulator System.  http://gem5.org             
gem5 is copyrighted software; use the --copyright option for details.                                    

gem5 compiled Feb 23 2018 05:25:49                  
gem5 started Feb 24 2018 04:10:38                   
gem5 executing on ciro-p51, pid 3092                
command line: ./gem5/gem5/build/ARM/gem5.opt ./gem5/gem5/configs/example/se.py -c ./a.out                

Global frequency set at 1000000000000 ticks per second                                                   
warn: DRAM device capacity (8192 Mbytes) does not match the address range assigned (512 Mbytes)          
0: system.remote_gdb.listener: listening for remote gdb #0 on port 7000                                  
**** REAL SIMULATION ****                           
info: Entering event queue @ 0.  Starting simulation...                                                  
FATAL: kernel too old                               
warn: ignoring syscall rt_sigprocmask(...)          
      (further warnings will be suppressed)         
fatal: syscall gettid (#224) unimplemented.         
Memory Usage: 659680 KBytes 

Analogous on X86.

This has been asked over and over on the mailing lists, so let's centralize the discussion here and determine the best solution.

https://www.mail-archive.com/gem5-users@gem5.org/msg12385.html provides a good problem description:

Shortly after the beginning of _start(), the C library issues the uname() syscall to verify for the minimum kernel version. If you look at gem5/src/arch/arm/linux/process.cchttp://process.cc, you will see that in 32-bit mode the emulated syscall returns "3.0.0" and in 64, "3.7.0+". When you configured the toolchain in crosstool-ng, there is an option "CT_LIBC_GLIBC_MIN_KERNEL_VERSION". If that's greater than what the emulated uname() reports, glibc will fatal().

I have noticed that if I use the magic in-tree blob:

tests/test-progs/hello/bin/arm/linux/hello

so what is special about that blob, and how was it generated?

Allowed source version on the source code

823d9d177fded16af07114d70b5c26caaec6aa00 teaches us that the x86 point where the fake kernel version is defined is src/arch/x86/linux/process.cc.

unameFunc(SyscallDesc *desc, int callnum, Process *process,
    ...
    strcpy(name->release, "3.2.0");

Analogous grepping tells us that arm 32 was at 3.0 and 64 at 3.7.0.

crosstool-ng attempts

One promising possibility is to use crosstool-ng https://github.com/crosstool-ng/crosstool-ng to generate the compiler, which makes things more controlled.

As of ab3c204aee88f08481f1f63825d0e94b082ef84e I tried both of the following configs:

  • ./ct-ng arm-cortex_a15-linux-gnueabihf
  • ./ct-ng aarch64-unknown-linux-gnu

which compile for kernel 4.16 with GCC 8.1, and then static compilation fails on gem5 49f96e7b77925837aa5bc84d4c3453ab5f07408e respectively with:

fatal: syscall openat (#322) unimplemented.

and:

panic: Attempted to execute unimplemented instruction 'mrs' (inst 0x4d5380000)

but I don't really understand any of the failures:

  • openat was introduced in much older kernel 2.6.16, and it does not seem so exotic so why wouldn't it be implemented yet?

    We then can see on the source that it is implemented for 64 bit but is not implemented for 32 bit for some reason.

    I also tried to set the arm minimum kernel version to 3.2, but unsurprisingly it did not help.

  • why an instruction mrs wouldn't be implemented? The ARM reference says this instruction encoding ends in:

    1 1 0 1 0 1 0 1 0 0 1 1
    

    which is:

    d 5 2
    

    so maybe it matches the 0x4d5380000, but I'm not sure.

It would also be interesting to play around with different crosstool-ng settings, in particular the target kernel version, which at that revision defaults to the latest v4.16 to see if it solves the syscall problem.

Tested on gem5 49f96e7b77925837aa5bc84d4c3453ab5f07408e May 2018.

解决方案

update gem5 May 2019

After the merging of the patch https://gem5-review.googlesource.com/c/public/gem5/+/17849 it is now possible to "fix" the problem simply with:

gem5.opt se.py --param 'system.cpu[0].workload[:].release = "4.18.0"'

You should then set a kernel version that matches your toolchain or newer.

I don't know how to find the minimal value easily for Ubuntu prebuild cross toolchains, but you could just try setting the newest kernel release, or maybe 99.99.99.

A version being too new might result in glibc using optional new kernel features not yet implemented in gem5, but this is not common I believe.

Ubuntu 18.04 with gem5 Oct 2018

After a few recent gem5 updates, a C hello world for all of x86, arm, aarch64 works with the pre-packaged Ubuntu toolchains. This is described in detail at: How to compile and run an executable in gem5 syscall emulation mode with se.py?

crosstool-ng x86_64-unknown-linux-gnu

Worked with gem5 49f96e7b77925837aa5bc84d4c3453ab5f07408e, ct-ng ab3c204aee88f08481f1f63825d0e94b082ef84e. Generates executables for old Linux kernel 3.2 according to file for some reason.

uclibc

This is likely a bad idea, but if we use crosstool-ng with uclibc instead of glibc:

./ct-ng aarch64-unknown-linux-uclibc

then that implementation does not have a kernel check, and the hello world works for all archs.

Also for some reason mrs was not used in that case because glibc tends to use more features on it's pre-main functions. That problem was however solved on a later commit as mentioned at: How to compile and run an executable in gem5 syscall emulation mode with se.py?

Of course, other unimplemented syscalls on more complex programs are bound to fail.

这篇关于如何解决“致命的:内核太老了"?在syscall仿真SE模式下运行gem5时?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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