From nobody Tue Feb 10 01:32:53 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=none dis=none) header.from=yandex-team.com ARC-Seal: i=1; a=rsa-sha256; t=1666005180; cv=none; d=zohomail.com; s=zohoarc; b=Pzeie74i112KWg+kCxN4gbGf4ioMu/o9owtTEgEH9oBbXvvuhTeLxx7Gk/nnelg4EidatnWhyseTh7GtJPU5yAtKHpbB8lXlYdWWrXAMYwtZRx5pBI2ZyQlgw872P/DlcfPK0jL7DE5ebZ52xb0nctwn+sftFaAKUgtUirMEe/c= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1666005180; h=Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=43QDqg/hxytt/fGiR7Qd1qh7ZB1ECiEMYfrGwAdxma4=; b=Ctn1ErahnvAD+MXHs6AAYzXAU+wgGYDMy8+imtkb4cYydkiaZVpHbWuzV5LJXMVSuqsyKoWNQquVK4zMLBjIACOu/tTh1vqRhgnf+dPmrJBHT+dhoDUaordtJMsbdaMRU+YMiDguSIT1Bc5GXz9CcV386PZjAexCek+Tqw24MyM= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1666005180689378.19596965129836; Mon, 17 Oct 2022 04:13:00 -0700 (PDT) Received: from localhost ([::1]:51260 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1okO3H-0008KC-FH for importer@patchew.org; Mon, 17 Oct 2022 07:12:59 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:33296) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1okNvy-0001S0-TY for qemu-devel@nongnu.org; Mon, 17 Oct 2022 07:05:27 -0400 Received: from forwardcorp1b.mail.yandex.net ([178.154.239.136]:54278) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1okNvq-0001IH-G2 for qemu-devel@nongnu.org; Mon, 17 Oct 2022 07:05:24 -0400 Received: from sas1-7470331623bb.qloud-c.yandex.net (sas1-7470331623bb.qloud-c.yandex.net [IPv6:2a02:6b8:c08:bd1e:0:640:7470:3316]) by forwardcorp1b.mail.yandex.net (Yandex) with ESMTP id 785FE60E7D; Mon, 17 Oct 2022 13:54:30 +0300 (MSK) Received: from dellarbn.yandex.net (unknown [2a02:6b8:0:107:3e85:844d:5b1d:60a]) by sas1-7470331623bb.qloud-c.yandex.net (smtpcorp/Yandex) with ESMTPSA id PrI3KDUSQF-sS7Kd5R0; Mon, 17 Oct 2022 13:54:29 +0300 (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) (Client certificate not present) Precedence: bulk X-Yandex-Fwd: 1 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=yandex-team.com; s=default; t=1666004069; bh=43QDqg/hxytt/fGiR7Qd1qh7ZB1ECiEMYfrGwAdxma4=; h=Message-Id:Date:In-Reply-To:Cc:Subject:References:To:From; b=tY2RPaCzypziMhqW5U2ov/+u4r2r6x7E14xvhmp//DWc3nfcoPREAlNPHTVVx+x0+ aRWUYdn/gwoX4E2QpROE0t9XXLurBAyY2pwKKA3diNL7umIUenyDgwtlubzfY2+ABy aR2S8SwCMVekaobHt1vMcQKkjLaicwvDWugvWcQQ= Authentication-Results: sas1-7470331623bb.qloud-c.yandex.net; dkim=pass header.i=@yandex-team.com From: Andrey Ryabinin To: qemu-devel@nongnu.org Cc: Steve Sistare , yc-core@yandex-team.ru, Andrey Ryabinin , Tony Krowiak , Halil Pasic , Jason Herne , Alex Williamson , Cornelia Huck , Thomas Huth , Eric Farman , Matthew Rosato , Eric Blake , Markus Armbruster , Paolo Bonzini , =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= , Eduardo Habkost , Cleber Rosa , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , Wainer dos Santos Moschetta , Beraldo Leal Subject: [PATCH 4/4] tests/avocado/vfio: add test for vfio devices Date: Mon, 17 Oct 2022 13:54:07 +0300 Message-Id: <20221017105407.3858-5-arbn@yandex-team.com> X-Mailer: git-send-email 2.37.3 In-Reply-To: <20221017105407.3858-1-arbn@yandex-team.com> References: <20221017105407.3858-1-arbn@yandex-team.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=178.154.239.136; envelope-from=arbn@yandex-team.com; helo=forwardcorp1b.mail.yandex.net X-Spam_score_int: -16 X-Spam_score: -1.7 X-Spam_bar: - X-Spam_report: (-1.7 / 5.0 requ) BAYES_00=-1.9, DKIM_INVALID=0.1, DKIM_SIGNED=0.1, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=no autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail-DKIM: pass (identity @yandex-team.com) X-ZM-MESSAGEID: 1666005181866100004 Content-Type: text/plain; charset="utf-8" Add avocado test for vfio subsystem. The test uses pci-tesdev as a source PCI device for vfio. So the test supposed to be launched inside QEMU guest launched with '-device pci-testdev' devices. The test creates VFIO container&group, launches QEMU and passes container/group/device to it. Signed-off-by: Andrey Ryabinin --- tests/avocado/vfio.py | 156 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 156 insertions(+) create mode 100644 tests/avocado/vfio.py diff --git a/tests/avocado/vfio.py b/tests/avocado/vfio.py new file mode 100644 index 00000000000..fa0d2b65dc7 --- /dev/null +++ b/tests/avocado/vfio.py @@ -0,0 +1,156 @@ +# tests for QEMU's vfio subsystem +# +# Copyright (c) 2022 Yandex N.V. +# +# This work is licensed under the terms of the GNU GPL, version 2 or later. +# See the COPYING file in the top-level directory. + +from avocado.utils import wait +from avocado import skipUnless +from avocado_qemu import QemuSystemTest +from avocado_qemu import run_cmd +import os +import sys +import subprocess +from fcntl import ioctl +from ctypes import * +import struct + + +VFIO_CMD_PREFIX =3D ord(';') << (4*2) +VFIO_GET_API_VERSION =3D VFIO_CMD_PREFIX | 100 +VFIO_CHECK_EXTENSION =3D VFIO_CMD_PREFIX | 101 +VFIO_SET_IOMMU =3D VFIO_CMD_PREFIX | 102 +VFIO_GROUP_GET_STATUS =3D VFIO_CMD_PREFIX | 103 +VFIO_GROUP_SET_CONTAINER =3D VFIO_CMD_PREFIX | 104 +VFIO_GROUP_GET_DEVICE_FD =3D VFIO_CMD_PREFIX | 106 + +VFIO_TYPE1_IOMMU =3D 1 +VFIO_SPAPR_TCE_IOMMU =3D 2 +VFIO_TYPE1v2_IOMMU =3D 3 +VFIO_SPAPR_TCE_v2_IOMMU =3D 7 + +VFIO_API_VERSION =3D 0 +VFIO_TYPE1_IOMMU =3D 1 +PCI_VENDOR_ID=3D0x1b36 +PCI_DEV_ID=3D0x0005 + +class vfio_group_status(Structure): + _fields_ =3D [("argsz", c_uint32), + ("flags", c_uint32)] + +class vfio_container(object): + def open(self): + self.container_fd =3D os.open("/dev/vfio/vfio", os.O_RDWR) + if ioctl(self.container_fd, VFIO_GET_API_VERSION) !=3D VFIO_API_VE= RSION: + raise Exception("VFIO_GET_API_VERSION: unexpected vfio api ver= sion") + iommu_types =3D [ VFIO_TYPE1v2_IOMMU, VFIO_TYPE1_IOMMU, + VFIO_SPAPR_TCE_v2_IOMMU, VFIO_SPAPR_TCE_IOMMU ]; + for iommu_type in iommu_types: + if ioctl(self.container_fd, VFIO_CHECK_EXTENSION, iommu_type): + self.iommu_type =3D iommu_type + if not self.iommu_type: + raise Exception("No available IOMMU models"); + + def set_iommu(self): + ioctl(self.container_fd, VFIO_SET_IOMMU, self.iommu_type); + +class vfio_group(object): + def __init__(self, container, group_num): + self.ct =3D container + self.group_num =3D group_num + def open(self): + self.group_fd =3D os.open("/dev/vfio/%d" % self.group_num, os.O_RD= WR) + status =3D vfio_group_status(0, 0) + ioctl(self.group_fd, VFIO_GROUP_GET_STATUS, pointer(status)) + ioctl(self.group_fd, VFIO_GROUP_SET_CONTAINER, + c_int(self.ct.container_fd)); + +class vfio_device(object): + def __init__(self, dev, group): + self.dev =3D dev + self.group =3D group + +def pci_testdev_exists(): + for dev in next(os.walk('/sys/bus/pci/devices'))[1]: + with open("/sys/bus/pci/devices/%s/vendor" % dev) as f: + if f.read() !=3D '0x%x\n' % PCI_VENDOR_ID: + continue + with open("/sys/bus/pci/devices/%s/device" % dev) as f: + if f.read() !=3D '0x%.4x\n' % PCI_DEV_ID: + continue + return True + return False + +class VFIOIOMMUTest(QemuSystemTest): + devices =3D [] + groups =3D [] + timeout =3D 900 + ct =3D vfio_container() + + def add_group(self, dev): + tmp =3D os.readlink("/sys/bus/pci/devices/%s/iommu_group" % dev) + group_num =3D int(tmp.split('/')[-1]) + + for g in self.groups: + if g.group_num =3D=3D group_num: + return g + group =3D vfio_group(self.ct, group_num) + self.groups.append(group) + return group + + def setUp(self): + super().setUp() + run_cmd(('modprobe', 'vfio-pci')) + try: + f =3D open("/sys/bus/pci/drivers/vfio-pci/new_id", "a") + f.write("%x %x" % (PCI_VENDOR_ID, PCI_DEV_ID)) + except PermissionError: + pass + except FileExistsError: + pass + for dev in next(os.walk('/sys/bus/pci/devices'))[1]: + with open("/sys/bus/pci/devices/%s/vendor" % dev) as f: + if f.read() !=3D '0x%x\n' % PCI_VENDOR_ID: + continue + with open("/sys/bus/pci/devices/%s/device" % dev) as f: + if f.read() !=3D '0x%.4x\n' % PCI_DEV_ID: + continue + + self.devices.append(vfio_device(dev, self.add_group(dev))) + + def open_dev_fds(self): + self.ct.open() + for group in self.groups: + group.open() + self.ct.set_iommu() + + def close_fds(self): + for group in self.groups: + os.close(group.group_fd) + os.close(self.ct.container_fd) + + def hotplug_devices(self, vm): + vm._qmp.send_fd_scm(self.devices[0].group.ct.container_fd) + vm.command("getfd", fdname=3D"ct") + vm.command("object-add", qom_type=3D"vfio-container", id=3D"ct", f= d=3D"ct") + + for group in self.groups: + vm._qmp.send_fd_scm(group.group_fd) + vm.command("getfd", fdname=3D"group_fd") + vm.command("object-add", qom_type=3D"vfio-group", + id=3D"group%d" % group.group_num, + fd=3D"group_fd", container=3D"ct") + + for i in range(len(self.devices)): + vm.command("device_add", driver=3D"vfio-pci", + host=3Dself.devices[i].dev, id=3D"dev%d" % i, + group=3D"group%d" % self.devices[i].group.group_num) + + @skipUnless(pci_testdev_exists(), "no pci-testdev found") + def test_vfio(self): + self.open_dev_fds() + self.vm.add_args('-nodefaults') + self.vm.launch() + self.hotplug_devices(self.vm) + self.close_fds() --=20 2.37.3