0%

Kata rootfs 适配昇腾GPU驱动(Arm平台)

Kata rootfs 适配昇腾GPU驱动(Arm平台)

虚拟机

选择

  • 系统:驱动适配比较好的系统是CentOS 7.6和8.2,本次制作使用CentOS 8.2.2004 arm 镜像
  • 虚拟机:驱动依赖硬件设备,所以选择在宿主机通过qemu启动虚拟机,在虚拟机内部适配驱动
  • 其他:开启kvm加速,实测arm架构下开启kvm,需要宿主机是L0(不能是虚拟机),且bios使用edk2
  • 宿主机:宿主机系统为银河麒麟v10 arm版

准备工作

制作虚拟机(宿主机)

  • 制作qcow2文件(相当于是硬盘, 文件名hd.qcow2 , 大小100G)
    • qemu-img create -f qcow2 hd.qcow2 100G
  • 安装操作系统
    • qemu启动命令:qemu-system-aarch64 -m 24G -cpu host -smp 16 -M virt,accel=kvm -bios QEMU_EFI.fd -nographic -drive if=none,file=hd.qcow2,id=hd0 -device virtio-blk-device,drive=hd0 -drive if=none,file=CentOS-8.2.2004-aarch64-dvd1.iso,id=cdrom,media=cdrom -device virtio-scsi-device -device scsi-cd,drive=cdrom -net user,hostfwd=tcp::2222-:22 -net nic -device vfio-pci,host=0000:83:00.0
    • qemu参数说明:
      • -m 24G 指定内存大小
      • -cpu host 指定CPU类型和宿主机一致,注意host类型需要开启kvm加速
      • -M virt,accel=kvm machineType类型为virt(arm均使用virt),加速器使用kvm
      • -smp 16 cpu 16核
      • -bios QEMU_EFI.fd 指定edk2的efi文件
      • -nographic 因为不是在本地,所以直接通过控制台以基础文本的形式显示
      • -drive if=none,file=hd.qcow2,id=hd0 -device virtio-blk-device,drive=hd0 指定硬盘设备及驱动
      • -drive if=none,file=CentOS-8.2.2004-aarch64-dvd1.iso,id=cdrom,media=cdrom -device virtio-scsi-device -device scsi-cd,drive=cdrom 指定操作系统安装文件,以cdrom方式加载
      • -net user,hostfwd=tcp::2222-:22 -net nic 开启与宿主机的共享网络,同时将虚拟机的22端口映射到宿主机的2222端口
      • -device vfio-pci,host=0000:83:00.0 将宿主机的设备vfio直通到虚拟机
    • 如果在宿主机无法正常安装,可以考虑本地启动qemu安装,然后将qcow2文件拷贝至服务器
    • 安装完成后重启系统即可,以后启动qemu cdrom参数不再需要。
  • 注意事项:
    • 虚拟机启动后,需要开启sshd,否则无法ssh连接到虚拟机
    • QEMU_EFI.fd一定用edk2的,不要使用https://releases.linaro.org/components/kernel/uefi-linaro/latest/release/qemu64/QEMU_EFI.fd 这个版本,这个无法开启kvm加速
    • 全虚拟化的虚拟机慢的要死,开机就要15分钟,一定要开启kvm加速,后面驱动适配在全虚拟化下也会失败(全虚拟化运行太慢,导致驱动执行失败)
    • vfio宿主机一定要开启,否则虚拟机无法获取设备
    • 设备号可以通过lspci看到

内核制作

修改内核magversion

  • 进入内核源码目录,修改 include/linux/vermagic.h
    • 修改#define MODULE_VERMAGIC_MODULE_UNLOAD ""
    • 为:#define MODULE_VERMAGIC_MODULE_UNLOAD "mod_unload"
    • 修改#define MODULE_VERMAGIC_MODVERSIONS ""
    • 为:#define MODULE_VERMAGIC_MODVERSIONS "modversions"

编译内核获取bzImage(宿主机或虚拟机都可)

  • 直接执行make就行,注意配置和之前保持一致
  • 编译完成后,将arch/aarch64/boot/bzImage拷贝出来,作为kata启动的kernel

