From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail-pf1-f197.google.com (mail-pf1-f197.google.com [209.85.210.197]) (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 00A3B34DB4A for ; Sat, 8 Aug 2026 02:27:34 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.197 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786156057; cv=none; b=d9a6wbkb1ptlmHcNihPwPiph1Z25jsEy1RWwOQWIyRhiL3Kdf1U/ZjYyGAKIHkzbUVIMttSn9w5nu4gw0JIcV1EQUgkJg3cggChw1TCH5cr0bfUgGK6d/Hk2BNzCbl7Sr4eLI8msMsfze+ahFkAbiVh/c4lhCReht3Bk3913ZRI= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786156057; c=relaxed/simple; bh=5qpVBacu4NBLAhc1pfVFf5yJFvTA4zolajEODz3I81o=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=X5oOVWHZ266ND+Fsq/oj24XrcNEgiUgvMPRmYXJOwV0kBRhuHnPMIAWQjDefHDc/aKhyAZAKPiqFOCwUP/L3xJZD00RXTsI6Bwd/zgzo6hsUEDZMUdurD8/nmNCR+2rqxmfQv554rdw2x0rs449/63uHbroZ95AUZYwm6iiwI6M= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--skhawaja.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=QG7KL5GK; arc=none smtp.client-ip=209.85.210.197 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--skhawaja.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="QG7KL5GK" Received: by mail-pf1-f197.google.com with SMTP id d2e1a72fcca58-84e13b57b2cso225106b3a.1 for ; Fri, 07 Aug 2026 19:27:34 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20251104; t=1786156054; x=1786760854; darn=vger.kernel.org; h=content-type:cc:to:from:subject:message-id:references:mime-version :in-reply-to:date:from:to:cc:subject:date:message-id:reply-to :content-type; bh=h0I5m3kRcm6Zim8yk8tuyJQnlP/R/V9C8d9m0BO5rXQ=; b=QG7KL5GKdPkYpUqmOr6gG2hjcJhlfLsD0dNg+ciGLoY9VcEbtEzbhmNlp7xy4RMcJ0 JR8WHK/Y7tno/hhrEaKy5uRssASfTU/utZU9sTn9VdyXOpCL5iX+G8P+A5HuRfV1EBjQ MCYSN4kMyovd00NkqEcyQObc8nxvxo4HDL5zA7WZ74lVvYKL3lkwgJo+TS3h8eL2ljOp VOoIRMM7dijYDvmX45C26Z7o6do+dVk70p/sU9idAzJM10Vs+FDkKDsG0SpoAgNbjl1C psqMBlsA5jJttlltk0/3z1kRFOqfUwMLj02eNlK9QUjqv0ln1ohPiQp8G4E++cPRJuCv Qs4Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1786156054; x=1786760854; h=content-type: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:content-type; bh=h0I5m3kRcm6Zim8yk8tuyJQnlP/R/V9C8d9m0BO5rXQ=; b=mQmyid74iMDsGog7UeRzJXA299J2YuPGgAyHFBsELtDyWrNazpuyv7m1mUOux6PzXP oO/fftPnlR8UoonWmIP6tsdyedEiavm2E9Kswwnjj3K/X9nMFlMpbbhAse+KUrrNs+gx oUlkh4iJKEeOO/z1DDWGhjc8AVVn7mCPBYwgPwaAPwCv9igyMdAicUdib1yk5DbC5NXH eXIS8UKhvqCiVNgkWcBrLXGu9VJIkop+doogCH+qs1RF8cm5pxAT7iyuICYiXuEo03y2 WhsJwxmgzmm6nxHgzvqQdMeBAbVUJ+hEsh2mMW8bz9TfsqaaxwQhyan9cjAI6/x0svVu h83w== X-Forwarded-Encrypted: i=1; AHgh+RrqlwAW7ZuwinufyC/jseMbP84ygOPfxrkR58ZI9PP9KV14boK04Wjq1srbrIKkxAdqmtdJ37nDKc/TI6A=@vger.kernel.org X-Gm-Message-State: AOJu0Yz+Kh/oWzpVrqkmlS/9hedeqEIjkC3fnJLgfwNS9fvMc0K/vaDG MOw6GzHIZsVBAp5YnsmZxNVcM3P9aWxRHCtVqxqKkVueO8O5thyLe4wH6PcC/acDngWRcl4HiU4 uF2X/9QYk6E3DBA== X-Received: from pfam7.prod.google.com ([2002:aa7:8a07:0:b0:847:926b:dc15]) (user=skhawaja job=prod-delivery.src-stubby-dispatcher) by 2002:a05:6a00:6c82:b0:847:5ec6:3afe with SMTP id d2e1a72fcca58-84f2e0588demr32993883b3a.31.1786156054111; Fri, 07 Aug 2026 19:27:34 -0700 (PDT) Date: Sat, 8 Aug 2026 02:27:17 +0000 In-Reply-To: <20260808022723.3893618-1-skhawaja@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20260808022723.3893618-1-skhawaja@google.com> X-Mailer: git-send-email 2.55.0.679.g6767b8d81c-goog Message-ID: <20260808022723.3893618-13-skhawaja@google.com> Subject: [PATCH v4 12/18] iommu/vt-d: Handle reattach of the restored domain From: Samiullah Khawaja To: David Woodhouse , Lu Baolu , Joerg Roedel , Will Deacon , Jason Gunthorpe Cc: Samiullah Khawaja , Robin Murphy , Kevin Tian , Alex Williamson , Shuah Khan , iommu@lists.linux.dev, linux-kernel@vger.kernel.org, kvm@vger.kernel.org, Pratyush Yadav , Pasha Tatashin , David Matlack , Andrew Morton , Pranjal Shrivastava , Vipin Sharma Content-Type: text/plain; charset="UTF-8" Reattach the restored domain to the preserved device using restored domain ID. While reattaching do not setup the context and PASID entries as those are preserved during liveupdate. Signed-off-by: Samiullah Khawaja --- drivers/iommu/intel/iommu.c | 9 ++- drivers/iommu/intel/iommu.h | 10 +++ drivers/iommu/intel/liveupdate.c | 120 +++++++++++++++++++++++++++++++ 3 files changed, 136 insertions(+), 3 deletions(-) diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c index 42d3ff6db281..5370214629f4 100644 --- a/drivers/iommu/intel/iommu.c +++ b/drivers/iommu/intel/iommu.c @@ -864,7 +864,7 @@ static bool dev_needs_extra_dtlb_flush(struct pci_dev *pdev) return true; } -static void iommu_enable_pci_ats(struct device_domain_info *info) +void intel_iommu_enable_pci_ats(struct device_domain_info *info) { struct pci_dev *pdev; @@ -1225,7 +1225,7 @@ domain_context_mapping(struct dmar_domain *domain, struct device *dev) if (ret) return ret; - iommu_enable_pci_ats(info); + intel_iommu_enable_pci_ats(info); return 0; } @@ -3164,6 +3164,9 @@ static int intel_iommu_attach_device(struct iommu_domain *domain, { int ret; + if (dev_iommu_restored_state(dev)) + return intel_iommu_restore_device(domain, dev); + device_block_translation(dev); ret = paging_domain_compatible(domain, dev); @@ -3376,7 +3379,7 @@ static void intel_iommu_probe_finalize(struct device *dev) info->pasid_enabled = 1; if (sm_supported(iommu) && !dev_is_real_dma_subdevice(dev)) { - iommu_enable_pci_ats(info); + intel_iommu_enable_pci_ats(info); /* Assign a DEVTLB cache tag to the default domain. */ if (info->ats_enabled && info->domain) { u16 did = domain_id_iommu(info->domain, iommu); diff --git a/drivers/iommu/intel/iommu.h b/drivers/iommu/intel/iommu.h index b33a12528066..1ef3b9309d44 100644 --- a/drivers/iommu/intel/iommu.h +++ b/drivers/iommu/intel/iommu.h @@ -1187,6 +1187,8 @@ void domain_detach_iommu(struct dmar_domain *domain, struct intel_iommu *iommu); void device_block_translation(struct device *dev); int paging_domain_compatible(struct iommu_domain *domain, struct device *dev); +void intel_iommu_enable_pci_ats(struct device_domain_info *info); + struct dev_pasid_info * domain_add_dev_pasid(struct iommu_domain *domain, struct device *dev, ioasid_t pasid); @@ -1309,6 +1311,8 @@ void intel_iommu_unpreserve(struct iommu_device *iommu, void clear_unpreserved_context_entries(struct intel_iommu *iommu); void intel_iommu_liveupdate_restore_root_table(struct intel_iommu *iommu, struct iommu_hw_ser *iommu_ser); +int intel_iommu_restore_device(struct iommu_domain *domain, + struct device *dev); #else static inline int intel_iommu_preserve_device(struct device *dev, struct iommu_device_ser *device_ser) @@ -1340,6 +1344,12 @@ static inline void intel_iommu_liveupdate_restore_root_table(struct intel_iommu struct iommu_hw_ser *iommu_ser) { } + +static inline int intel_iommu_restore_device(struct iommu_domain *domain, + struct device *dev) +{ + return -EOPNOTSUPP; +} #endif #ifdef CONFIG_INTEL_IOMMU_SVM diff --git a/drivers/iommu/intel/liveupdate.c b/drivers/iommu/intel/liveupdate.c index 480eab2d966b..05dea3893399 100644 --- a/drivers/iommu/intel/liveupdate.c +++ b/drivers/iommu/intel/liveupdate.c @@ -12,6 +12,7 @@ #include #include #include +#include #include "iommu.h" #include "../iommu-pages.h" @@ -342,6 +343,125 @@ void intel_iommu_liveupdate_restore_root_table(struct intel_iommu *iommu, BUG_ON(iommu_for_each_preserved_device(_restore_used_domain_ids, iommu)); } +static void domain_detach_reattached_iommu(struct dmar_domain *domain, + struct intel_iommu *iommu) +{ + struct iommu_domain_info *info; + + guard(mutex)(&iommu->did_lock); + info = xa_load(&domain->iommu_array, iommu->seq_id); + if (--info->refcnt == 0) { + xa_erase(&domain->iommu_array, iommu->seq_id); + kfree(info); + } +} + +static int domain_reattach_iommu(struct dmar_domain *domain, + struct intel_iommu *iommu, + struct iommu_device_ser *device_ser) +{ + struct iommu_domain_info *info, *curr; + int restored_did; + int ret; + + if (!iommu_domain_restored_state(&domain->domain)) + return -EINVAL; + + restored_did = device_ser->domain_iommu_ser.attachment_id; + if (!ida_exists(&iommu->domain_ida, restored_did)) + return -EINVAL; + + info = kzalloc_obj(*info); + if (!info) + return -ENOMEM; + + guard(mutex)(&iommu->did_lock); + curr = xa_load(&domain->iommu_array, iommu->seq_id); + if (curr) { + curr->refcnt++; + kfree(info); + return 0; + } + + info->refcnt = 1; + info->did = restored_did; + info->iommu = iommu; + curr = xa_cmpxchg(&domain->iommu_array, iommu->seq_id, + NULL, info, GFP_KERNEL); + if (curr) { + ret = xa_err(curr) ? : -EBUSY; + goto err_unlock; + } + + return 0; + +err_unlock: + kfree(info); + return ret; +} + +/** + * intel_iommu_restore_device() - Restore device domain attachment after live update + * @domain: Restored domain + * @dev: Restored device + * + * Return: 0 on success, or negative error code. + */ +int intel_iommu_restore_device(struct iommu_domain *domain, + struct device *dev) +{ + struct iommu_device_ser *device_ser = dev_iommu_restored_state(dev); + struct device_domain_info *info = dev_iommu_priv_get(dev); + struct dmar_domain *dmar_domain = to_dmar_domain(domain); + struct intel_iommu *iommu = info->iommu; + unsigned long flags; + int ret; + + if (!device_ser) + return -EINVAL; + + if (dev_is_real_dma_subdevice(dev)) + return -EOPNOTSUPP; + + ret = domain_reattach_iommu(dmar_domain, iommu, device_ser); + if (ret) + return ret; + + info->domain = dmar_domain; + info->domain_attached = true; + spin_lock_irqsave(&dmar_domain->lock, flags); + list_add(&info->link, &dmar_domain->devices); + spin_unlock_irqrestore(&dmar_domain->lock, flags); + + if (!sm_supported(iommu)) + intel_iommu_enable_pci_ats(info); + + ret = cache_tag_assign_domain(dmar_domain, dev, IOMMU_NO_PASID); + if (ret) + goto err; + + ret = iopf_for_domain_set(domain, dev); + if (ret) + goto err; + + return 0; + +err: + /* + * Detach the restored domain from device and iommu on failure, but keep + * the hardware state intact. + */ + info->domain_attached = false; + cache_tag_unassign_domain(info->domain, dev, IOMMU_NO_PASID); + spin_lock_irqsave(&info->domain->lock, flags); + list_del(&info->link); + spin_unlock_irqrestore(&info->domain->lock, flags); + + domain_detach_reattached_iommu(info->domain, iommu); + info->domain = NULL; + return ret; +} + /** * intel_iommu_preserve_device() - Intel IOMMU callback to preserve device state * @dev: Target device -- 2.55.0.679.g6767b8d81c-goog