如何运行SVE程序?
在深入学习SVE指令之前,我们需要搭建一个能运行和调试SVE指令的实验环境。由于树莓派4b不支持SVE扩展,我们可以采用QEMU+ARM64实验平台来模拟SVE指令。runninglinuxkernel_5.0项目在github里,或者腾讯coding仓库中,如何使用请参考里面的Readme.
访问github:
https://github.com/figozhang/...
访问腾讯coding仓库:
https://benshushu.coding.net/...
要想在QEMU中使能SVE扩展,需要在QEMU程序中指定“-cpu”参数,例如“-cpu max,sve=on,sve256=on”表示使能所有CPU的特性,包括SVE扩展,另外SVE支持的矢量长度设置为256位。读者也可以设置其他长度的SVE,例如1024位的SVE长度。
启动QEMU的命令如下。
$ qemu-system-aarch64 -m 1024 -cpu max,sve=on,sve256=on -M virt,gic-version=3,its=on,iommu=smmuv3 -nographic -smp 4 -kernel arch/arm64/boot/Image -append "noinintrd sched_debug root=/dev/vda rootfstype=ext4 rw crashkernel=256M loglevel=8" -drive if=none,file=rootfs_debian_arm64.ext4,id=hd0 -device virtio-blk-device,drive=hd0 --fsdev local,id=kmod_dev,path=./kmodules,security_model=none -device virtio-9p-pci,fsdev=kmod_dev,mount_tag=kmod_mount
下面编写一个使用SVE指令的简单汇编程序。
1 .section .data
2
3 .align 3
4 print_hello_sve:
5 .string "hello sve\n"
6
7 .section .text
8 .globl main
9 main:
10 stp x29, x30, [sp, -16]!
11
12 mov x2, #4
13 whilelo p0.s, xzr, x2
14 mov z0.s, p0/z, #0x55
15
16 adrp x0, print_hello_sve
17 add x0, x0, :lo12:print_hello_sve
18 bl printf
19
20 mov x0, #0
21 ldp x29, x30, [sp], 16
22 ret
这个汇编程序打印“hello sve”。为了测试能否编译和运行SVE指令,我们在第13~14行里添加两条SVE指令,其中WHILELO指令初始化P0预测寄存器,关于WHILELO指令我们后面会介绍。MOV是把立即数搬移到Z0矢量寄存器中。
首先启动QEMU+ARM64实验平台。关于如何使用QEMU+ARM64实验平台,请参考《奔跑吧linux内核 入门篇》第二版第1.5.3节内容。
运行run_rlk_arm64.sh脚本,输入run参数即可。run_rlk_arm64.sh脚本已经使能了SVE扩展。
$./run_rlk_arm64.sh run
登陆到QEMU+ARM64系统之后,可以通过“/proc/cpuinfo”节点来检查系统是否支持SVE扩展。在“Features”中显示了当前CPU支持的所有硬件特性,例如SVE等。
cat /proc/cpuinfo
processor : 0
BogoMIPS : 125.00
Features :sve fp asimd evtstrm aes
CPU implementer : 0x00
CPU architecture: 8
CPU variant : 0x0
CPU part : 0x051
CPU revision : 0
使用GCC来编译这个汇编程序。GCC是从GCC 8开始支持SVE指令的。
gcc hello_sve.S -o hello_sve
hello_sve.S: Assembler messages:
hello_sve.S:13: Error: selected processor does not support `whilelo p0.s,xzr,x2'
hello_sve.S:14: Error: selected processor does not support `mov z0.s,p0/z,#0x55'
直接使用“gcc hello_sve.S -o hello_sve”来编译,会出现不能识别SVE指令的错误。我们需要设置“-march”参数来指定处理器架构,例如“-march=armv8-a+sve”表示要编译的程序需要支持ARMv8架构以及SVE扩展。
gcc hello_sve.S -o hello_sve -g -march=armv8-a+sve
编译完成之后运行hello_sve程序。
./hello_sve
hello sve
这样我们就搭建了一个能运行SVE指令的实验环境了。
如何单步调试SVE程序?
接下来我们使用GDB来单步调试SVE指令。启动GDB来调试程序。
gdb hello_sve
在main函数入口设置断点。
(gdb) b main
Breakpoint 1 at 0x76c: file hello_sve.S, line 10.
输入“r”命令来启动调试。GDB会停在断点中。
(gdb) r
Starting program: /mnt/sve/example_hello_sve/hello_sve
Breakpoint 1, main () at hello_sve.S:10
10 stp x29, x30, [sp, -16]!
(gdb)
使用“s”命令来单步调试。使用“info reg”命令来查看寄存器的值,如图所示,使用info reg p0来查看预测寄存器p0的值,也可以使用info reg z0来查看z0矢量寄存器的值。
文章图片
ARM64视频课程
文章图片
【ARMv9的SVE/SVE2入门教程 (2)】
文章图片