制作内核rpm安装包(宿主机或虚拟机都可)

  • 保持配置不变,执行make rpm-pkg
  • 然后将kernel,kernel-devel,kernel-headers三个rpm拷贝出来

虚拟机安装新内核(虚拟机)

  • 将编译的rpm安装包拷贝至虚拟机(开启ssh后scp -P 2222 xxx xxx@localhost:~即可)
  • 进入虚拟机后,执行rpm -ivh kernel-xxxxx.rpm 安装内核,然后重启虚拟机,用编译版本的内核启动虚拟机,准备后续rootfs制作

rootfs制作

制作rootfs(宿主机或虚拟机都可)

  • 进入kata源码kata-containers/tools/osbuilder/目录下,执行make镜像命令
  • make DISTRO=centos OS_VERSION=8.2.2004 SECCOMP=no DEBUG=true USE_DOCKER=true AGENT_INIT=yes EXTRA_PKGS='net-tools pciutils udev e2fsprogs tar gcc' rootfs
  • net-tools pciutils udev e2fsprogs tar gcc 这几样工具是驱动安装过程中需要的,需要提前打包至rootfs

拷贝rootfs至虚拟机

  • 上一步操作完成后,当前目录下会出来centos_rootfs文件夹,将该目录打包,拷贝至虚拟机
  • tar czvf centos_rootfs.tgz centos_rootfs
  • scp -P 2222 centos_rootfs.tgz root@localhost:~

驱动适配

补充缺失文件(虚拟机,其实这一步再打包之前操作也可以)

  • 解压rootfs
  • /usr/share/zoneinfo文件夹拷贝至 rootfs对应的目录下(centos默认rootfs缺失时区信息,无法安装驱动)
  • 拷贝驱动文件,kernel-devel,kernel-headers到rootfs的某目录下(我拷贝到home目录下),用于后续chroot安装
  • 创建hook脚本
    • mkdir -p /usr/share/oci/hooks/prestart
    • cd /usr/share/oci/hooks/prestart
    • 创建mount_tmpfs.sh脚本,解决/tmp,/var/log 只读问题,内容如下:
1
2
3
#!/bin/sh
mount -t tmpfs -o size=8192m tmpfs /tmp
mount -t tmpfs -o size=8192m tmpfs /var/log

挂载目录(虚拟机)

  • export ROOTFS_DIR=/root/centos_rootfs
  • mount -t sysfs -o ro none ${ROOTFS_DIR}/sys
  • mount -t proc -o ro none ${ROOTFS_DIR}/proc
  • mount -o bind,ro /dev ${ROOTFS_DIR}/dev
  • mount -t devpts none ${ROOTFS_DIR}/dev/pts
  • mount -t tmpfs none ${ROOTFS_DIR}/tmp

chroot并安装驱动(虚拟机)

  • chroot $ROOTFS_DIR
  • 进入home目录(驱动和kernel目录)
  • 安装kernel-devel和kernel-headers (rpm -ivh kernel*.rpm)
  • 创建华为用户组HwHiAiUser 和 用户
    • groupadd HwHiAiUser
    • useradd -g HwHiAiUser -d /home/HwHiAiUser -m HwHiAiUser -s /bin/bash
  • 安装驱动 ./A300-3000-npu-driver_21.0.3.3_linux-aarch64.run –full
  • 驱动安装成功后,执行 /usr/local/sbin/npu-smi info 如果能正常回显,则继续安装驱动,不能正常回显,则重启虚拟机,先exit退出chroot
  • 解除挂载 umount ${ROOTFS_DIR}/sys ${ROOTFS_DIR}/proc ${ROOTFS_DIR}/dev/pts ${ROOTFS_DIR}/tmp ${ROOTFS_DIR}/dev
  • 然后reboot重启虚拟机,重启后重新挂载目录,然后执行 /usr/local/sbin/npu-smi info 看是否能正常回显
  • 正常回显后,安装固件 ./A300-3000-npu-firmware_1.81.22.2.220.run –full
  • 然后删除内核源码(/usr/src/kernels下,内核版本的源码删除),删除kernel-devel,kernel-headers,驱动等文件(减少rootfs镜像大小)
  • exit退出chroot
  • 解除挂载 umount ${ROOTFS_DIR}/sys ${ROOTFS_DIR}/proc ${ROOTFS_DIR}/dev/pts ${ROOTFS_DIR}/tmp ${ROOTFS_DIR}/dev
  • 将rootfs打包(如果rootfs在虚拟机中制作,则忽略该步骤),并拷贝到宿主机上

