CPU 微架构逆向方法学
背景
最近做了不少微架构的评测,其中涉及到了很多的 CPU 微架构的逆向:
- AMD Zen 5 微架构评测
- ARM Neoverse V2 微架构评测
- Apple M1 微架构评测
- Apple M4 微架构评测
- Intel Golden Cove 微架构评测
- Intel Gracemont 微架构评测
- Intel Redwood Cove 微架构评测
- Qualcomm Oryon 微架构评测
因此总结一下 CPU 微架构逆向方法学。
最近做了不少微架构的评测,其中涉及到了很多的 CPU 微架构的逆向:
因此总结一下 CPU 微架构逆向方法学。
虽然 Apple M1 已经是 2020 年的处理器,但它对苹果自研芯片来说是一个里程碑,考虑到 X Elite 处理器的 Oryon 微架构和 Apple M1 性能核 Firestorm 微架构的相似性,还是测试一下这个 Firestorm + Icestorm 微架构在各个方面的表现。Apple A14 采用了和 Apple M1 一样的微架构。
最近使用 Linux 的性能分析功能比较多,但是很少去探究背后的原理,例如硬件的 PMU 是怎么配置的,每个进程乃至每个线程级别的 PMU 是怎么采样的。这篇博客尝试探究这背后的原理。
SPEC CPU 2017 官方只附带了 arm/ppc/sparc/riscv/x86 指令集的预编译 tools,如果要在其他指令集上使用,就需要首先编译 tools,过程如下:
# https://gist.github.com/cyyself/4cee148ad11081dde7b938e3584b4536
wget -O config.guess 'https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD'
wget -O config.sub 'https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD'
cp config.* /mnt/tools/src/expat-2.1.0/conftools/
cp config.* /mnt/tools/src/make-4.2.1/config/
cp config.* /mnt/tools/src/rxp-1.5.0/
cp config.* /mnt/tools/src/specinvoke/
cp config.* /mnt/tools/src/specsum/build-aux/
cp config.* /mnt/tools/src/tar-1.28/build-aux/
cp config.* /mnt/tools/src/xz-5.2.2/build-aux/
# fix glob impl
# https://github.com/GQBBBB/GQBBBB.github.io/issues/10
# http://git.savannah.gnu.org/cgit/make.git/patch/?id=48c8a116a914a325a0497721f5d8b58d5bba34d4
sed -i 's/_GNU_GLOB_INTERFACE_VERSION ==/_GNU_GLOB_INTERFACE_VERSION >=/' /mnt/tools/src/make-4.2.1/glob/glob.c
# fix missing test_driver.pl
# https://bugs.gentoo.org/613772
# http://git.savannah.gnu.org/cgit/make.git/commit/tests/run_make_tests.pl?id=d9d4e06084a4c7da480bd49a3487aadf6ba77b54
sed -i 's/require "test_driver.pl";/use FindBin;\nuse lib "$FindBin::Bin";\n\0/' /mnt/tools/src/make-4.2.1/tests/run_make_tests.pl
# fix wildcard test sigsegv
# https://lore.kernel.org/all/20200122223655.2569-1-sno@netbsd.org/T/
# http://git.savannah.gnu.org/cgit/make.git/commit/?id=193f1e81edd6b1b56b0eb0ff8aa4b41c7b4257b4
sed -i 's/gl->gl_stat = local_stat;/gl->gl_lstat = lstat;\n\0/' /mnt/tools/src/make-4.2.1/dir.c
# missing include ctype.h for isxdigit
sed -i 's/#include "xfreopen.h"/#include <ctype.h>\n\0/' /mnt/tools/src/specsum/src/md5sum.c
# fix gcc version detection
sed -i 's/1\*)/1.\*)/g' /mnt/tools/src/perl-5.24.0/Configure
# fix gettime test
sed -i 's/timegm(0,0,0,1,0,70)/timegm(0,0,0,1,0,1970)/g' /mnt/tools/src/TimeDate-2.30/t/getdate.t
# fix re.o generated instead of re.so
sed -i 's/main/int main/g' /mnt/tools/src/perl-5.24.0/hints/linux.sh
# GCC 15 default C23 fixes:
# 1. missing __alignof_is_defined && alignof macro
sed -i 's/#include <stdalign.h>/#define __alignof_is_defined 1\n#define alignof _Alignof\n\0/' /mnt/tools/src/specsum/tests/test-stdalign.c
# 2. hack stdbool.h detection
sed -i 's/#ifdef HAVE_STDBOOL_H/#if 1/' /mnt/tools/src/specinvoke/specinvoke.h
# 3. fix conflicting types for cleanup_os
sed -i 's/cleanup_os();/cleanup_os(specinvoke_state_t *si);/' /mnt/tools/src/specinvoke/specinvoke.h
# 4. fix char ** incompatible conversion to char*
sed -i 's/safesysrealloc(environ,/safesysrealloc((char*)environ,/' /mnt/tools/src/perl-5.24.0/util.c
sed -i 's/safesysfree(environ);/safesysfree((char*)environ);/' /mnt/tools/src/perl-5.24.0/perl.c
# 5. fix SDBM_FILE* incompatible conversion to char *
sed -i 's/safefree(db)/safefree((char*)db)/' /mnt/tools/src/perl-5.24.0/ext/SDBM_File/SDBM_File.xs
# 6. fix conflicting types for malloc/free
sed -i 's/extern Malloc_t malloc/extern void *malloc/' /mnt/tools/src/perl-5.24.0/ext/SDBM_File/sdbm.c
sed -i 's/extern Free_t free proto((Malloc_t))/extern void free proto((void *))/' /mnt/tools/src/perl-5.24.0/ext/SDBM_File/sdbm.c
# build tools
cd /mnt && echo 'y' | SKIPTOOLSINTRO=1 FORCE_UNSAFE_CONFIGURE=1 MAKEFLAGS=-j16 ./tools/src/buildtools
例如在 LoongArch 上编译 SPEC CPU 2017 的 Dockerfile,假设 SPEC CPU 2017 已经解压到 /mnt:
RUN cd /mnt && tar xvf install_archives/tools-src.tar
RUN wget -O config.guess 'https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD'
RUN wget -O config.sub 'https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD'
RUN cp config.* /mnt/tools/src/expat-2.1.0/conftools/
RUN cp config.* /mnt/tools/src/make-4.2.1/config/
RUN cp config.* /mnt/tools/src/rxp-1.5.0/
RUN cp config.* /mnt/tools/src/specinvoke/
RUN cp config.* /mnt/tools/src/specsum/build-aux/
RUN cp config.* /mnt/tools/src/tar-1.28/build-aux/
RUN cp config.* /mnt/tools/src/xz-5.2.2/build-aux/
# https://gist.github.com/cyyself/4cee148ad11081dde7b938e3584b4536
# fix glob impl
# https://github.com/GQBBBB/GQBBBB.github.io/issues/10
# http://git.savannah.gnu.org/cgit/make.git/patch/?id=48c8a116a914a325a0497721f5d8b58d5bba34d4
RUN sed -i 's/_GNU_GLOB_INTERFACE_VERSION ==/_GNU_GLOB_INTERFACE_VERSION >=/' /mnt/tools/src/make-4.2.1/glob/glob.c
# fix missing test_driver.pl
# https://bugs.gentoo.org/613772
# http://git.savannah.gnu.org/cgit/make.git/commit/tests/run_make_tests.pl?id=d9d4e06084a4c7da480bd49a3487aadf6ba77b54
RUN sed -i 's/require "test_driver.pl";/use FindBin;\nuse lib "$FindBin::Bin";\n\0/' /mnt/tools/src/make-4.2.1/tests/run_make_tests.pl
# fix wildcard test sigsegv
# https://lore.kernel.org/all/20200122223655.2569-1-sno@netbsd.org/T/
# http://git.savannah.gnu.org/cgit/make.git/commit/?id=193f1e81edd6b1b56b0eb0ff8aa4b41c7b4257b4
RUN sed -i 's/gl->gl_stat = local_stat;/gl->gl_lstat = lstat;\n\0/' /mnt/tools/src/make-4.2.1/dir.c
# missing include ctype.h for isxdigit
RUN sed -i 's/#include "xfreopen.h"/#include <ctype.h>\n\0/' /mnt/tools/src/specsum/src/md5sum.c
# fix gcc version detection
RUN sed -i 's/1\*)/1.\*)/g' /mnt/tools/src/perl-5.24.0/Configure
# fix gettime test
RUN sed -i 's/timegm(0,0,0,1,0,70)/timegm(0,0,0,1,0,1970)/g' /mnt/tools/src/TimeDate-2.30/t/getdate.t
# fix re.o generated instead of re.so
RUN sed -i 's/main/int main/g' /mnt/tools/src/perl-5.24.0/hints/linux.sh
# GCC 15 default C23 fixes:
# 1. missing __alignof_is_defined && alignof macro
RUN sed -i 's/#include <stdalign.h>/#define __alignof_is_defined 1\n#define alignof _Alignof\n\0/' /mnt/tools/src/specsum/tests/test-stdalign.c
# 2. hack stdbool.h detection
RUN sed -i 's/#ifdef HAVE_STDBOOL_H/#if 1/' /mnt/tools/src/specinvoke/specinvoke.h
# 3. fix conflicting types for cleanup_os
RUN sed -i 's/cleanup_os();/cleanup_os(specinvoke_state_t *si);/' /mnt/tools/src/specinvoke/specinvoke.h
# 4. fix char ** incompatible conversion to char*
RUN sed -i 's/safesysrealloc(environ,/safesysrealloc((char*)environ,/' /mnt/tools/src/perl-5.24.0/util.c
RUN sed -i 's/safesysfree(environ);/safesysfree((char*)environ);/' /mnt/tools/src/perl-5.24.0/perl.c
# 5. fix SDBM_FILE* incompatible conversion to char *
RUN sed -i 's/safefree(db)/safefree((char*)db)/' /mnt/tools/src/perl-5.24.0/ext/SDBM_File/SDBM_File.xs
# 6. fix conflicting types for malloc/free
RUN sed -i 's/extern Malloc_t malloc/extern void *malloc/' /mnt/tools/src/perl-5.24.0/ext/SDBM_File/sdbm.c
RUN sed -i 's/extern Free_t free proto((Malloc_t))/extern void free proto((void *))/' /mnt/tools/src/perl-5.24.0/ext/SDBM_File/sdbm.c
# build tools
RUN cd /mnt && echo 'y' | SKIPTOOLSINTRO=1 FORCE_UNSAFE_CONFIGURE=1 MAKEFLAGS=-j16 ./tools/src/buildtools
RUN mkdir -p /mnt/config
RUN cd /mnt && . ./shrc && packagetools linux-loong64
RUN /mnt/install.sh -f
Disqus 要加广告了,于是本博客的评论系统迁移到了 Giscus。
ARM Neoverse V2 是目前(2024 年)在服务器上能用到的最新的 ARM 公版核平台(AWS Graviton 4),测试一下这个微架构在各个方面的表现。
ISCA 2020 的一篇文章 The IBM z15 High Frequency Mainframe Branch Predictor Industrial Product 非常详细地解析了 IBM z15 Mainframe CPU 的分支预测器设计。本文是对这篇论文的学习和整理的笔记。
ISCA 2020 的一篇文章 Evolution of the Samsung Exynos CPU Microarchitecture 非常详细地解析了三星 Exynos 自研 CPU 微架构的演进历史。本文是对这篇论文的学习和整理的笔记。
最近借到一台 Surface Laptop 7 可以拿来折腾,它用的是高通 Snapdragon X Elite 处理器,借此机会测试一下这个微架构在各个方面的表现。
随着 Zen 5 的推出,更多 Zen5 的架构设计细节被公开,可以看到 Zen 5 前端出现了令人瞩目的变化:引入了 2-taken, 2-ahead 分支预测的设计。这是什么意思?它架构上是怎么实现的?可以带来哪些性能提升?
最近借到一台 Surface Laptop 7 可以拿来折腾,它用的是高通 Snapdragon X Elite 处理器,跑的是 Windows on Arm 系统。但作为 Linux 用户,肯定不满足于 WSL,而要裸机上安装 Linux。由于这个机器太新,所以安装的过程遇到了很多坎坷。
本文同步发布到本人的知乎。
这个系列的前三篇博客实现了一个简单的静态链接器,它可以输入若干个 ELF .o 文件,输出 ELF 可执行文件或者动态库。接下来,我们要进一步支持动态库,不仅可以生成动态库,还支持让动态库参与到静态链接当中。
本文同步发布到本人的知乎。
这个系列的前两篇博客实现了一个简单的静态链接器,它可以输入若干个 ELF .o 文件,输出 ELF 可执行文件。接下来,我们进一步支持动态库:输入若干个 ELF .o 文件,输出 ELF 动态库。
本文同步发布到本人的知乎。
这个系列的第一篇博客实现了一个最简单的静态链接器,它可以输入单个 ELF .o 文件,输出 ELF 可执行文件。接下来,我们需要把它升级到支持输入两个或者更多的 ELF .o 文件。
本文同步发布到本人的知乎。
无论是在课程中还是实践中,都经常和链接器打交道。在这个过程中,大概了解了它的工作原理,对于常见的错误可以知道大概是怎么一回事,以及如何解决。但最近遇到一些涉及到链接器内部的问题,才发现自己对链接器的内部的了解还是比较匮乏的。因此想到自己开发一个链接器,在开发的过程中学习。
Google Chrome 也用了很长时间了,但是一直没有尝试过构建 Chromium,这次趁着往 LoongArch 移植 Chromium 的机会,学习了一下 Chromium 的构建。