From nobody Fri Oct 2 13:03:25 2026 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.12]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 9329F35DA7B; Fri, 31 Jul 2026 05:54:43 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.12 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785477285; cv=none; b=XxpSNuvJ3LHbCbnG36JWU3hoaFNB5phRqpyMX9TR/IrGSNJ43pea5vxXtS74RRAmKJ6W0jrgQPLomoAuUDkiiUwtrCMvbnoWUXxHjLqNQTleEkIMgf3c+0a2nHPUFUTf38hz4swX9+n2VtftnCY5QoTYQip7Cnh3sjodYM0l0p4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785477285; c=relaxed/simple; bh=AGmLDLYM3hd8Bo5EwLYvV6ZcLEieM+g057QtIEdzj/o=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=W1af7Dia0KGvxM5Lh2DOSAx4bcL12tCS1OINerdoxyYPDBWmIMF/ElSwwNpGWqnMCm15BcCpRWGoU6FTe5nLA3qrnxGqN7X17OjpN19Fy64CRM1AMiP5qEen1yTIu77UeKdVG2H3k0pdiWsaJTCjAtf3go36bAy+hbf07z5DZDo= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com; spf=pass smtp.mailfrom=linux.intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=X2L5zu/g; arc=none smtp.client-ip=198.175.65.12 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="X2L5zu/g" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1785477283; x=1817013283; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=AGmLDLYM3hd8Bo5EwLYvV6ZcLEieM+g057QtIEdzj/o=; b=X2L5zu/g3LztpZJ03orYa5gue0gGo9krrNm9YDkjYF/Slocyu03JMnwy lOBIRFh83g18Y3ufO60SkbWRCGCgtr0lsR8iQb+9xM3DT288wXonRwfTm iHoWWJ7v0LkII020ZgSKnf2TOkNhJNSwVtJqkihHmH2gYc/q/90MT33h8 b0jIxPY3hRK4RCcCmbXAhy2yHgwxj4eNRzRT0biVrt43Jvyw+67YMwtS+ 6qvOq0Hr6pTT6Vy/kNh4mVFWdzUBV55rtlbMlEkeshXtq2hHDH+6bTpSA jZDt67SbL/3os/9nLLdQFB6hIuQQ2i08ExAZ4l5sR+3ebwRLIY69UsYVc Q==; X-CSE-ConnectionGUID: nXF+Nar8Sim1uJItLJ8ZjQ== X-CSE-MsgGUID: vEB329K/RpatOAp3dhyeHg== X-IronPort-AV: E=McAfee;i="6800,10657,11860"; a="97615874" X-IronPort-AV: E=Sophos;i="6.25,195,1779174000"; d="scan'208";a="97615874" Received: from orviesa001.jf.intel.com ([10.64.159.141]) by orvoesa104.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 30 Jul 2026 22:54:43 -0700 X-CSE-ConnectionGUID: jDbFrx7VQlC0nfth6zHrqQ== X-CSE-MsgGUID: VifPtfz+QFmq6S2ejdXP/Q== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.25,195,1779174000"; d="scan'208";a="298695467" Received: from allen-box.sh.intel.com ([10.239.159.52]) by orviesa001.jf.intel.com with ESMTP; 30 Jul 2026 22:54:41 -0700 From: Lu Baolu To: Joerg Roedel , Will Deacon , Robin Murphy , Jason Gunthorpe , Kevin Tian Cc: iommu@lists.linux.dev, linux-kernel@vger.kernel.org, Lu Baolu , stable@vger.kernel.org, Sashiko Subject: [PATCH 1/5] iommu/vt-d: Fix shift overflow in qi_desc_dev_iotlb_pasid() Date: Fri, 31 Jul 2026 13:43:25 +0800 Message-ID: <20260731054329.2948252-2-baolu.lu@linux.intel.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260731054329.2948252-1-baolu.lu@linux.intel.com> References: <20260731054329.2948252-1-baolu.lu@linux.intel.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Callers request a full Device-TLB flush by passing MAX_AGAW_PFN_WIDTH (64 - VTD_PAGE_SHIFT =3D=3D 52) as @size_order. Two shifts in qi_desc_dev_iotlb_pasid() are not prepared for a value that large: unsigned long mask =3D 1UL << (VTD_PAGE_SHIFT + size_order - 1); ... if (!IS_ALIGNED(addr, VTD_PAGE_SIZE << size_order)) The first evaluates to 1UL << 63. On 32-bit builds this is undefined behaviour; in practice x86 masks the shift count to 5 bits, so the expression yields 1UL << 31 and ~mask becomes 0x7fffffff. That value is zero-extended when it is applied to the 64-bit descriptor, so desc->qw1 &=3D ~mask; clears qw1[63:32] as well as bit 31. The ADDR field, which had just been filled with ones to request the widest possible range, collapses to 0x7ffff000. As the S bit remains set, hardware decodes the least significant zero bit of ADDR and invalidates only 2GiB instead of the entire address space. Device-TLB entries above that boundary survive the unmap, leaving an ATS-capable device able to keep accessing memory that has already been freed. The second shift, VTD_PAGE_SIZE << size_order, is 1UL << 64 and is therefore undefined on 64-bit builds too. On x86_64 the shift count masks to zero, IS_ALIGNED(addr, 1) is trivially true and the sanity check silently degrades into a no-op. Compute both quantities in 64-bit and clamp @size_order to the largest range the ADDR field can encode. Capping at 63 - VTD_PAGE_SHIFT keeps the intended "flush everything" behaviour: qw1[62:12] is set, bit 62 is cleared as the size indicator and the S bit is set. The non-PASID variant qi_desc_dev_iotlb() already uses 1ULL and is unaffected. Fixes: f701c9f36bcb7 ("iommu/vt-d: Factor out invalidation descriptor compo= sition") Cc: stable@vger.kernel.org Reported-by: Sashiko Closes: https://sashiko.dev/#/patchset/20260623060122.3796325-1-guanghuifen= g%40linux.alibaba.com Assisted-by: Claude:claude-opus-5 Signed-off-by: Lu Baolu Reviewed-by: Samiullah Khawaja --- drivers/iommu/intel/iommu.h | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/drivers/iommu/intel/iommu.h b/drivers/iommu/intel/iommu.h index c00f44db0020..8a59c7c9d0a6 100644 --- a/drivers/iommu/intel/iommu.h +++ b/drivers/iommu/intel/iommu.h @@ -1105,12 +1105,20 @@ static inline void qi_desc_dev_iotlb_pasid(u16 sid,= u16 pfsid, u32 pasid, unsigned int size_order, struct qi_desc *desc) { - unsigned long mask =3D 1UL << (VTD_PAGE_SHIFT + size_order - 1); - desc->qw0 =3D QI_DEV_EIOTLB_PASID(pasid) | QI_DEV_EIOTLB_SID(sid) | QI_DEV_EIOTLB_QDEP(qdep) | QI_DEIOTLB_TYPE | QI_DEV_IOTLB_PFSID(pfsid); =20 + /* + * The invalidation range is encoded in the ADDR field, which only + * covers bits 63:12. Clamp @size_order so that callers asking for a + * full flush (e.g. with MAX_AGAW_PFN_WIDTH) do not overflow the + * shifts below. The clamped value still spans the whole range that + * the descriptor is able to express. + */ + if (size_order > 63 - VTD_PAGE_SHIFT) + size_order =3D 63 - VTD_PAGE_SHIFT; + /* * If S bit is 0, we only flush a single page. If S bit is set, * The least significant zero bit indicates the invalidation address @@ -1120,7 +1128,7 @@ static inline void qi_desc_dev_iotlb_pasid(u16 sid, u= 16 pfsid, u32 pasid, * Max Invs Pending (MIP) is set to 0 for now until we have DIT in * ECAP. */ - if (!IS_ALIGNED(addr, VTD_PAGE_SIZE << size_order)) + if (!IS_ALIGNED(addr, BIT_ULL(VTD_PAGE_SHIFT + size_order))) pr_warn_ratelimited("Invalidate non-aligned address %llx, order %d\n", addr, size_order); =20 @@ -1136,7 +1144,7 @@ static inline void qi_desc_dev_iotlb_pasid(u16 sid, u= 16 pfsid, u32 pasid, desc->qw1 |=3D GENMASK_ULL(size_order + VTD_PAGE_SHIFT - 1, VTD_PAGE_SHIFT); /* Clear size_order bit to indicate size */ - desc->qw1 &=3D ~mask; + desc->qw1 &=3D ~BIT_ULL(VTD_PAGE_SHIFT + size_order - 1); /* Set the S bit to indicate flushing more than 1 page */ desc->qw1 |=3D QI_DEV_EIOTLB_SIZE; } --=20 2.43.0 From nobody Fri Oct 2 13:03:25 2026 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.12]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 992DC360EF0 for ; Fri, 31 Jul 2026 05:54:45 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.12 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785477287; cv=none; b=WNSKA0bkqWGbv6zHyxBfwpXo5ZU+6+0QVTtDW8l1Wn9uHCo7t3LY54aZkDTGv7p6xWgYMz74HNP44NhnSNzsaewqq4xwpPNlpDcwQwluvFlnvIGumw/UdY0aiXlNedAPCQuQrDz/HFem+T7MTSeXvnHgwl9p4itR9cz0w6nCr0k= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785477287; c=relaxed/simple; bh=Y/X/Ba6YIuDetywzLYJFUFjzzynh/RHM+bsBpMwRxzE=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=NIG4cD4fsOMvAOA/OFwEa4h3jgXdeHoczOKM549I4s18S+hrx/kxp5egt3TnovtRS7mUiEj+W/mvNnIez+eW3Lads/vBTx3UoGhQm+qScMWk1JeJZ8cRT1wvyFm1ouQoQp1VCxphZGSOB2pYMm8uC5KTUIIq9A6L3ML40le3aUI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com; spf=pass smtp.mailfrom=linux.intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=eF3V2wYJ; arc=none smtp.client-ip=198.175.65.12 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="eF3V2wYJ" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1785477285; x=1817013285; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=Y/X/Ba6YIuDetywzLYJFUFjzzynh/RHM+bsBpMwRxzE=; b=eF3V2wYJMlaNfYz+SymZve8+YOOTlmu25lC9gcWEMJTDxSZB0/z4/TvW 5B2aynLgduR781FGeSlnK4Df3q7VbedyU4FDwfWTJhsT2nhnNpU4woDWS yVp7BmMFxW0skd+sI7z+c73tkpXkhcRk59TDljwHXejwy6A9s3K9P5QKC dnm6GvM8kAX0poqkJNuOsvqw/HHKFHCqWIHR28QfJgoDUCYwtNlMFdQtW cvqCg7UV1lKjVjq4peYdVBaBhHYNfC0CnEgaz8e9jLvqizIRYkkKnWEhc ZWgTADeqzSjHj9v0TGZcyHpYOsS/ekwaEurZFXyX4DNvuV22OtidQioIg A==; X-CSE-ConnectionGUID: l0C/dp08Rtig4rmU1mgguA== X-CSE-MsgGUID: 7oi8BeKWR/CVGaOEF80y9Q== X-IronPort-AV: E=McAfee;i="6800,10657,11860"; a="97615883" X-IronPort-AV: E=Sophos;i="6.25,195,1779174000"; d="scan'208";a="97615883" Received: from orviesa001.jf.intel.com ([10.64.159.141]) by orvoesa104.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 30 Jul 2026 22:54:45 -0700 X-CSE-ConnectionGUID: Cjc+GTTeSrK4LjrmUwfBkg== X-CSE-MsgGUID: WnNwPufJTRyiVIBTMiFIWw== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.25,195,1779174000"; d="scan'208";a="298695472" Received: from allen-box.sh.intel.com ([10.239.159.52]) by orviesa001.jf.intel.com with ESMTP; 30 Jul 2026 22:54:43 -0700 From: Lu Baolu To: Joerg Roedel , Will Deacon , Robin Murphy , Jason Gunthorpe , Kevin Tian Cc: iommu@lists.linux.dev, linux-kernel@vger.kernel.org, Lu Baolu , Sashiko Subject: [PATCH 2/5] iommu/vt-d: Clear Present bit before tearing down copied context entry Date: Fri, 31 Jul 2026 13:43:26 +0800 Message-ID: <20260731054329.2948252-3-baolu.lu@linux.intel.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260731054329.2948252-1-baolu.lu@linux.intel.com> References: <20260731054329.2948252-1-baolu.lu@linux.intel.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" copied_context_tear_down() zeroes the 128-bit context entry with context_clear_entry() while the Present bit is still set, and only then issues the context-cache and IOTLB invalidations. This leaves a window in which hardware can fetch a torn entry, with some fields already zeroed while Present is still set, leading to unpredictable behaviour or spurious faults. While x86 provides strong write ordering, the compiler may reorder the writes to the two 64-bit halves of the entry, and the hardware fetch is not guaranteed to be atomic with respect to multiple CPU writes. There is no cacheline flush before the invalidation either, so on an IOMMU without coherent access to the context table the zeroed entry may not be visible to hardware at the point the invalidation is submitted. Apply the same ownership handshake described in the VT-d spec, Section 6.5.3.3 ("Guidance to Software for Invalidations"): clear only the Present bit, flush it out to the IOMMU, perform the invalidations, and only then zero the remainder of the entry. Fixes: c7191984e5aad ("iommu/vt-d: Factor out helpers from domain_context_m= apping_one()") Reported-by: Sashiko Closes: https://sashiko.dev/#/patchset/20260602233426.357499-1-baolu.lu%40l= inux.intel.com Assisted-by: Claude:claude-opus-5 Signed-off-by: Lu Baolu --- drivers/iommu/intel/iommu.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c index 058967b669d9..528b59e5f4ce 100644 --- a/drivers/iommu/intel/iommu.c +++ b/drivers/iommu/intel/iommu.c @@ -1115,7 +1115,8 @@ static void copied_context_tear_down(struct intel_iom= mu *iommu, assert_spin_locked(&iommu->lock); =20 did_old =3D context_domain_id(context); - context_clear_entry(context); + context_clear_present(context); + __iommu_flush_cache(iommu, context, sizeof(*context)); =20 if (did_old < iommu->max_domain_id) { iommu->flush.flush_context(iommu, did_old, @@ -1126,6 +1127,9 @@ static void copied_context_tear_down(struct intel_iom= mu *iommu, DMA_TLB_DSI_FLUSH); } =20 + context_clear_entry(context); + __iommu_flush_cache(iommu, context, sizeof(*context)); + clear_context_copied(iommu, bus, devfn); } =20 --=20 2.43.0 From nobody Fri Oct 2 13:03:25 2026 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.12]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 8F4A9361953 for ; Fri, 31 Jul 2026 05:54:47 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.12 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785477288; cv=none; b=N9ur0kjz07vWpn/2yvVfXOlpbbubH52uQ+Qrjk1YjOSsseQI4P/mCYeWRl8XtmQsyxExmJpNy7nlksfByuXwdAJoadhN7dJebXAcPweeTDtDCiWdlH3jpI8CkMa8J0o9rzREa7O4uwXF97Z3pcmGu6Bv/kdJv5YlQ9iwRAHCq3U= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785477288; c=relaxed/simple; bh=nGcEK5ov3lgzx/0z00CAYMXlEb958viLjmsm0F0bSks=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=MvZfM/vITPVP+K66CnQ+/km+MZWd0nKpolhErRwt3t086+MOu0tfluzoyxK3JnWxwoyCPgEAM8BJg2XDbWKjN6Nt/UfUmcLjCPa6ZAQKRNA5IxxJAb7aYTV0X1CqI+yUyO1z0pqVirPeyCzBeqshDDMhVDK8q+nnXhWXHgH8YVU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com; spf=pass smtp.mailfrom=linux.intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=FzdrTL6E; arc=none smtp.client-ip=198.175.65.12 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="FzdrTL6E" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1785477287; x=1817013287; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=nGcEK5ov3lgzx/0z00CAYMXlEb958viLjmsm0F0bSks=; b=FzdrTL6E+fPetRljnbuzCY1Q1thYzB8z46vk26fxdhsZJH/8AQCbtveR 4E57ITdMR3hIyN6vfz6zzBxJ/94K1nwre6JO6IvYeRIoIMpO+6f3rcjrY YulH+NSzBcWBEmlBo6IUw3w7Te1a6qgkxHBgKG13e0xSvV13lQt5OqKkd BC46XZsFHCr33o+4n1xBkCXbqCGQd4Pt5P2ctiAbossygjpBiajTfsWnm 1qFrFXp2RxaeINb2qk5xPmOaj7fvERuXj4MhEwna2fKtGJI9gjpxcK3ad aCCfOwKSgUlVSDOlA9xipBfOab7BKf5wMVH6gfaHXHXKWIQaXk1uzw6IO Q==; X-CSE-ConnectionGUID: 09+FXFYFQDaNPZBkpl0GDQ== X-CSE-MsgGUID: w4xp72p0RYa80AX0gJh80Q== X-IronPort-AV: E=McAfee;i="6800,10657,11860"; a="97615891" X-IronPort-AV: E=Sophos;i="6.25,195,1779174000"; d="scan'208";a="97615891" Received: from orviesa001.jf.intel.com ([10.64.159.141]) by orvoesa104.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 30 Jul 2026 22:54:47 -0700 X-CSE-ConnectionGUID: Dx19Gj6pTZW/pGsEoSYhUg== X-CSE-MsgGUID: ZXRAU9DDS3+5f5MXlzTX5w== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.25,195,1779174000"; d="scan'208";a="298695476" Received: from allen-box.sh.intel.com ([10.239.159.52]) by orviesa001.jf.intel.com with ESMTP; 30 Jul 2026 22:54:45 -0700 From: Lu Baolu To: Joerg Roedel , Will Deacon , Robin Murphy , Jason Gunthorpe , Kevin Tian Cc: iommu@lists.linux.dev, linux-kernel@vger.kernel.org, Lu Baolu , Sashiko Subject: [PATCH 3/5] iommu/vt-d: Fix iopf_refcount leak on RID domain replacement Date: Fri, 31 Jul 2026 13:43:27 +0800 Message-ID: <20260731054329.2948252-4-baolu.lu@linux.intel.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260731054329.2948252-1-baolu.lu@linux.intel.com> References: <20260731054329.2948252-1-baolu.lu@linux.intel.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" intel_iommu_attach_device() enables IOPF for the new domain but never disables it for the old one. device_block_translation(), called at the start of the function, tears down translation but does not touch any IOPF state; blocking_domain_attach_dev() has to call iopf_for_domain_remove() explicitly before invoking it for exactly this reason. identity_domain_attach_dev() has the same problem. Its comment claims that no PRI handling is needed because the device has been put in the blocking state, but the blocking state and the IOPF reference count are independent of each other. As a result, replacing a domain that has an iopf_handler with another domain at RID level leaks a reference in info->iopf_refcount. The count never drops back to zero, so iopf_queue_remove_device() is never called and iommu_disable_pci_pri() triggers its WARN_ON(info->iopf_refcount) when the device is released. The PASID paths already handle this correctly by way of iopf_for_domain_replace(); convert the two RID paths to do the same. Using the replace helper rather than a bare remove keeps the enable before the disable, so the reference count does not transiently reach zero and evict the device from the IOPF queue. Fixes: 17fce9d2336d ("iommu/vt-d: Put iopf enablement in domain attach path= ") Reported-by: Sashiko Closes: https://sashiko.dev/#/patchset/20260602233426.357499-1-baolu.lu%40l= inux.intel.com Assisted-by: Claude:claude-opus-5 Signed-off-by: Lu Baolu --- drivers/iommu/intel/iommu.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c index 528b59e5f4ce..6baf1c075dc9 100644 --- a/drivers/iommu/intel/iommu.c +++ b/drivers/iommu/intel/iommu.c @@ -3158,13 +3158,13 @@ static int intel_iommu_attach_device(struct iommu_d= omain *domain, if (ret) return ret; =20 - ret =3D iopf_for_domain_set(domain, dev); + ret =3D iopf_for_domain_replace(domain, old, dev); if (ret) return ret; =20 ret =3D dmar_domain_attach_device(to_dmar_domain(domain), dev); if (ret) - iopf_for_domain_remove(domain, dev); + iopf_for_domain_replace(old, domain, dev); =20 return ret; } @@ -3870,10 +3870,13 @@ static int identity_domain_attach_dev(struct iommu_= domain *domain, return 0; =20 /* - * No PRI support with the global identity domain. No need to enable or - * disable PRI in this path as the iommu has been put in the blocking - * state. + * The identity domain has no iopf_handler, so no IOPF reference is + * taken for it. The reference held by the old domain must still be + * released here; putting the device in the blocking state above does + * not affect the IOPF reference count. */ + iopf_for_domain_remove(old, dev); + if (sm_supported(iommu)) ret =3D intel_pasid_setup_pass_through(iommu, dev, IOMMU_NO_PASID); else --=20 2.43.0 From nobody Fri Oct 2 13:03:25 2026 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.12]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 9D19A361DB1 for ; Fri, 31 Jul 2026 05:54:49 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.12 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785477290; cv=none; b=LW4QdQ5BLCzHSs/sfmo8iyLX+6tAYEeeBAu98dJJfnvqZ8deUpHqu9qHQDR3t9IELpN8a/Si5vCWlrTZbGLt73wvho8LVjWQzNmBgkBUKV67MvtOjirIiFHDLQJrx7T5PJHwSVX2ZTKVEt1oIFXUbYQtJtc6zKzrOOIXeTg/NCE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785477290; c=relaxed/simple; bh=w1DmIJJT/VVqp1LJKvA//Zkogd2iy0ulo2WljJSVg0g=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=goI7w5JH9a7FTRekVXB7chYn8oymCy6A038V20Eu/HBrKTHG9BR8JI3SNHmjo7GlNXWxtK+EpmEfcQd9/pMdeHSADIyjft8rosc/UuRlh/mpcjcMHKoqoBE/73aBnzySQ6LR+nzCydK4lFDNb94mvKbyLnr3yQzcXVVVEyN3+34= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com; spf=pass smtp.mailfrom=linux.intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=MSPqOwzZ; arc=none smtp.client-ip=198.175.65.12 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="MSPqOwzZ" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1785477289; x=1817013289; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=w1DmIJJT/VVqp1LJKvA//Zkogd2iy0ulo2WljJSVg0g=; b=MSPqOwzZH5qCNvA4KqFqn2FfO8hcnAhIjHgQbw+8WVQ8AKTsa+crTE9F 7d3+pQNhXaYZFlZ0d1XYCkjl+nsrA5X9SXI6a+wxi1QFGOkrz5nZbAYdW r8bzsAnd0hu0+V9Ge3RAWOUK4yDGIHHBgHgdcVCdWz6LogwqIT7nJqTNl u3DmH7Hz1Svz4hczeF8szXzH7RNp7Zy579cB2+e8TwZuOahHDhZZ/JhXx tUHWsLoknTcqx0Uf6ZAGb9HDUYx4v5XLbY89kSlLQb9ZKH8aQ9KcKVCbE OkzS9isV92GfjQCbvwZReN5MegwJ9+68D74xxUwKoXak4AZH8lLJKrxOS g==; X-CSE-ConnectionGUID: Z+EOZ5qlRX6WkhnI6ZaG6w== X-CSE-MsgGUID: PWlIn0UlSzW13c8x7GQD+A== X-IronPort-AV: E=McAfee;i="6800,10657,11860"; a="97615897" X-IronPort-AV: E=Sophos;i="6.25,195,1779174000"; d="scan'208";a="97615897" Received: from orviesa001.jf.intel.com ([10.64.159.141]) by orvoesa104.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 30 Jul 2026 22:54:49 -0700 X-CSE-ConnectionGUID: d24gsISwQROuymQQ562PUg== X-CSE-MsgGUID: NjXJmz07Sru8bNEAVmDr/A== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.25,195,1779174000"; d="scan'208";a="298695479" Received: from allen-box.sh.intel.com ([10.239.159.52]) by orviesa001.jf.intel.com with ESMTP; 30 Jul 2026 22:54:47 -0700 From: Lu Baolu To: Joerg Roedel , Will Deacon , Robin Murphy , Jason Gunthorpe , Kevin Tian Cc: iommu@lists.linux.dev, linux-kernel@vger.kernel.org, Lu Baolu , Sashiko Subject: [PATCH 4/5] iommu/vt-d: Tear down scalable-mode context on probe failure Date: Fri, 31 Jul 2026 13:43:28 +0800 Message-ID: <20260731054329.2948252-5-baolu.lu@linux.intel.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260731054329.2948252-1-baolu.lu@linux.intel.com> References: <20260731054329.2948252-1-baolu.lu@linux.intel.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable intel_pasid_setup_sm_context() walks a PCI device=E2=80=99s DMA aliases via pci_for_each_dma_alias() and programs a scalable-mode context entry for each RID. For a device with a dma_alias_mask, the callback is invoked once for the device=E2=80=99s own RID and once for each alias bit, all with= the same pci_dev, so device_pasid_table_setup() runs for multiple RIDs. pci_for_each_dma_alias() stops at the first callback error. Therefore, a failure partway through the walk can leave context entries for already processed RIDs present and still pointing to the device=E2=80=99s PASID tab= le. On this error path, intel_iommu_probe_device() currently jumps directly to intel_pasid_free_table(), which frees the PASID table without first tearing down those context entries. The IOMMU may then walk a present context entry whose PASID table pointer references freed memory. intel_iommu_release_device() already performs teardown before freeing the table. Apply the same ordering on the probe failure path. device_pasid_table_teardown() safely handles RIDs that were never programmed: iommu_context_addr() returns NULL when no context table has been allocated, and clearing the Present bit of an already non-present entry is a no-op. So unwind is safe for both the alias that failed and any aliases not yet reached. Fixes: 301f1a80487fd ("iommu/vt-d: Setup scalable mode context entry in pro= be path") Reported-by: Sashiko Closes: https://sashiko.dev/#/patchset/20260602233426.357499-1-baolu.lu%40l= inux.intel.com Assisted-by: Claude:claude-opus-5 Signed-off-by: Lu Baolu --- drivers/iommu/intel/iommu.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c index 6baf1c075dc9..489e9ab5f698 100644 --- a/drivers/iommu/intel/iommu.c +++ b/drivers/iommu/intel/iommu.c @@ -3342,6 +3342,7 @@ static struct iommu_device *intel_iommu_probe_device(= struct device *dev) =20 return &iommu->iommu; free_table: + intel_pasid_teardown_sm_context(dev); intel_pasid_free_table(dev); clear_rbtree: device_rbtree_remove(info); --=20 2.43.0 From nobody Fri Oct 2 13:03:25 2026 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.12]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id EB11635F19D for ; Fri, 31 Jul 2026 05:54:51 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.12 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785477293; cv=none; b=gbyb8PsiV24siNQfwcnbUlHao9IaeZk00IJEpQyNx7M6ZjTCsXs8BBCqak8RzrQXP1QLX5daeyBPR97rISILtelXlf0VKF7c4RvHZ2U+A0GA0Li7jj762dqyqDEP1rnli0PS5nzMT2EjGnyHDc3cKVhpZL90zYAwusauavTpdJ0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785477293; c=relaxed/simple; bh=/oApGxpXT2Dh+5iXlhTAd0ujuNkuxeR/SwYYQ008Nbs=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=P35KS5FGWR4sbtjRiOtcplONVJEW+d5vO0OCljPmrLa69DgQp8juKeu6lZWROlfHrgW6B9ENuH5ZCBp4/TEsvWghZRvw6BLFd4GnOXkjdHqJQ7MtDqokrfK+rR9qz3nFfLHUTQYfTQklXPR3R/bFydAw0CSDUYq11pVVea9W17A= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com; spf=pass smtp.mailfrom=linux.intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=LDJHNpAu; arc=none smtp.client-ip=198.175.65.12 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="LDJHNpAu" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1785477292; x=1817013292; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=/oApGxpXT2Dh+5iXlhTAd0ujuNkuxeR/SwYYQ008Nbs=; b=LDJHNpAudunFacsVtDt64XUPLeY1mx/3QyDw+dJ56HhJJfKYActD4/+r /WAWoUGFZBD1p/SML/FXtHAqTuo3JAc86G7kASQ20n3cX/rJjadYGW/Dl r2fuk8qdtgo+TLEko136d3s24YF00Z1k+m2aG/KGrpaKnc8vvRQK1oAi3 kLJq898IXYgyc7DnBjvcAI0Ed9aufdLoR0ZoWbuFBixGS430vVHHsfJPO BS7qLCRnaKXzFMbfTZfSZvbA0sjLgvgb5N0xnkZZSCCTgd1Elca7Ma5Jm sjKmx+oFrur4Soc9ElvwehF1lxX+WUOw+XpbrVXRIExos+4Pckj5+EXB8 g==; X-CSE-ConnectionGUID: VuL9HG+3Qy2XOlP6xNT+pA== X-CSE-MsgGUID: Zt4nb+3ASqW24H7XgdhYaw== X-IronPort-AV: E=McAfee;i="6800,10657,11860"; a="97615903" X-IronPort-AV: E=Sophos;i="6.25,195,1779174000"; d="scan'208";a="97615903" Received: from orviesa001.jf.intel.com ([10.64.159.141]) by orvoesa104.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 30 Jul 2026 22:54:51 -0700 X-CSE-ConnectionGUID: 1CcK+V+CSDytip6LlDCpDg== X-CSE-MsgGUID: q9Ufuxk7RSaZ060tsP6Xfg== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.25,195,1779174000"; d="scan'208";a="298695482" Received: from allen-box.sh.intel.com ([10.239.159.52]) by orviesa001.jf.intel.com with ESMTP; 30 Jul 2026 22:54:49 -0700 From: Lu Baolu To: Joerg Roedel , Will Deacon , Robin Murphy , Jason Gunthorpe , Kevin Tian Cc: iommu@lists.linux.dev, linux-kernel@vger.kernel.org, Lu Baolu , Sashiko Subject: [PATCH 5/5] iommu/vt-d: Flush context cache with correct SID when tearing down aliases Date: Fri, 31 Jul 2026 13:43:29 +0800 Message-ID: <20260731054329.2948252-6-baolu.lu@linux.intel.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260731054329.2948252-1-baolu.lu@linux.intel.com> References: <20260731054329.2948252-1-baolu.lu@linux.intel.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable domain_context_clear_one() and device_pasid_table_teardown() are both invoked once per DMA alias of a device. Each function locates the context entry using the bus/devfn pair provided by the pci_for_each_dma_alias() callback, then calls intel_context_flush_no_pasid(), which constructs a device-selective context-cache invalidation from info->bus and info->devfn (that is, always the requester ID of the device itself). As a result, for every alias other than the device=E2=80=99s own RID, the c= ontext entry that was just cleared in memory is never invalidated in the context cache. Hardware may continue using that stale cached entry. In the scalable-mode teardown path, intel_pasid_free_table() can then free the PASID directory still referenced by that stale entry, allowing the IOMMU to walk freed memory. Fix this by passing the source ID of the entry being torn down to intel_context_flush_no_pasid(), instead of deriving it from @info. Fixes: f90584f4beb84 ("iommu/vt-d: Add helper to flush caches for context c= hange") Reported-by: Sashiko Closes: https://sashiko.dev/#/patchset/20260602233426.357499-1-baolu.lu%40l= inux.intel.com Assisted-by: Claude:claude-opus-5 Signed-off-by: Lu Baolu Reviewed-by: Samiullah Khawaja --- drivers/iommu/intel/iommu.h | 2 +- drivers/iommu/intel/iommu.c | 2 +- drivers/iommu/intel/pasid.c | 9 ++++++--- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/drivers/iommu/intel/iommu.h b/drivers/iommu/intel/iommu.h index 8a59c7c9d0a6..7f01620bf3a1 100644 --- a/drivers/iommu/intel/iommu.h +++ b/drivers/iommu/intel/iommu.h @@ -1249,7 +1249,7 @@ void cache_tag_flush_range_np(struct dmar_domain *dom= ain, unsigned long start, unsigned long end); =20 void intel_context_flush_no_pasid(struct device_domain_info *info, - struct context_entry *context, u16 did); + struct context_entry *context, u16 did, u16 sid); =20 int intel_iommu_enable_prq(struct intel_iommu *iommu); int intel_iommu_finish_prq(struct intel_iommu *iommu); diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c index 489e9ab5f698..2e3b3ab216f8 100644 --- a/drivers/iommu/intel/iommu.c +++ b/drivers/iommu/intel/iommu.c @@ -1257,7 +1257,7 @@ static void domain_context_clear_one(struct device_do= main_info *info, u8 bus, u8 context_clear_present(context); __iommu_flush_cache(iommu, context, sizeof(*context)); spin_unlock(&iommu->lock); - intel_context_flush_no_pasid(info, context, did); + intel_context_flush_no_pasid(info, context, did, PCI_DEVID(bus, devfn)); context_clear_entry(context); __iommu_flush_cache(iommu, context, sizeof(*context)); } diff --git a/drivers/iommu/intel/pasid.c b/drivers/iommu/intel/pasid.c index 81353fd46b37..e4f24d3f19a6 100644 --- a/drivers/iommu/intel/pasid.c +++ b/drivers/iommu/intel/pasid.c @@ -751,7 +751,7 @@ static void device_pasid_table_teardown(struct device *= dev, u8 bus, u8 devfn) context_clear_present(context); __iommu_flush_cache(iommu, context, sizeof(*context)); spin_unlock(&iommu->lock); - intel_context_flush_no_pasid(info, context, did); + intel_context_flush_no_pasid(info, context, did, PCI_DEVID(bus, devfn)); context_clear_entry(context); __iommu_flush_cache(iommu, context, sizeof(*context)); } @@ -955,9 +955,12 @@ static void __context_flush_dev_iotlb(struct device_do= main_info *info) * This helper can only be used when IOMMU is working in the legacy mode or * IOMMU is in scalable mode but all PASID table entries of the device are * non-present. + * + * @sid identifies the context entry that was modified, which may be a DMA + * alias of @info->dev rather than its own requester ID. */ void intel_context_flush_no_pasid(struct device_domain_info *info, - struct context_entry *context, u16 did) + struct context_entry *context, u16 did, u16 sid) { struct intel_iommu *iommu =3D info->iommu; =20 @@ -967,7 +970,7 @@ void intel_context_flush_no_pasid(struct device_domain_= info *info, * when operating in scalable mode. Therefore the @did value doesn't * matter in scalable mode. */ - iommu->flush.flush_context(iommu, did, PCI_DEVID(info->bus, info->devfn), + iommu->flush.flush_context(iommu, did, sid, DMA_CCMD_MASK_NOBIT, DMA_CCMD_DEVICE_INVL); =20 /* --=20 2.43.0