From nobody Wed Feb 11 05:13:31 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+importer=patchew.org@nongnu.org ARC-Seal: i=1; a=rsa-sha256; t=1667264477; cv=none; d=zohomail.com; s=zohoarc; b=aYBryz021R6AXTg728dxy5I3nqSwjLkd8j8a9+SAs0eDoRAOi0TaixTH+mjz7fmxehaOZMM3S6SXd9mRKjyMk9LbVsUP4rZYkXQoFyBIK9a7y2T87yRxmglw4bqCh83X4bCcuOT0F+j7NJkF3LdY0BWV74vqEXdkm30ZvNoHGqk= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1667264477; 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; bh=Dax3RQHONH/CxIJKEROKqe9y68zTbsZcG/SJeuV7B0c=; b=S+1nrlufVZdwJ9Ar3dmcG8gyE58nkfGxWknXfUU3qCJJZav4TTx122P848g3n256XmCf7spXVXWJM8fHHVPJ3dMHdXb1cPHfZJGFETHZEyxRoZ5lFfl0LykOKd4EPSMqBuzdmFgyQE2DnPlJtRgDoTBkWUF1lCVP48C4VvokIRE= 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+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1667264477369648.1861099194884; Mon, 31 Oct 2022 18:01:17 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1opfce-0004HF-VN; Mon, 31 Oct 2022 20:59:20 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1opfcd-0004Gr-KG for qemu-devel@nongnu.org; Mon, 31 Oct 2022 20:59:19 -0400 Received: from mail-pf1-x429.google.com ([2607:f8b0:4864:20::429]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1opfca-0005ct-SQ for qemu-devel@nongnu.org; Mon, 31 Oct 2022 20:59:19 -0400 Received: by mail-pf1-x429.google.com with SMTP id k15so4089640pfg.2 for ; Mon, 31 Oct 2022 17:59:16 -0700 (PDT) Received: from fedora.flets-east.jp ([2400:4050:c360:8200:8ae8:3c4:c0da:7419]) by smtp.gmail.com with ESMTPSA id o9-20020aa79789000000b0056d98e359a5sm1875644pfp.165.2022.10.31.17.59.09 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 31 Oct 2022 17:59:13 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=daynix-com.20210112.gappssmtp.com; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=Dax3RQHONH/CxIJKEROKqe9y68zTbsZcG/SJeuV7B0c=; b=eT+UbnRIsjpYc3HGIcEVvgaT234ZsPY9epijyl3qp2azYMzoHJUBB3KmV4QI9Bf5pt ttMeQjeOskunhFoEJl1nAPYvPQCg3cjV69jLdOlX/GTLnmDfyLsl+OzGxOtb+ob15bkl e7JCOz1OPxOL5G+kutcON86on7NmLI11sT50R/xyj/ulYvNtbRloHQDVzka2YKN5fTft C5sPmTnHyXVs33PIbvxis/prpq0NoO7M5voLMuPi6sPpmOElyaGF5/0532xaP4Ko0aV6 J84Xq9a5xGbTVRVWqMYPqPhh1s/ijbVQ7vTCqLpowN8l0TN2VtFv0dnVMGqZj9bo3wnQ R4eQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=Dax3RQHONH/CxIJKEROKqe9y68zTbsZcG/SJeuV7B0c=; b=abRPT68U3oulzDgpHB8d7hdCk/6AYNCyQ3EJuy+0rb4+ZanBkv5+V4bgE3tPNvqnT4 z9tIneQhGIGpQHnYOLbgZxWKQtx1w6sEe/3U2x7qjvEnhaOoIFY4JDUq6r/ndAcoxxsy Ogw3Gf7bVDuKRY3FtvLX4FQGYbxRBs29nAVfwbXQ0LNyjq1rxUztqsIKNI271BpZSPKB 735Dxju0bUH9yRjZc1Ld6OD+PPw7Gb9VQtf8SsfELv2HrLf3G3VuCqJOgJq2dukhxkuk 9XMnhUJR0T1MXQn+t+xuWLFSQ7BKgB+eUzUIJbJ08iY4smvrTRMp17wzj5ishmvwCei3 9QuQ== X-Gm-Message-State: ACrzQf1R9KEDAinKYNCi0RXSkGXvkDFxnrbaD62glYNWZKPojdeGO1yu sA9x9QqEOTBqpBIdzAuvZTUuzlJk5ntm+pXB X-Google-Smtp-Source: AMsMyM4U0goGD7PToOi1glhta5z4gNsP1bqO/vs0Len2ltDUAtj7pNdnJwDs8L3wgk2P/P/BkMDe5A== X-Received: by 2002:a63:6507:0:b0:46f:ea82:5792 with SMTP id z7-20020a636507000000b0046fea825792mr1401040pgb.50.1667264353930; Mon, 31 Oct 2022 17:59:13 -0700 (PDT) From: Akihiko Odaki To: Cc: qemu-devel@nongnu.org, qemu-block@nongnu.org, qemu-arm@nongnu.org, "Michael S . Tsirkin" , Marcel Apfelbaum , Gerd Hoffmann , Paolo Bonzini , Richard Henderson , Eduardo Habkost , John Snow , Dmitry Fleytman , Jason Wang , Stefan Weil , Keith Busch , Klaus Jensen , Peter Maydell , Andrey Smirnov , Paul Burton , Aleksandar Rikalo , Yan Vugenfirer , Yuri Benditovich , Akihiko Odaki Subject: [PATCH v7 01/17] hw/vfio/pci: Ensure MSI and MSI-X do not overlap Date: Tue, 1 Nov 2022 09:58:43 +0900 Message-Id: <20221101005859.4198-2-akihiko.odaki@daynix.com> X-Mailer: git-send-email 2.38.1 In-Reply-To: <20221101005859.4198-1-akihiko.odaki@daynix.com> References: <20221101005859.4198-1-akihiko.odaki@daynix.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+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: none client-ip=2607:f8b0:4864:20::429; envelope-from=akihiko.odaki@daynix.com; helo=mail-pf1-x429.google.com X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_NONE=0.001 autolearn=unavailable autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "Qemu-devel" Errors-To: qemu-devel-bounces+importer=patchew.org+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @daynix-com.20210112.gappssmtp.com) X-ZM-MESSAGEID: 1667264477928100001 Content-Type: text/plain; charset="utf-8" pci_add_capability() checks whether capabilities overlap, and notifies its caller so that it can properly handle the case. However, in the most cases, the capabilities actually never overlap, and the interface incurred extra error handling code, which is often incorrect or suboptimal. For such cases, pci_add_capability() can simply abort the execution if the capabilities actually overlap since it should be a programming error. This change handles the other cases: hw/vfio/pci depends on the check to decide MSI and MSI-X capabilities overlap with another. As they are quite an exceptional and hw/vfio/pci knows much about PCI capabilities, adding code specific to the cases to hw/vfio/pci still results in less code than having error handling code everywhere in total. Signed-off-by: Akihiko Odaki --- hw/pci/pci.c | 32 ++++++++++++++++++++------------ hw/vfio/pci.c | 15 ++++++++++++++- include/hw/pci/pci.h | 3 +++ 3 files changed, 37 insertions(+), 13 deletions(-) diff --git a/hw/pci/pci.c b/hw/pci/pci.c index 2f450f6a72..33f5406706 100644 --- a/hw/pci/pci.c +++ b/hw/pci/pci.c @@ -2512,6 +2512,23 @@ static void pci_del_option_rom(PCIDevice *pdev) pdev->has_rom =3D false; } =20 +void pci_check_capability_overlap(PCIDevice *pdev, uint8_t cap_id, + uint8_t offset, uint8_t size, Error **er= rp) +{ + int i; + + for (i =3D offset; i < offset + size; i++) { + if (pdev->used[i]) { + error_setg(errp, + "%s:%02x:%02x.%x PCI capability %x at offset %x ove= rlaps existing capability %x at offset %x", + pci_root_bus_path(pdev), pci_dev_bus_num(pdev), + PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn), + cap_id, offset, pci_find_capability_at_offset(pdev,= i), i); + return; + } + } +} + /* * On success, pci_add_capability() returns a positive value * that the offset of the pci capability. @@ -2523,7 +2540,6 @@ int pci_add_capability(PCIDevice *pdev, uint8_t cap_i= d, Error **errp) { uint8_t *config; - int i, overlapping_cap; =20 if (!offset) { offset =3D pci_find_space(pdev, size); @@ -2534,17 +2550,9 @@ int pci_add_capability(PCIDevice *pdev, uint8_t cap_= id, * depends on this check to verify that the device is not broken. * Should never trigger for emulated devices, but it's helpful * for debugging these. */ - for (i =3D offset; i < offset + size; i++) { - overlapping_cap =3D pci_find_capability_at_offset(pdev, i); - if (overlapping_cap) { - error_setg(errp, "%s:%02x:%02x.%x " - "Attempt to add PCI capability %x at offset " - "%x overlaps existing capability %x at offset %= x", - pci_root_bus_path(pdev), pci_dev_bus_num(pdev), - PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn), - cap_id, offset, overlapping_cap, i); - return -EINVAL; - } + pci_check_capability_overlap(pdev, cap_id, offset, size, errp); + if (errp) { + return -EINVAL; } } =20 diff --git a/hw/vfio/pci.c b/hw/vfio/pci.c index 939dcc3d4a..7ef1044f22 100644 --- a/hw/vfio/pci.c +++ b/hw/vfio/pci.c @@ -1298,6 +1298,14 @@ static int vfio_msi_setup(VFIOPCIDevice *vdev, int p= os, Error **errp) =20 trace_vfio_msi_setup(vdev->vbasedev.name, pos); =20 + vdev->msi_cap_size =3D 0xa + (msi_maskbit ? 0xa : 0) + (msi_64bit ? 0x= 4 : 0); + + pci_check_capability_overlap(&vdev->pdev, + PCI_CAP_ID_MSI, pos, vdev->msi_cap_size, = errp); + if (*errp) { + return -EINVAL; + } + ret =3D msi_init(&vdev->pdev, pos, entries, msi_64bit, msi_maskbit, &e= rr); if (ret < 0) { if (ret =3D=3D -ENOTSUP) { @@ -1306,7 +1314,6 @@ static int vfio_msi_setup(VFIOPCIDevice *vdev, int po= s, Error **errp) error_propagate_prepend(errp, err, "msi_init failed: "); return ret; } - vdev->msi_cap_size =3D 0xa + (msi_maskbit ? 0xa : 0) + (msi_64bit ? 0x= 4 : 0); =20 return 0; } @@ -1575,6 +1582,12 @@ static int vfio_msix_setup(VFIOPCIDevice *vdev, int = pos, Error **errp) int ret; Error *err =3D NULL; =20 + pci_check_capability_overlap(&vdev->pdev, + PCI_CAP_ID_MSIX, pos, MSIX_CAP_LENGTH, er= rp); + if (*errp) { + return -EINVAL; + } + vdev->msix->pending =3D g_new0(unsigned long, BITS_TO_LONGS(vdev->msix->entries)); ret =3D msix_init(&vdev->pdev, vdev->msix->entries, diff --git a/include/hw/pci/pci.h b/include/hw/pci/pci.h index b54b6ef88f..75e64ecdf2 100644 --- a/include/hw/pci/pci.h +++ b/include/hw/pci/pci.h @@ -390,6 +390,9 @@ void pci_register_vga(PCIDevice *pci_dev, MemoryRegion = *mem, void pci_unregister_vga(PCIDevice *pci_dev); pcibus_t pci_get_bar_addr(PCIDevice *pci_dev, int region_num); =20 +void pci_check_capability_overlap(PCIDevice *pdev, uint8_t cap_id, + uint8_t offset, uint8_t size, Error **er= rp); + int pci_add_capability(PCIDevice *pdev, uint8_t cap_id, uint8_t offset, uint8_t size, Error **errp); --=20 2.38.1