From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.9]) (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 0DDC3345EC0 for ; Mon, 28 Sep 2026 03:39:24 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=192.198.163.9 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790566765; cv=none; b=AQulrqXQ+EX33wuqn/qvoYC+qKrVo/Z2b4dZYXCyzdu0Caoa0cnZ7GipBXntV6g8L/8BFbNpH6bqng2aj22OMbPjtXw+oUZponXt3t+9tpkz5fErcXjY6dgf5S0ReIFOxgv1YPj2Ru+wyMt3GzaTeMOB+SzTDNWj9wSXR8GJnGY= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790566765; c=relaxed/simple; bh=8ySS42gq8m32VjZ8WeEMReLFtdCCfmGoLff6CDCDGr8=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Tl86QlCTNehdAJ3JTTS24MqQ+5pRQGywlUWAWyLL3HPEroBnGr8mdRYLw8UgWLPt14+167mG+kHRZFCMlCySNWT7GrSYKaU4CHDqMELZl0/Kq3gFo29OuXatglmm2AbWQtTF1+xl+5E5XZKdiCh1ZYj5qzSOUxmbsfM5FQwUVaA= 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=N/zYEa14; arc=none smtp.client-ip=192.198.163.9 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="N/zYEa14" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1790566764; x=1822102764; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=8ySS42gq8m32VjZ8WeEMReLFtdCCfmGoLff6CDCDGr8=; b=N/zYEa14BNnmBKPMXAm3BvTWxj57gCBC0f/2qfZHDAZoTWHxIUMeCpTi 5UUTwGYgRDQI4/AvBHJ5aHH2kVGcY3kAKaLJeOdSUL/pQu6QU+tkzD8Ai QGsJ+Li1nS05BNZJH/JxvtqrAViaQtismxdNEAvelxAmTCFRUQYXbTf+e G1YZ0q7z8wBIoUTvHoxgczHVVkl5lJ2AmjpVNDmgcrn9arwpx28A2rIFn ZqXs6OBWBjXm8sRHcLHyeqK99OGScXTMPqXx0JRkB7juk9SuX8RmvYooJ Pk7rYfsf5dydYRbVBm6EP026ty7a22P5DG78cPw+dfFWq2VdK1n62iJnb A==; X-CSE-ConnectionGUID: PvM/ijzbS7uYUVgcwQv7FA== X-CSE-MsgGUID: yoGb1ByBQwGgBOg74absKA== X-IronPort-AV: E=McAfee;i="6800,10657,11918"; a="101917208" X-IronPort-AV: E=Sophos;i="6.27,127,1787036400"; d="scan'208";a="101917208" Received: from fmviesa005.fm.intel.com ([10.60.135.145]) by fmvoesa103.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 27 Sep 2026 20:39:24 -0700 X-CSE-ConnectionGUID: XehOyJ67T/umdnuAoaN2Zg== X-CSE-MsgGUID: TOlmPmeETXu0Cw0XAGHktA== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.27,127,1787036400"; d="scan'208";a="283004097" Received: from allen-box.sh.intel.com ([10.239.48.101]) by fmviesa005.fm.intel.com with ESMTP; 27 Sep 2026 20:39:22 -0700 From: Lu Baolu To: Joerg Roedel Cc: Guanghui Feng , Zhenzhong Duan , iommu@lists.linux.dev, linux-kernel@vger.kernel.org Subject: [PATCH 5/9] iommu/vt-d: Reserve scalable-mode DIDs from PASID entries during copy Date: Mon, 28 Sep 2026 11:27:18 +0800 Message-ID: <20260928032722.2868623-6-baolu.lu@linux.intel.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260928032722.2868623-1-baolu.lu@linux.intel.com> References: <20260928032722.2868623-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: 8bit copy_context_table() reserves old domain IDs (DIDs) from context entries. That works for legacy mode, but not for scalable mode: scalable context entries do not carry DID, so this path ends up reserving the wrong value (often DID 0) repeatedly. In scalable mode, real DIDs are stored in PASID table entries. If they are not reserved during kdump table copy, new domains may reuse old DIDs while stale PASID/IOTLB cache state still exists, causing translation conflicts and DMA faults. Fix this by walking PASID tables in scalable mode, and reserving DIDs from present PASID entries. If PASID structures cannot be remapped, return error so caller can fall back safely instead of continuing with an unsafe DID space. Fixes: 0c5f6c0d8201 ("iommu/vt-d: Fix kdump kernels boot failure with scalable mode") Signed-off-by: Lu Baolu Reviewed-by: Kevin Tian --- drivers/iommu/intel/iommu.c | 74 ++++++++++++++++++++++++++++++++++++- 1 file changed, 72 insertions(+), 2 deletions(-) diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c index 85400d0ab334..c9e246e8f8e2 100644 --- a/drivers/iommu/intel/iommu.c +++ b/drivers/iommu/intel/iommu.c @@ -1479,6 +1479,70 @@ static int reserve_domain_id(struct intel_iommu *iommu, int did) return ret; } +/* + * Reserve the domain IDs used by a scalable mode context entry copied from + * the previous kernel. + */ +static int copy_pasid_table_dids(struct intel_iommu *iommu, struct context_entry *ce) +{ + struct pasid_dir_entry *dir; + unsigned long dir_size; + phys_addr_t dir_phys; + int ret = 0; + int i, j; + + dir_phys = ce->lo & VTD_PAGE_MASK; + if (!dir_phys) + return 0; + + dir_size = get_pasid_dir_size(ce); + dir = memremap(dir_phys, dir_size * sizeof(*dir), MEMREMAP_WB); + if (!dir) + return -ENOMEM; + + for (i = 0; i < dir_size; i++) { + struct pasid_entry *table; + phys_addr_t table_phys; + + if (!pasid_pde_is_present(&dir[i])) + continue; + + /* + * Do not use get_pasid_table_from_pde(); that returns a + * phys_to_virt() pointer, which is not valid for memory + * owned by the previous kernel. + */ + table_phys = READ_ONCE(dir[i].val) & PDE_PFN_MASK; + if (!table_phys) + continue; + + /* A PASID table is one page: PASID_TBL_ENTRIES * 64 bytes. */ + table = memremap(table_phys, PAGE_SIZE, MEMREMAP_WB); + if (!table) { + ret = -ENOMEM; + goto out; + } + + for (j = 0; j < PASID_TBL_ENTRIES; j++) { + if (!pasid_pte_is_present(&table[j])) + continue; + + ret = reserve_domain_id(iommu, pasid_get_domain_id(&table[j])); + if (ret) { + memunmap(table); + goto out; + } + } + + memunmap(table); + } + +out: + memunmap(dir); + + return ret; +} + static int copy_context_table(struct intel_iommu *iommu, struct root_entry *old_re, struct context_entry **tbl, @@ -1546,8 +1610,14 @@ static int copy_context_table(struct intel_iommu *iommu, if (!context_present(&ce)) continue; - - ret = reserve_domain_id(iommu, context_domain_id(&ce)); + /* + * The context entry only holds a domain ID in legacy mode. + * In scalable mode the IDs are in the PASID table entries. + */ + if (ext) + ret = copy_pasid_table_dids(iommu, &ce); + else + ret = reserve_domain_id(iommu, context_domain_id(&ce)); if (ret) { /* Not yet published through @tbl, so free it here. */ iommu_free_pages(new_ce); -- 2.43.0