在 s390 上测试 BPF

1. 简介

IBM Z 是大型机计算机,是 1964 年 IBM System/360 的后代。它们在 Linux 内核中以 “s390” 的名称支持。本文档描述如何在 s390 QEMU 客户机中测试 BPF。

2. 一次性设置

构建和运行测试套件需要以下内容

  • s390 GCC

  • s390 开发头文件和库

  • 支持 BPF 的 Clang

  • 支持 s390 的 QEMU

  • 带有 s390 rootfs 的磁盘镜像

Debian 支持开箱即用地安装 s390 的编译器和库。其他发行版的用户可以使用 debootstrap 来设置 Debian chroot

sudo debootstrap \
  --variant=minbase \
  --include=sudo \
  testing \
  ./s390-toolchain
sudo mount --rbind /dev ./s390-toolchain/dev
sudo mount --rbind /proc ./s390-toolchain/proc
sudo mount --rbind /sys ./s390-toolchain/sys
sudo chroot ./s390-toolchain

一旦在 Debian 上,可以按如下方式安装构建先决条件

sudo dpkg --add-architecture s390x
sudo apt-get update
sudo apt-get install \
  bc \
  bison \
  cmake \
  debootstrap \
  dwarves \
  flex \
  g++ \
  gcc \
  g++-s390x-linux-gnu \
  gcc-s390x-linux-gnu \
  gdb-multiarch \
  git \
  make \
  python3 \
  qemu-system-misc \
  qemu-utils \
  rsync \
  libcap-dev:s390x \
  libelf-dev:s390x \
  libncurses-dev

可以按如下方式安装最新的面向 BPF 的 Clang

git clone https://github.com/llvm/llvm-project.git
ln -s ../../clang llvm-project/llvm/tools/
mkdir llvm-project-build
cd llvm-project-build
cmake \
  -DLLVM_TARGETS_TO_BUILD=BPF \
  -DCMAKE_BUILD_TYPE=Release \
  -DCMAKE_INSTALL_PREFIX=/opt/clang-bpf \
  ../llvm-project/llvm
make
sudo make install
export PATH=/opt/clang-bpf/bin:$PATH

可以使用回环挂载和 debootstrap 来准备磁盘镜像

qemu-img create -f raw ./s390.img 1G
sudo losetup -f ./s390.img
sudo mkfs.ext4 /dev/loopX
mkdir ./s390.rootfs
sudo mount /dev/loopX ./s390.rootfs
sudo debootstrap \
  --foreign \
  --arch=s390x \
  --variant=minbase \
  --include=" \
    iproute2, \
    iputils-ping, \
    isc-dhcp-client, \
    kmod, \
    libcap2, \
    libelf1, \
    netcat, \
    procps" \
  testing \
  ./s390.rootfs
sudo umount ./s390.rootfs
sudo losetup -d /dev/loopX

3. 编译

除了运行 BPF 测试套件所需的常用 Kconfig 选项外,选择以下选项也很有帮助

CONFIG_NET_9P=y
CONFIG_9P_FS=y
CONFIG_NET_9P_VIRTIO=y
CONFIG_VIRTIO_PCI=y

因为这将启用一种非常简单的方式来与 s390 虚拟机共享文件。

可以使用以下命令编译内核、模块和测试套件,以及准备 gdb 脚本以简化调试

make ARCH=s390 CROSS_COMPILE=s390x-linux-gnu- menuconfig
make ARCH=s390 CROSS_COMPILE=s390x-linux-gnu- bzImage modules scripts_gdb
make ARCH=s390 CROSS_COMPILE=s390x-linux-gnu- \
  -C tools/testing/selftests \
  TARGETS=bpf \
  INSTALL_PATH=$PWD/tools/testing/selftests/kselftest_install \
  install

4. 运行测试套件

可以按如下方式启动虚拟机

qemu-system-s390x \
  -cpu max,zpci=on \
  -smp 2 \
  -m 4G \
  -kernel linux/arch/s390/boot/compressed/vmlinux \
  -drive file=./s390.img,if=virtio,format=raw \
  -nographic \
  -append 'root=/dev/vda rw console=ttyS1' \
  -virtfs local,path=./linux,security_model=none,mount_tag=linux \
  -object rng-random,filename=/dev/urandom,id=rng0 \
  -device virtio-rng-ccw,rng=rng0 \
  -netdev user,id=net0 \
  -device virtio-net-ccw,netdev=net0

当在真实的 IBM Z 上使用此方法时,可以添加 -enable-kvm 以获得更好的性能。首次启动虚拟机时,必须使用以下命令完成磁盘映像设置

/debootstrap/debootstrap --second-stage

需要在主机上构建的代码目录以及 /proc/sys 需要按如下方式挂载

mkdir -p /linux
mount -t 9p linux /linux
mount -t proc proc /proc
mount -t sysfs sys /sys

之后,可以使用以下命令运行测试套件

cd /linux/tools/testing/selftests/kselftest_install
./run_kselftest.sh

与往常一样,也可以单独运行测试

cd /linux/tools/testing/selftests/bpf
./test_verifier

5. 调试

可以使用 QEMU GDB stub 调试 s390 内核,通过将 -s 传递给 QEMU 来激活该 stub。

最好关闭 KASLR,以便 gdb 知道在内存中查找内核映像的位置,方法是使用以下命令构建内核

RANDOMIZE_BASE=n

然后可以使用以下命令附加 GDB

gdb-multiarch -ex 'target remote localhost:1234' ./vmlinux

6. 网络

如果需要在虚拟机中使用网络,例如安装其他软件包,可以使用以下方法配置

dhclient eth0