最小的 Ubuntu 设置
首先要注意一件事:动态链接的可执行文件首先运行动态加载器,这意味着除了静态 ELF 的 pre main 内容之外还有更多的启动指令。因此,如果您有一个小型用户区测试,并且这种时间差恰好发生在“5 秒到 50 秒”的范围内,那么当您使用该测试用例迭代模拟器/测试用例补丁时,它可能会破坏您的生产力。例如,我观察到一个 C++ hello world 调试版本,其中 DerivO3CPU 在 6 秒内运行一个静态可执行文件,在 150 秒内运行一个动态可执行文件!
从 gem5 开始8162e0da0285d346046151b2a45ceeb1baf63b8f https://github.com/gem5/gem5/commit/8162e0da0285d346046151b2a45ceeb1baf63b8f2018 年 10 月,适用于所有 x86、arm 和 aarch64 的 C hello world 只能在 Ubuntu 16.04 和 18.04 上运行。 x86 之前可以工作,但该提交最终完成了一些必要的 Arm 更改以制作 glibc int 代码之前运行main https://electronics.stackexchange.com/questions/258896/what-happens-before-main/404298#404298好好工作。
给定 gem5 版本和 Ubuntu 版本之一,您可以运行以下 C 程序:
main.c
#include <stdio.h>
int main(int argc, char **argv) {
size_t i;
for (i = 0; i < (size_t)argc; ++i)
printf("%s\n", argv[i]);
return 0;
}
简单地说:
sudo apt-get install gcc
gcc -O0 -ggdb3 -std=c99 -static -o x86.out main.c
build/X86/gem5.opt \
configs/example/se.py \
-c x86.out \
-o 'asdf qwer' \
;
sudo apt-get install gcc-arm-linux-gnueabihf
arm-linux-gnueabihf-gcc -O0 -ggdb3 -std=c99 -static -o arm.out main.c
build/ARM/gem5.opt \
configs/example/se.py \
-c arm.out \
-o 'asdf qwer' \
;
sudo apt-get install gcc-aarch64-linux-gnu
aarch64-linux-gnu-gcc -O0 -ggdb3 -std=c99 -static -o aarch64.out main.c
build/ARM/gem5.opt \
configs/example/se.py \
-c aarch64.out \
-o 'asdf qwer' \
;
并且在所有情况下都会产生正确的输出:
asdf
qwer
-static
如以下所述,ARM 上需要:如何在gem5中运行动态链接的可执行系统调用模拟模式se.py? https://stackoverflow.com/questions/50542222/how-to-run-a-dynamically-linked-executable-syscall-emulation-mode-se-py-in-gem5尽管不再需要它,但它仍然需要更少的 CLI 选项并且更易于使用。
Ubuntu 交叉编译器安装也提到:如何使用 se.py 在 gem5 系统调用模拟模式下编译和运行可执行文件? https://stackoverflow.com/questions/53085048/how-to-compile-and-run-an-executable-in-gem5-syscall-emulation-mode-with-se-py/53085049#53085049
还有一些 gem5 树内用户示例,其中一些具有适当的交叉编译支持,位于tests/test-progs https://github.com/gem5/gem5/tree/9fc9c67b4242c03f165951775be5cd0812f2a705/tests/test-progs.
如果有人在较新的 gem5 版本或 Ubuntu 版本中发现这样的最小 C 程序无法在前面提到的架构之一中正确执行的设置,请发送一封电子邮件,详细描述您的系统设置到邮件列表并抄送给我。
缺少系统调用
当然,当您尝试运行更复杂的用户态程序时,您将不可避免地遇到未实现的系统调用,因为其中有很多。
请不要将这些报告为错误,除非它们出现在最小 C 示例的 glibc 设置代码中,因为我们已经有了源代码本身缺少的系统调用的列表。
相反,不要犹豫,尝试修补程序!
许多系统调用的实现都很简单,例如8162e0da0285d346046151b2a45ceeb1baf63b8f https://github.com/gem5/gem5/commit/8162e0da0285d346046151b2a45ceeb1baf63b8f.
另外,您也可以将系统调用标记为忽略ignoreFunc
,如果您认为跳过它们不会显着影响执行,请参阅例如:https://github.com/gem5/gem5/blob/8162e0da0285d346046151b2a45ceeb1baf63b8f/src/arch/arm/linux/process.cc#L161 https://github.com/gem5/gem5/blob/8162e0da0285d346046151b2a45ceeb1baf63b8f/src/arch/arm/linux/process.cc#L161
只有这样,如果您尝试了补丁但失败了,请开始向邮件列表中的人员发送 ping 消息,并寻求有关如何使您的补丁发挥作用的指导。
Related:
- gem5 系统调用模拟 OpenBLAS cblas_dgemm 失败并显示“致命:系统调用 mbind (#237) 未实现” https://stackoverflow.com/questions/49227682/gem5-syscall-emulation-openblas-cblas-dgemm-fails-with-fatal-syscall-mbind-2/49278729#49278729
- gem5 系统调用模拟 arm C hello world 失败并显示“致命:系统调用 gettid (#224) 未实现” https://stackoverflow.com/questions/51256193/gem5-syscall-emulation-arm-c-hello-world-fails-with-fatal-syscall-gettid-224/51266763#51266763
多线程
TODO 这是一个已知的主要痛点。我不知道状态如何,但我听说它很不稳定。
最近使 ARM 正常工作的修复
由于事情不可避免地会再次出现问题,您也许可以从我们所做的以下修复中获得一些灵感,并可能自己修复问题:
-
FATAL: kernel too old
: 在系统调用模拟 SE 模式下运行 gem5 时如何解决“FATAL: kernel too old”? https://stackoverflow.com/questions/48959349/how-to-solve-fatal-kernel-too-old-when-running-gem5-in-syscall-emulation-se-m修复者:260b0fc5381a47c681e7ead8e4f13aad45069665 https://github.com/gem5/gem5/commit/260b0fc5381a47c681e7ead8e4f13aad45069665
-
openat
未实施。 Ubuntu 18.04上的glibc ARM启动代码开始使用它,这打破了hello world。修复者:8162e0da0285d346046151b2a45ceeb1baf63b8f https://github.com/gem5/gem5/commit/8162e0da0285d346046151b2a45ceeb1baf63b8f
-
panic: Attempted to execute unimplemented instruction 'mrs'
。修复者:6efe7e1abf9d289859eb23b52b3a319f15f2736a https://github.com/gem5/gem5/commit/6efe7e1abf9d289859eb23b52b3a319f15f2736a。通过手动解码,执行的指令是mrs x0, midr_el1
.
交叉工具-NG
使用 crosstool-NG 启用 ulibc 而不是 glibc 有时可以作为 glibc 初始化代码的解决方法,因为 ulibc 比 glibc 更精简,执行的代码更少。它并不理想,但如果您确实无法修补 gem5,则可能会起作用。描述于:在系统调用模拟 SE 模式下运行 gem5 时如何解决“FATAL: kernel too old”? https://stackoverflow.com/questions/48959349/how-to-solve-fatal-kernel-too-old-when-running-gem5-in-syscall-emulation-se-m
如果您还需要从头开始生成完整的系统映像,另一种可能性是使用 Buildroot 构建的交叉编译器,看这个例子 https://github.com/cirosantilli/linux-kernel-module-cheat/tree/e1d0a2fafbb35c9e65c1a8a0b6d46df3e9161461#userland-setup-getting-started.
还有一些可以跨编译器构建的树内脚本:util/build_cross_gcc https://github.com/gem5/gem5/tree/f41abbdb5cf5c67233f3d730885d43517969afda/util/build_cross_gcc但我只会使用 crosstool-NG 来排除与其他项目的交叉编译器的维护。