ARMv9的SVE/SVE2入门教程 (2)

如何运行SVE程序?

在深入学习SVE指令之前,我们需要搭建一个能运行和调试SVE指令的实验环境。由于树莓派4b不支持SVE扩展,我们可以采用QEMU+ARM64实验平台来模拟SVE指令。runninglinuxkernel_5.0项目在github里,或者腾讯coding仓库中,如何使用请参考里面的Readme.

访问github:

https: //github.com/figozhang/runninglinuxkernel_5.0

访问腾讯coding仓库:
https: //benshushu.coding.net/public/runninglinuxkernel_5.0/runninglinuxkernel_5.0/git/files

要想在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: 13Error: 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视频课程


请使用浏览器的分享功能分享到微信等