制作镜像

  • 解压虚拟机中的rootfs文件
  • 切换到kata的image-builder目录(kata-containers/tools/osbuilder/image-builder)
  • 制作镜像./image_builder.sh rootfsDir
  • 得到kata-containers.img

其他适配

配置文件

  • kata的config需要进行以下几个修改
    1. guest_hook_path = "/usr/share/oci/hooks"
    2. kernel_modules=["drv_devdrv_host","drv_davinci_intf_host","drv_tsdrv_platform_host","drv_pcie_vnic_host","drv_pcie_hdc_host","drv_devmm_host"]
    3. hotplug_vfio_on_root_bus = true
    4. pcie_root_port = 2
  • 说明:
    1. guest_hook_path 执行hook,路径不需要更改,驱动需要挂载tmpfs,通过hook执行
    2. kernel_modules 驱动的modules默认不会加载,需要手动加载,配置到这里,vm启动会自动加载
    3. hotplug_vfio_on_root_bus 开启root bus,arm平台需要通过pcie_root_port进行设备热插拔
    4. pcie_root_port 单个虚拟机最多可以挂载GPU设备数

Kata源码

  • 主要修改如下:
    • virt模式支持pcieRootPort设备,通过配置进行加载
    • qmp添加设备指定bus为pcieRootPort设备,arm下只有pcieRootPort支持热插拔

Q&A

  1. 启动后,kata-runtime exec 进入vm后,/dev/loop设备只有1个

    • 修改内核配置
      • CONFIG_BLK_DEV_LOOP=y
      • CONFIG_BLK_DEV_LOOP_MIN_COUNT=4
  2. qemu 使用 -cpu host -M virt,accel=kvm 启动虚拟机黑屏

    • bios的efi启动文件不正确,使用edk2的efi文件即可
  3. 安装驱动npu-smi info执行后提示 dcmi module initialize failed. ret is -8005

    • 提示-8005的原因有很多,下面列出来几个适配中遇到过的
      • 显卡设备被其他驱动占用,去/sys/bus/pci/drivers/devdrv_device_driver目录下重新bind设备即可。
      • 内核模块加载不全,lsmod对比kernel_modules中的配置,是否已经加载全。
      • 同时提示sh: /tmp/pci_get_info_234.tmp: Read-only file system检查Hook脚本是否执行,可以df看下挂载情况。
      • 其他原因,可以通过dmesg查看kernel日志,具体排查
  4. chroot后,安装驱动,提示缺少xxxx组件

    • EXTRA_PKGS后面追加缺少的命令的安装包即可,无依赖的,可直接拷贝到rootfs对应目录下
  5. kernel-devel和kernel-headers是否可以不安装?

    • 需要安装,驱动安装过程中,有部分模块依赖内核,需要通过内核源码进行重编译,安装完成后,删除对应src目录即可。
    • 通过dkms安装会快点,但是依赖过多,不建议
  6. 内核日志提示:drv_seclib_host: version magic '5.4.160-1.el7.aarch64 SMP mod_unload modversions aarch64' should be '5.4.160-1.el7.aarch64 SMP aarch64'

    • 内核的version magic和编译的驱动的version magic不一致,参考内核部分修改version magic,重新编译即可
  7. qemu启动时加上-net user提示 -net user: Parameter 'type' expects a net backend type (maybe it is not compiled into this binary)

    • 编译qemu缺少slirp,重新config qemu,加上slirp后重新make qemu即可