@Vengineerの戯言 : Twitter
SystemVerilogの世界へようこそ、すべては、SystemC v0.9公開から始まった
はじめに
今までは、Xilinx QEMU と SystemC側を繋げるケースについて見てきました。
今回からは、Linux の vfio (Virtual Function I/O と SystemC を繋げ、SystemCから vfio 経由で PCIe Device へアクセスするケースを見ていきます。
実際にどうやって動かすかは、ここ に詳しく書いてあります。
vfio について
vfio (Virtual Function I/O) については、下記に詳しく書いてありました。
vfio で PCIデバイスを操作するためには、vfio-pci ドライバをデバイスに bind すればいいようです。
上記のサイトから引用すると、下記のようにすればいいようです。Ethernet driver (Intel 82574) を前提にしています。
% lspci -nn | grep -i Ether 86:00.0 Ethernet controller [0200]: Intel Corporation 82574L Gigabit Network Connection [8086:10d3] % sudo modprobe vfio-pci % echo 0000:86:00.0 | sudo tee -a /sys/bus/pci/devices/0000:86:00.0/driver/unbind % echo 8086 10d3 | sudo tee -a /sys/bus/pci/drivers/vfio-pci/new_id
/dev/vfio/vfio /dev/vfio/<num> <num> は、I/O MMU のグルーブ番号
ができるようです。
デバイスがどの I/O MMU のグループ番号に属するかは、
$ ls -l /sys/bus/pci/devices/<ssss:bb:dd.f>/iommu_group/devices
のようなコマンドでわかるようです。
Ubuntu cloud image で QEMUを起動
x86-64マシン上で動作する Ubuntuの vfio ではなく、x86-64マシン上のQEMU上で Ubuntu cloud image を起動して、Ubuntu cloud image 上のSystemC側と接続します。
Ubuntu cloud image VM を ダウンロードし、イメージのサイズを 10GB にし、cloud image を qemu-system-x86_64 で起動します。
$ mkdir /tmp/machine-x86 $ qemu-system-x86_64 \ -M q35,accel=kvm,kernel-irqchip=split -m 4G -smp 4 -enable-kvm \ -device virtio-net-pci,netdev=net0 -netdev type=user,id=net0 \ -serial mon:stdio -machine-path /tmp/machine-x86 -display none \ -device intel-iommu,intremap=on,device-iotlb=on \ -device ioh3420,id=rootport,slot=0 -device ioh3420,id=rootport1,slot=1 \ -drive file=~/Downloads/ubuntu-20.04-server-cloudimg-amd64.img,format=qcow2 \ -drive file=~/Downloads/user-data.img,format=raw \ -kernel ~/Downloads/ubuntu-20.04-server-cloudimg-amd64-vmlinuz-generic \ -append "root=/dev/sda1 ro console=tty1 console=ttyS0 intel_iommu=on" \ -initrd ~/Downloads/ubuntu-20.04-server-cloudimg-amd64-initrd-generic
Ubuntu cloud image に SystemC および Verilator をインストール
Zynq、ZynqMP、Versalの時と違って、QEMUで起動した Ubuntu cloud image の中に、SystemC と Verilator をインストールする必要があります。
Ubuntu cloud image に login した後に、下記のように必要なパッケージをインストールします。
$ sudo apt-get update $ sudo apt-get install git build-essential autoconf flex bison
また、I/O MMU が on になっていることを確かめます。
$ cat /proc/cmdline "...ro quiet splash intel_iommu=on..."
次に、SystemC をインストールします。ここでは、2.3.2 をインストールしています。そして、Verilator もインストールします。ここでは、v4.010 をインストールしています。
SystemC側のモデルのビルド
SystemC側のモデル (PCIe RTL VFIO demos) をビルドします。.config.mk に SYSTEMCの環境を設定して、tests/rtl-bridges/pcie ディレクトリで make を実行します。
$ cd ~/github/ $ git clone https://github.com/Xilinx/libsystemctlm-soc.git $ cd libsystemctlm-soc $ cat <<EOF > .config.mk SYSTEMC = /opt/systemc-2.3.2/ EOF $ cd tests/rtl-bridges/pcie $ make
make コマンドが終了してら、下記のように2つのコマンドが生成されます。
$ ls test-pcie-ep-master-vfio test-pcie-ep-slave-vfio
Cloud image 上での vfio-pcie の登録
SystemC側のモデルを実行する前に、vfio-pcie を登録します。
test/rtl-bridges/pcie ディレクトリに移動し、modprobe コマンドにて vfio-pci を登録します。
/sys/bus/pci/drivers/vfio-pcie/new_id に対して、VendorID/DeviceIDを10ee d004に設定します。また、I/O MMUのグループを確認します。この例では、I/O MMU のグループは 3 という想定しています。
$ cd ~/github/libsystemctlm-soc/tests/rtl-bridges/pcie $ sudo modprobe vfio-pci nointxmask=1 $ sudo sh -c 'echo 10ee d004 > /sys/bus/pci/drivers/vfio-pci/new_id' $ # Find the iommu group $ ls -l /sys/bus/pci/devices/0000\:01\:00.0/iommu_group $ # The iommu group was 3