From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail-pl1-f201.google.com (mail-pl1-f201.google.com [209.85.214.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 4600721884B for ; Fri, 23 May 2025 23:30:35 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.214.201 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1748043036; cv=none; b=Qti41kC48uOnKYvcuz9XZDU9iKM0M4k0QumsAlY9wTQ+D8DfFh4m/3vOQX3Evvfmyz2au/tG8BEQL0jV9b3EtTwpFgYAAQF+iU0VE7+A5PshmOGcCV9eAxyZ5qKFokZACsbkAAczXutJg8wR2HE9yaEuAqryNf4xIy3NlYi6acI= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1748043036; c=relaxed/simple; bh=khOouQ7K9HPY9V4q+fKz3JDmI5DVBtGLNNEPubkBK8Q=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=KODsMO+9f1tjCoJRu+S+WJVSdm8DooQLFvDnA3UMdhstbu5IIzHhJgqEWTSR75TQEvsr8KbNq8UamSZt7HhcB+2gCGCxVABA2lnQRFqqK5HqANhzk7ne/2TE1+Gn8noGSCHnKiDmF+00E+fqr1RkHjaZyHXFKUFF6Yq1BqZ7AkE= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--dmatlack.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=uyX8VLEJ; arc=none smtp.client-ip=209.85.214.201 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--dmatlack.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="uyX8VLEJ" Received: by mail-pl1-f201.google.com with SMTP id d9443c01a7336-231de0e1ca3so3148095ad.0 for ; Fri, 23 May 2025 16:30:35 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1748043034; x=1748647834; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=qB1hXH62G4kjHsebxbjU1ZcMGCGD2fFhQzb591JcmdA=; b=uyX8VLEJSlTHlEVPVfJaHJl+vegV3NRPf25D+GOI3x2hWcSyTmlgK3pfMLJPe0lukL t3IvWVnOdYTDZ5H8bsZwqYvZ5uU/1YPn93yW14xyOy6ALonSieS1XoiYK9fkilS/OjT0 d5arlB7UE/r6tYhyCkCswaSpFgH+shw5fXzrymzS65rzgreDWKfcNj5npTMEL/BNluSN bf4lh/KaB0DxZbGgJd1zIaEK1y7I45vDHj9Ws+PZgBus685gU+Kj8xX+asOECBSz41ck /9auajFhm6m2qEMJ/XiUOYpB5mUZBPe7athw22tWmCvt4VP9UNDVbHaCyct+SwGPjrQj hosw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1748043034; x=1748647834; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=qB1hXH62G4kjHsebxbjU1ZcMGCGD2fFhQzb591JcmdA=; b=S5yEIoUMhh0nSKX+uHuczdVsrMqhQR6qWN7aVndMlMoir5OiB6c6nJVuIIXOm7e78B yXZPc9m1pIIx0sIPGsvQWyWjAR2H36PvfqvDiAU0RJhXBtz9haG6TepwrpD2QYcZS8Jd i5QUTPjC8Rvxmz3nr9cHJA0At9G67/qYkCTmd7LkP7w/AHN9NsERixtBn/1zVzZygjdY orcfbnw1zW76CO7g54Q3o44wUEC4hUVBWdkpmn0/vjKZgNoUOJzKWP3a8eUK0FRBLl7h QAUZZZL9dWH5pr/erWUeoxGDyiU81EdEJ7Wv7DMoXEw0cFITkt+xVbsiky4GTnLcO9i9 h5xg== X-Forwarded-Encrypted: i=1; AJvYcCWc3ke2+eRLjSIDegYZIiq5fMheVnLI4iO/MNllL0oNBzEXTHU4Inv0LslhF1jcBAaR5gI=@vger.kernel.org X-Gm-Message-State: AOJu0YxUE0GQzZadINoNUn33MCAt59E9O+A/+eqXFfzMT2GqvJbejTs3 pgTN13zXXBe1cf8TzU6M8cDvdov4VbGrrsaI9Q6VU3Oc4A7Yz0G1wc5IlmGcXAfrBcFv6G4SIJE 7gRcMTnPnSdqLjQ== X-Google-Smtp-Source: AGHT+IFd3EY9dZRO53rLPnjiCT79iMcz/a6Fw1kBGeR7CA4vrZULJpLBOvDx0Rak6gfiG4egPpnJjHwQyQV7ig== X-Received: from pjbnr10.prod.google.com ([2002:a17:90b:240a:b0:311:7cc:2d4c]) (user=dmatlack job=prod-delivery.src-stubby-dispatcher) by 2002:a17:903:4b30:b0:226:38ff:1d6a with SMTP id d9443c01a7336-23414f55b34mr15993465ad.7.1748043034529; Fri, 23 May 2025 16:30:34 -0700 (PDT) Date: Fri, 23 May 2025 23:29:48 +0000 In-Reply-To: <20250523233018.1702151-1-dmatlack@google.com> Precedence: bulk X-Mailing-List: kvm@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20250523233018.1702151-1-dmatlack@google.com> X-Mailer: git-send-email 2.49.0.1151.ga128411c76-goog Message-ID: <20250523233018.1702151-4-dmatlack@google.com> Subject: [RFC PATCH 03/33] vfio: selftests: Introduce vfio_pci_device_test From: David Matlack To: Alex Williamson Cc: Shuah Khan , Paolo Bonzini , David Matlack , Vinod Koul , Fenghua Yu , "Masami Hiramatsu (Google)" , Adhemerval Zanella , Jiri Olsa , Andrii Nakryiko , Wei Yang , Bjorn Helgaas , Takashi Iwai , Greg Kroah-Hartman , Pierre-Louis Bossart , Andy Shevchenko , FUJITA Tomonori , WangYuli , Sean Christopherson , Andrew Jones , Claudio Imbrenda , Eric Auger , Josh Hilke , linux-kselftest@vger.kernel.org, kvm@vger.kernel.org, Jason Gunthorpe , Kevin Tian , Vipin Sharma , Pasha Tatashin , Saeed Mahameed , Adithya Jayachandran , Parav Pandit , Leon Romanovsky , Vinicius Costa Gomes , Dave Jiang , Dan Williams Content-Type: text/plain; charset="UTF-8" Introduce a basic VFIO selftest called vfio_pci_device_test to demonstrate the functionality of the VFIO selftest library and provide some test coverage of basic VFIO operations, including: - Mapping and unmapping DMA - Mapping and unmapping BARs - Enabling, triggering, and disabling MSI and MSI-x - Reading and writing to PCI config space This test should work with most PCI devices, as long as they are bound to vfio-pci. Signed-off-by: David Matlack --- tools/testing/selftests/vfio/Makefile | 1 + .../selftests/vfio/vfio_pci_device_test.c | 180 ++++++++++++++++++ 2 files changed, 181 insertions(+) create mode 100644 tools/testing/selftests/vfio/vfio_pci_device_test.c diff --git a/tools/testing/selftests/vfio/Makefile b/tools/testing/selftests/vfio/Makefile index f8933dcdc8e1..89313d63414f 100644 --- a/tools/testing/selftests/vfio/Makefile +++ b/tools/testing/selftests/vfio/Makefile @@ -1,4 +1,5 @@ CFLAGS = $(KHDR_INCLUDES) +TEST_GEN_PROGS_EXTENDED += vfio_pci_device_test include ../lib.mk include lib/libvfio.mk diff --git a/tools/testing/selftests/vfio/vfio_pci_device_test.c b/tools/testing/selftests/vfio/vfio_pci_device_test.c new file mode 100644 index 000000000000..7906b2684dd3 --- /dev/null +++ b/tools/testing/selftests/vfio/vfio_pci_device_test.c @@ -0,0 +1,180 @@ +// SPDX-License-Identifier: GPL-2.0-only +#include +#include + +#include +#include + +#include +#include +#include +#include + +#include + +#include "../kselftest_harness.h" + +const char *device_bdf; + +/* + * Limit the number of MSIs enabled/disabled by the test regardless of the + * number of MSIs the device itself supports, e.g. to avoid hitting IRTE limits. + */ +#define MAX_TEST_MSI 16U + +FIXTURE(vfio_pci_device_test) { + struct vfio_pci_device *device; +}; + +FIXTURE_SETUP(vfio_pci_device_test) { + self->device = vfio_pci_device_init(device_bdf, VFIO_TYPE1_IOMMU); +} + +FIXTURE_TEARDOWN(vfio_pci_device_test) { + vfio_pci_device_cleanup(self->device); +} + +TEST_F(vfio_pci_device_test, dma_map_unmap) +{ + const u64 size = SZ_2M; + const u64 iova = SZ_4G; + void *mem; + + mem = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0); + ASSERT_NE(mem, MAP_FAILED); + + vfio_pci_dma_map(self->device, iova, size, mem); + printf("Mapped HVA %p (size 0x%lx) at IOVA 0x%lx\n", mem, size, iova); + vfio_pci_dma_unmap(self->device, iova, size); + + ASSERT_TRUE(!munmap(mem, SZ_2M)); +} + +#define read_pci_id_from_sysfs(_file) ({ \ + char __sysfs_path[PATH_MAX]; \ + char __buf[32]; \ + int __fd; \ + \ + snprintf(__sysfs_path, PATH_MAX, "/sys/bus/pci/devices/%s/%s", device_bdf, _file); \ + ASSERT_GT((__fd = open(__sysfs_path, O_RDONLY)), 0); \ + ASSERT_GT(read(__fd, __buf, ARRAY_SIZE(__buf)), 0); \ + ASSERT_EQ(0, close(__fd)); \ + (u16)strtoul(__buf, NULL, 0); \ +}) + +TEST_F(vfio_pci_device_test, config_space_read_write) +{ + u16 vendor, device; + u16 command; + + /* Check that Vendor and Device match what the kernel reports. */ + vendor = read_pci_id_from_sysfs("vendor"); + device = read_pci_id_from_sysfs("device"); + + ASSERT_EQ(vendor, vfio_pci_config_readw(self->device, PCI_VENDOR_ID)); + ASSERT_EQ(device, vfio_pci_config_readw(self->device, PCI_DEVICE_ID)); + + printf("Vendor: %04x, Device: %04x\n", vendor, device); + + command = vfio_pci_config_readw(self->device, PCI_COMMAND); + ASSERT_FALSE(command & PCI_COMMAND_MASTER); + + vfio_pci_config_writew(self->device, PCI_COMMAND, command | PCI_COMMAND_MASTER); + command = vfio_pci_config_readw(self->device, PCI_COMMAND); + ASSERT_TRUE(command & PCI_COMMAND_MASTER); + printf("Enabled Bus Mastering (command: %04x)\n", command); + + vfio_pci_config_writew(self->device, PCI_COMMAND, command & ~PCI_COMMAND_MASTER); + command = vfio_pci_config_readw(self->device, PCI_COMMAND); + ASSERT_FALSE(command & PCI_COMMAND_MASTER); + printf("Disabled Bus Mastering (command: %04x)\n", command); +} + +TEST_F(vfio_pci_device_test, validate_bars) +{ + struct vfio_pci_bar *bar; + int i; + + for (i = 0; i < PCI_STD_NUM_BARS; i++) { + bar = &self->device->bars[i]; + + if (!(bar->info.flags & VFIO_REGION_INFO_FLAG_MMAP)) { + printf("BAR %d does not support mmap()\n", i); + ASSERT_EQ(NULL, bar->vaddr); + continue; + } + + /* + * BARs that support mmap() should be automatically mapped by + * vfio_pci_device_init(). + */ + ASSERT_NE(NULL, bar->vaddr); + ASSERT_NE(0, bar->info.size); + printf("BAR %d mapped at %p (size 0x%llx)\n", i, bar->vaddr, bar->info.size); + } +} + +FIXTURE(vfio_pci_irq_test) { + struct vfio_pci_device *device; +}; + +FIXTURE_VARIANT(vfio_pci_irq_test) { + int irq_index; +}; + +FIXTURE_VARIANT_ADD(vfio_pci_irq_test, msi) { + .irq_index = VFIO_PCI_MSI_IRQ_INDEX, +}; + +FIXTURE_VARIANT_ADD(vfio_pci_irq_test, msix) { + .irq_index = VFIO_PCI_MSIX_IRQ_INDEX, +}; + +FIXTURE_SETUP(vfio_pci_irq_test) { + self->device = vfio_pci_device_init(device_bdf, VFIO_TYPE1_IOMMU); +} + +FIXTURE_TEARDOWN(vfio_pci_irq_test) { + vfio_pci_device_cleanup(self->device); +} + +TEST_F(vfio_pci_irq_test, enable_trigger_disable) +{ + bool msix = variant->irq_index == VFIO_PCI_MSIX_IRQ_INDEX; + u32 count; + u64 value; + int i; + + if (msix) + count = self->device->msix_info.count; + else + count = self->device->msi_info.count; + + count = min(count, MAX_TEST_MSI); + + if (!count) + SKIP(return, "MSI%s: not supported\n", msix ? "-x" : ""); + + vfio_pci_irq_enable(self->device, variant->irq_index, 0, count); + printf("MSI%s: enabled %d interrupts\n", msix ? "-x" : "", count); + + for (i = 0; i < count; i++) { + vfio_pci_irq_trigger(self->device, variant->irq_index, i); + ASSERT_EQ(8, read(self->device->msi_eventfds[i], &value, 8)); + ASSERT_EQ(1, value); + } + + vfio_pci_irq_disable(self->device, variant->irq_index); +} + +int main(int argc, char *argv[]) +{ + if (argc != 2) { + fprintf(stderr, "usage: %s segment:bus:device.function\n", argv[0]); + return KSFT_FAIL; + } + + device_bdf = argv[1]; + + return test_harness_run(1, argv); +} -- 2.49.0.1151.ga128411c76-goog