最近使用C1-Ultra FVP来研究Linux kernel时遇到了不少问题,不过借助于强大的ARM Development Studio逐一解决了所有问题,为后续源码级研究kernel搭建了一个完美的环境,本文记录了我在解决这些问题的所有步骤,非常具有指导作用!
使用boot-wrapper-aarch64作为bootloader
为什么使用boot-wrapper-aarch64,因为我这里只关注Linux内核,所以没必要跑完整的软件栈,使用boot-wrapper-aarch64启动Linux比较快捷,且boot-wrapper-aarch64简单易懂,对于理解arm64 Linux启动流程已经足够了。
编译内核
如果你是windows环境,编译内核需要Linux环境,可以使用虚拟机或者wsl2,我这里使用的是wsl2 注意,后面下载内核,编译代码都在Linux环境上进行的
下载内核
这里使用的内核版本为6.19.3,也是我当时研究时的最新版本,不过此时已经不是最新版本了,理论上你使用当前最新版本也没啥问题

添加图片注释,不超过 140 字(可选)
使用国内镜像源下载linux-6.19.3: wget https://mirrors.ustc.edu.cn/kernel.org/linux/kernel/v6.x/linux-6.19.3.tar.xz
配置及编译内核
tar xf linux-6.19.3.tar.xz
cd linux-6.19.3
make ARCH=arm64 CROSS_COMPILE=aarch64-none-linux-gnu- defconfig
make ARCH=arm64 CROSS_COMPILE=aarch64-none-linux-gnu- menuconfig
Kernel hacking
\* Kernel debugging
\* Miscellaneous debug code
Compile-time checks and compiler options --->
Debug information (Rely on the toolchain's implicit default DWARF version) --->
Reduce debugging information //这个不要勾选
make ARCH=arm64 CROSS_COMPILE=aarch64-none-linux-gnu- -j12
编译rootfs
直接使用buildroot编译即可:
wget https://buildroot.org/downloads/buildroot-2025.11.2.tar.xz
tar xf buildroot-2025.11.2.tar.xz
cd buildroot-2025.11.2
make menuconfig //进行arm64架构,编译器等的配置
make
不过需要注意的就是编译过程中会下载一些包,可能较慢,可以使用我提供的编译过的源码包,省去下载步骤
这里补充一下配置内容:
目标架构:

添加图片注释,不超过 140 字(可选)
外部编译器:

添加图片注释,不超过 140 字(可选)
文件系统格式:

添加图片注释,不超过 140 字(可选)
基本上配置这些内容就够了,编译完成,一个简单的rootfs就制作好了,在buildroot-2025.11.2/output/images路径下
编译boot-wrapper-aarch64
clone boot-wrapper-aarch64代码:
git clone git://git.kernel.org/pub/scm/linux/kernel/git/mark/boot-wrapper-aarch64.git
cd boot-wrapper-aarch64
cat README
Linux boot wrapper with FDT support
===================================
To get started:
$ autoreconf -i
$ ./configure --host=<toolchain-triplet> --with-kernel-dir=<kernel-dir> <other-options>
$ make
Where:
- <toolchain-triplet>: this is something like aarch64-linux-gnu
- <kernel-dir>: the directory containing a pre-built aarch64 kernel
and its sources.
- <other-options>: see ./configure -h for a list of other options.
配置及编译
更多configure参数,可以使用如下命令查看:
configure -h
完整的配置及编译命令如下:
注意下面configure命令的参数,内核和dtb路径改成你自己的
autoreconf -i
./configure --host=aarch64-none-linux-gnu --enable-psci --enable-gicv3 --with-kernel-dir=/home/coolloser/arm64_linux/linux-6.19.3 --with-dtb=/home/coolloser/arm64_linux/linux-6.19.3/arch/arm64/boot/dts/arm/foundation-v8-gicv3-psci.dtb --with-initrd=/home/coolloser/arm64_linux/buildroot-2025.11.2/output/images/rootfs.cpio --with-cmdline="rdinit=/linuxrc console=ttyAMA0"
make -j12
设置ADS
导入源码
打开ads 2025.1后,先导入源码,由于我使用的是wsl2,所以先将wsl2映射到本地的一个盘符,如下图所示,在文件资源管理器中,右键wsl2的目录,选择映射网络驱动器:

添加图片注释,不超过 140 字(可选)
点击完成即可:

添加图片注释,不超过 140 字(可选)
现在可以在ads中导入源码了,点击File->Import:

添加图片注释,不超过 140 字(可选)
选择General->Projects from Folder or Archive,然后next

添加图片注释,不超过 140 字(可选)
之后将Search for nested projects取消勾选,因为我们要导入Linux源码,这里不取消勾选,待会check的会很慢,然后点击Directory:

添加图片注释,不超过 140 字(可选)
选择我们存放boot-wrapper-aarch64和linux-6.19.3的目录:

添加图片注释,不超过 140 字(可选)
点击finish即可,导入之后如下:

添加图片注释,不超过 140 字(可选)
创建debug launch
右键导入的工程,选择Debug As->Debug Configurations

添加图片注释,不超过 140 字(可选)
右键Generic Arm C/C++ Application,选择New Configuration

添加图片注释,不超过 140 字(可选)
选择C1 Ultra x4 FVP,注意在Arm FVP(Installed with Arm DS)中选择,名字随便起一个:

添加图片注释,不超过 140 字(可选)
然后点击Files,在Application on host to download下点击Workspace,选择boot-wrapper-aarch64/linux-system.axf

添加图片注释,不超过 140 字(可选)
点击Debugger,选择Debug from entry point

添加图片注释,不超过 140 字(可选)
在Source search directory中点击Workspace,添加boot-wrapper-aarch64和linux-6.19.3路径

添加图片注释,不超过 140 字(可选)
设置完成之后,点击Debug,这时候FVP就启动了,并且调试器连接FVP,下载程序,加载符号表等,一气呵成:

添加图片注释,不超过 140 字(可选)
完成后的界面是这样的:

添加图片注释,不超过 140 字(可选)
运行boot-wrapper-aarch64和Linux(解决无法启动问题)
运行之前需要开启Telnet:

添加图片注释,不超过 140 字(可选)
经过以上准备工作,现在可以运行boot-wrapper-aarch64和Linux了 提前剧透一下,运行起来可没那么一帆风顺,不过我就喜欢遇到问题^_^
问题一
点击运行按钮即可运行程序 很不幸,第一步就没运行起来,幸运的是,给出了解决的提示,即需要给FVP添加bp.secure_memory=false参数,以解决TZC-400对DRAM的控制

添加图片注释,不超过 140 字(可选)
现在我们根据提示给FVP添加bp.secure_memory=false参数: 先断开连接 然后右键这个launch,或者右键工程,选择Debug As->Debug Configurations,就跟我们创建这个launch时一样:

添加图片注释,不超过 140 字(可选)
在Connection下,Model parametes中填入-C bp.secure_memory=false,然后点击Debug

添加图片注释,不超过 140 字(可选)
现在又启动了,点击运行按钮,这下终于有log了:

添加图片注释,不超过 140 字(可选)
问题二
不过,等等,为啥卡在这里了?这就需要我们进行调试了,看看卡在哪里了,为什么卡住了 经过我的一番debug,发现除了主cpu的id匹配上了,其他cpu的id未能匹配,所以其他cpu直接结束运行,改动很简单,修改内核中的设备树:

添加图片注释,不超过 140 字(可选)
改完之后,重新编译设备树和boot-wrapper-aarch64,再次运行:

添加图片注释,不超过 140 字(可选)
这次可以看到已经进入kernel了,但是kernel并没有运行起来,看来卡在kernel启动阶段了,至少boot-wrapper-aarch64已经运行完了
问题三
下面我们继续debug kernel,看看卡在哪里了,以及为什么卡住了 经过我的一番debug,终于找到原因了,是因为kernel运行在EL2N(因为VHE),访问mpam寄存器时,trap到EL3了,解决起来也挺简单,在boot-wrapper-aarch64中添加几行代码将mpam使能,让低异常级别可以访问mpam相关的系统寄存器,就可以了:

添加图片注释,不超过 140 字(可选)
问题四
再次运行,终于看到kernel的log了

添加图片注释,不超过 140 字(可选)
可惜又卡死了,分析下来,发现调度器没运行起来,使用时间生成随机数时失败,且log前面的时间全是0,才明白过来 执行FVP_Base_C1-Ultra.exe --list-param命令,可以看到如下内容

添加图片注释,不超过 140 字(可选)
bp.refcounter.non_arch_start_at_default默认是0,本身是需要firmware来使能的,也可以在fvp的参数中使能,我们在fvp的参数中添加-C bp.refcounter.non_arch_start_at_default=1 再次运行,终于运行起来了:

添加图片注释,不超过 140 字(可选)