From nobody Mon Feb 9 10:27:36 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of redhat.com designates 216.205.24.124 as permitted sender) client-ip=216.205.24.124; envelope-from=libvir-list-bounces@redhat.com; helo=us-smtp-delivery-124.mimecast.com; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of redhat.com designates 216.205.24.124 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com; dmarc=pass(p=none dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1607477909; cv=none; d=zohomail.com; s=zohoarc; b=eUpIcUJ99S3CLGryq+MNXhnPXYxqLxjyagfFS8UiDNuxaHc3I4aW1AlC3qScb2om89hFfmLFTfKup77aLvcILOqxO9momqP//VzQXiMbBPqtKUK+elYfeUVhPiFa79SXOEtfBRlQ3zlVwAhKdPRZudsnkYRBeLbB2V6SBTF3AH8= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1607477909; h=Content-Type:Content-Transfer-Encoding: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=MPkU6PElZqAUS2Rp2utfe3u0xUV0JUZsDCaw6D4Ls2I=; b=D8gJ7uKRiWAOl1tWB0UbIvMQE1OMgMt4MnOQRzBpOJdoL/4xB63L83c0hYMT/sjfenAcCztiPnPkloy0qi1W7wiIbK7cu0Cfq8Zl9inmuiOJUC2VOLwA44Hf6c54gUZWcQXlg/Q/oCRWu4UO4hnUPFq8LmQk1btQ5zhuAP0P5IM= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of redhat.com designates 216.205.24.124 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com; dmarc=pass header.from= (p=none dis=none) header.from= Return-Path: Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [216.205.24.124]) by mx.zohomail.com with SMTPS id 1607477909317468.2336723884962; Tue, 8 Dec 2020 17:38:29 -0800 (PST) Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-397-QTLVwPWgM6qIhrTZhdGKBA-1; Tue, 08 Dec 2020 20:38:25 -0500 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 4055C8030AD; Wed, 9 Dec 2020 01:38:20 +0000 (UTC) Received: from colo-mx.corp.redhat.com (colo-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.20]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 1DA6E60BF1; Wed, 9 Dec 2020 01:38:20 +0000 (UTC) Received: from lists01.pubmisc.prod.ext.phx2.redhat.com (lists01.pubmisc.prod.ext.phx2.redhat.com [10.5.19.33]) by colo-mx.corp.redhat.com (Postfix) with ESMTP id DB4851809CA4; Wed, 9 Dec 2020 01:38:19 +0000 (UTC) Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15]) by lists01.pubmisc.prod.ext.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id 0B91br39007416 for ; Tue, 8 Dec 2020 20:37:53 -0500 Received: by smtp.corp.redhat.com (Postfix) id 23E3B5D6D5; Wed, 9 Dec 2020 01:37:53 +0000 (UTC) Received: from vhost2.laine.org (ovpn-112-50.phx2.redhat.com [10.3.112.50]) by smtp.corp.redhat.com (Postfix) with ESMTP id E153A5D6AB for ; Wed, 9 Dec 2020 01:37:52 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1607477908; h=from:from:sender:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:mime-version:mime-version: content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references:list-id:list-help: list-unsubscribe:list-subscribe:list-post; bh=MPkU6PElZqAUS2Rp2utfe3u0xUV0JUZsDCaw6D4Ls2I=; b=Ng3k93H0rLNjpM7kwouxl8WtRAYavoWvLhiC2SeDUw6/gM2Mpu4nG/iVOYv98GgoISlCNW jzE4zeYAuE3Ve8p7jpLJHTn29EZUX0thjdLyBo2X9YnSax34CmjjVGAxPrtoFhG0EcHIKU kW1+4v3i38zJgjFDMPjxphUl97shhTA= X-MC-Unique: QTLVwPWgM6qIhrTZhdGKBA-1 From: Laine Stump To: libvir-list@redhat.com Subject: [PATCH 6/7] util: make virPCIDeviceIsPCIExpress() more intelligent Date: Tue, 8 Dec 2020 20:37:44 -0500 Message-Id: <20201209013745.599662-7-laine@redhat.com> In-Reply-To: <20201209013745.599662-1-laine@redhat.com> References: <20201209013745.599662-1-laine@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.15 X-loop: libvir-list@redhat.com X-BeenThere: libvir-list@redhat.com X-Mailman-Version: 2.1.12 Precedence: junk List-Id: Development discussions about the libvirt library & tools List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: libvir-list-bounces@redhat.com Errors-To: libvir-list-bounces@redhat.com X-Scanned-By: MIMEDefang 2.79 on 10.5.11.12 Authentication-Results: relay.mimecast.com; auth=pass smtp.auth=CUSA124A263 smtp.mailfrom=libvir-list-bounces@redhat.com X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Transfer-Encoding: quoted-printable X-ZohoMail-DKIM: pass (identity @redhat.com) Content-Type: text/plain; charset="utf-8" Until now there has been an extra bit of code in qemuDomainDeviceCalculatePCIConnectFlag() (one of the two callers of virPCIDeviceIsPCIExpress()) that tries to determine if a device is PCIe by looking at the *length* of its sysfs config file; it only does this when libvirt is running as a non-root process. This patch takes advantage of our newfound ability to tell the difference between "I read a 0 from the device PCI config file" and "I couldn't read the PCI Express Capabilities because I don't have sufficient permission" to move the file length check down into virPCIDeviceIsPCIExpress(), and do that check any time we fail while reading the config file (not only when the process is non-root). Fixes: https://bugzilla.redhat.com/1901685 Signed-off-by: Laine Stump --- src/util/virpci.c | 42 ++++++++++++++++++++++++++++++++++++++---- 1 file changed, 38 insertions(+), 4 deletions(-) diff --git a/src/util/virpci.c b/src/util/virpci.c index 2f99bb93bd..01a156dfcf 100644 --- a/src/util/virpci.c +++ b/src/util/virpci.c @@ -73,10 +73,18 @@ struct _virPCIDevice { char *used_by_drvname; char *used_by_domname; =20 + /* The following 5 items are only valid after virPCIDeviceInit() + * has been called for the virPCIDevice object. This is *not* done + * in most cases (because it creates extra overhead, and parts of + * it can fail if libvirtd is running unprivileged) + */ unsigned int pcie_cap_pos; unsigned int pci_pm_cap_pos; bool has_flr; bool has_pm_reset; + bool is_pcie; + /**/ + bool managed; =20 virPCIStubDriver stubDriver; @@ -594,7 +602,8 @@ virPCIDeviceDetectFunctionLevelReset(virPCIDevicePtr de= v, int cfgfd) * the same thing, except for conventional PCI * devices. This is not common yet. */ - virPCIDeviceFindCapabilityOffset(dev, cfgfd, PCI_CAP_ID_AF, &pos); + if (virPCIDeviceFindCapabilityOffset(dev, cfgfd, PCI_CAP_ID_AF, &pos) = < 0) + goto error; =20 if (pos) { caps =3D virPCIDeviceRead16(dev, cfgfd, pos + PCI_AF_CAP); @@ -619,8 +628,8 @@ virPCIDeviceDetectFunctionLevelReset(virPCIDevicePtr de= v, int cfgfd) return true; } =20 + error: VIR_DEBUG("%s %s: no FLR capability found", dev->id, dev->name); - return false; } =20 @@ -905,7 +914,32 @@ virPCIDeviceTryPowerManagementReset(virPCIDevicePtr de= v, int cfgfd) static int virPCIDeviceInit(virPCIDevicePtr dev, int cfgfd) { - virPCIDeviceFindCapabilityOffset(dev, cfgfd, PCI_CAP_ID_EXP, &dev->pci= e_cap_pos); + dev->is_pcie =3D false; + if (virPCIDeviceFindCapabilityOffset(dev, cfgfd, PCI_CAP_ID_EXP, &dev-= >pcie_cap_pos) < 0) { + /* an unprivileged process is unable to read *all* of a + * device's PCI config (it can only read the first 64 + * bytes, which isn't enough for see the Express + * Capabilities data). If virPCIDeviceFindCapabilityOffset + * returns failure (and not just a pcie_cap_pos =3D=3D 0, + * which is *success* at determining the device is *not* + * PCIe) we make an educated guess based on the length of + * the device's config file - if it is 256 bytes, then it + * is definitely a legacy PCI device. If it's larger than + * that, then it is *probably PCIe (although it could be + * PCI-x, but those are extremely rare). If the config + * file can't be found (in which case the "length" will be + * -1), then we blindly assume the most likely outcome - + * PCIe. + */ + off_t configLen =3D virFileLength(virPCIDeviceGetConfigPath(dev), = -1); + + if (configLen !=3D 256) + dev->is_pcie =3D true; + + } else { + dev->is_pcie =3D (dev->pcie_cap_pos !=3D 0); + } + virPCIDeviceFindCapabilityOffset(dev, cfgfd, PCI_CAP_ID_PM, &dev->pci_= pm_cap_pos); dev->has_flr =3D virPCIDeviceDetectFunctionLevelReset(dev, cfgfd); dev->has_pm_reset =3D virPCIDeviceDetectPowerManagementReset(dev, cfgf= d); @@ -2609,7 +2643,7 @@ virPCIDeviceIsPCIExpress(virPCIDevicePtr dev) if (virPCIDeviceInit(dev, fd) < 0) goto cleanup; =20 - ret =3D dev->pcie_cap_pos !=3D 0; + ret =3D dev->is_pcie; =20 cleanup: virPCIDeviceConfigClose(dev, fd); --=20 2.28.0