From mboxrd@z Thu Jan 1 00:00:00 1970 Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.remote-ip=209.85.210.199 ARC-Seal: i=1; d=subspace.kernel.org; s=arc20261015; a=rsa-sha256; cv=none; t=1792894792; b=LiZP0h0bGUQzFfs/lb1OqMHQTEvGTbR89Ua5OCLJdiHJQ0BJaG4GBWWrGdcJRzz253T/ N8zNp2zU6hNNwXPFqF9O3tyMxM2n5sY0gTqRYq6jWTU6pE7CRSbQ4Nu94UqnLVnyC5ucq 73r7KTlLLF0mbP5se6NlI6o9JQQzyNQChTbFEcCgS5Y6S+NRYa5x7e3Nff+PxTMmvUuzy 0y3kpw7YQ34YCL2Hl/jALVYPH8BTfAXhOuyVNdEeap04BcUEpIPDp0v4nyURO4Ezp7sM9 XERZH8aJgnM1gyaIyybYg/kSuu9hkOjzGsKm5zeJodmQmcEqWwIfvYfEU0H72nLA0VQ== ARC-Message-Signature: i=1; d=subspace.kernel.org; s=arc20261015; a=rsa-sha256; c=relaxed/relaxed; t=1792894792; h=DMARC-Filter:Received:DKIM-Signature:X-Google-DKIM-Signature: X-Forwarded-Encrypted:X-Gm-Message-State:X-Received:Date:In-Reply-To: Mime-Version:References:X-Mailer:Message-ID:Subject:From:To:Cc: Content-Type; bh=gFxfqRPTTiNci0a2xkz2JDSqfxRC3WenmzWdDXFtYp8=; b=R2/FmCcJo947Oak73FLmhU0Ajvok1cjoqy34tZgF4dDIT32N6/wjVDUjrA7sXJ6kLU1a dNnU/NRYBcmH481ESHQUnIsZamZUM4k+vLYCyHhAfQPpf+q8Y7QgK+IadWBBp10xJh5VM cWBzYi9N4dAzKwm8AoCoODa6xOskF3CI/EqV1eanoWnjQ8Ifv3ZAic+pMCmo21Nrug1iD uCfARQ93xX6sEJITqMWnnwXLIcPrGc6r3SaPqrjIL3HjjyzkK3NL1b9JdmcN/DXrf8Rjh F+HboCZUxwkT2rp7VRj6TZrOR5ORc1/gbNTq6zgm3AuT0SlB0cbmVcRH7+hYuiZ4VZA== ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass header.from=google.com; spf=pass smtp.mailfrom=flex--skhawaja.bounces.google.com; dkim=pass header.d=google.com header.i=@google.com header.a=rsa-sha256 header.s=20251104 header.b=BujbbpJo; arc=none smtp.remote-ip=209.85.210.199 Received: from mail-pf1-f199.google.com (mail-pf1-f199.google.com [209.85.210.199]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits) key-exchange X25519 server-signature ECDSA (prime256v1) server-digest SHA256) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 559AC606B9E7 for ; Sun, 25 Oct 2026 02:19:52 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.2 smtp.subspace.kernel.org 559AC606B9E7 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, unprotected) header.d=google.com header.i=@google.com header.a=rsa-sha256 header.s=20251104 header.b=BujbbpJo Received: by mail-pf1-f199.google.com with SMTP id d2e1a72fcca58-8a079256596so1523758b3a.0 for ; Sat, 24 Oct 2026 19:19:52 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20251104; t=1792894792; x=1793499592; 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=gFxfqRPTTiNci0a2xkz2JDSqfxRC3WenmzWdDXFtYp8=; b=BujbbpJoFpzSmpuvNT/dFDmfu3S9LiA3F1GDyoGtiKQWshPpGl6T+mF0XGIiTTMGBd HQ3hDggJTIMBajU4bClGzKxeUfFnX8MWir+d/ql9zmF8+BJBKteVPh6pnF+vgIvhBXFE 8PWiOWam75u104l4u9VDoCx7BI19A366au0Ow+os5RCCE+XzSXsQsmNCCFnD+7tXRLo1 SkvbzKR+/TX9/AvvZ2+OF8zr5LOuCrirpCIq6f929XsGtlD8VgKIG6cp7PIu3TL6TYe2 c3zKYgedUbVCBTiTAtXIBns+ifbmOaiJZ5Kis4T+WHMqmYuXG/uiVg2uVsvAJDK/JDGT RFvA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1792894792; x=1793499592; 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=gFxfqRPTTiNci0a2xkz2JDSqfxRC3WenmzWdDXFtYp8=; b=gyncy4r0lBZGLJCtKy8FdIEFBFvu/jl387Yf/Ffkw/8/vQAZm6/f75FguyGjfvBG9E F3wpsCtU3UhupxhMVW1ha5vkBe9VQe9Icl5lYaIm/63E/jme1roZ8qDQXa4sKH9m48Wi ZW+2S4jMA1TDrFF7k55B6EE2q7PRo6iRnSA6qz2xEvYcrCBKOTFeBv/ePOIAk/VfNXRj eUp5wRV5OLSN2cOApgje+pvBMj1DNRSvecG5srfHdMeV7PRvs0TVs6zgmt+tiK3euc2B BoUPQLC2zI3lIKfgP94Szmp3ymgHFQgZmJ2eVq1tn2+lVWkTx4oxv8x6pbTGw1MTd2ls GtTA== X-Forwarded-Encrypted: i=1; AKwUvBxfMF6vjsRpdPD8tdjuIGNlNZZ5ivZL8C/d07Q9NT9SHa730QZc8BTAJHF5jMni3wxT3yg0knl2FIXNdeg=@vger.kernel.org X-Gm-Message-State: AFq9FYJEZRq4EJvEqCOPK4svtma+81rITj7PsLCs+qkCyur1jg1Cfv4p dAYVgKThDPuQscNcTVJ2OU1K3Db6vxl9Tlxah+6DxsyFgpqt7V2/idiUh6PTRy+ImYXI2O0wIXG L0yz7XjjvyVb5dw== X-Received: from pgbm22-n2.prod.google.com ([2002:a05:6a02:6196:20b0:cd6:1d17:2ccc]) (user=skhawaja job=prod-delivery.src-stubby-dispatcher) by 2002:a05:6a20:9c16:b0:3e2:8fdc:a6cf with SMTP id adf61e73a8af0-3e7bfab8c31mr2586186637.30.1792894791568; Sat, 24 Oct 2026 19:19:51 -0700 (PDT) Date: Sun, 25 Oct 2026 02:19:24 +0000 In-Reply-To: <20261025021930.674647-1-skhawaja@google.com> X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Post: List-Help: List-Subscribe: List-Unsubscribe: List-Owner: Precedence: list Mime-Version: 1.0 References: <20261025021930.674647-1-skhawaja@google.com> X-Mailer: git-send-email 2.56.0.257.gf7497c7d27-goog Message-ID: <20261025021930.674647-14-skhawaja@google.com> Subject: [PATCH v6 13/18] iommu/vt-d: Handle reattach of the restored domain From: Samiullah Khawaja To: Joerg Roedel , Will Deacon , Lu Baolu , Jason Gunthorpe , David Woodhouse 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 , Ankit Soni , Nicolin Chen , John Starks 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 | 34 ++++++-- drivers/iommu/intel/iommu.h | 14 ++++ drivers/iommu/intel/liveupdate.c | 131 +++++++++++++++++++++++++++++++ 3 files changed, 171 insertions(+), 8 deletions(-) diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c index ecec057f78dd..4f01aa34ccb5 100644 --- a/drivers/iommu/intel/iommu.c +++ b/drivers/iommu/intel/iommu.c @@ -2926,6 +2926,9 @@ static int blocking_domain_attach_dev(struct iommu_domain *domain, struct device *dev, struct iommu_domain *old) { + if (dev_iommu_restored_state(dev)) + return -EBUSY; + iopf_for_domain_remove(old, dev); device_block_translation(dev); return 0; @@ -3294,6 +3297,9 @@ static int intel_iommu_attach_device(struct iommu_domain *domain, { int ret; + if (dev_iommu_restored_state(dev)) + return intel_iommu_attach_restored_device(domain, dev); + device_block_translation(dev); ret = paging_domain_compatible(domain, dev); @@ -3424,7 +3430,8 @@ static struct iommu_device *intel_iommu_probe_device(struct device *dev) info->iommu = iommu; RB_CLEAR_NODE(&info->node); if (dev_is_pci(dev)) { - if (ecap_dev_iotlb_support(iommu->ecap) && + if (!dev_iommu_restored_state(dev) && + ecap_dev_iotlb_support(iommu->ecap) && pci_ats_supported(pdev) && dmar_ats_supported(pdev, iommu)) { info->ats_supported = 1; @@ -3529,12 +3536,16 @@ static void intel_iommu_release_device(struct device *dev) struct device_domain_info *info = dev_iommu_priv_get(dev); struct intel_iommu *iommu = info->iommu; - iommu_disable_pci_pri(info); - iommu_disable_pci_ats(info); + if (!dev_iommu_restored_state(dev)) { + iommu_disable_pci_pri(info); + iommu_disable_pci_ats(info); - if (info->pasid_enabled) { - pci_disable_pasid(to_pci_dev(dev)); - info->pasid_enabled = 0; + if (info->pasid_enabled) { + pci_disable_pasid(to_pci_dev(dev)); + info->pasid_enabled = 0; + } + } else { + intel_iommu_detach_restored_device(dev); } mutex_lock(&iommu->iopf_lock); @@ -3542,11 +3553,15 @@ static void intel_iommu_release_device(struct device *dev) device_rbtree_remove(info); mutex_unlock(&iommu->iopf_lock); - if (sm_supported(iommu) && !dev_is_real_dma_subdevice(dev) && + if (!dev_iommu_restored_state(dev) && sm_supported(iommu) && + !dev_is_real_dma_subdevice(dev) && !context_copied(iommu, info->bus, info->devfn)) intel_pasid_teardown_sm_context(dev); - intel_pasid_free_table(dev); + if (!dev_iommu_restored_state(dev)) + intel_pasid_free_table(dev); + else + kfree(info->pasid_table); intel_iommu_debugfs_remove_dev(info); kfree(info); } @@ -4003,6 +4018,9 @@ static int identity_domain_attach_dev(struct iommu_domain *domain, struct intel_iommu *iommu = info->iommu; int ret; + if (dev_iommu_restored_state(dev)) + return -EBUSY; + device_block_translation(dev); if (dev_is_real_dma_subdevice(dev)) diff --git a/drivers/iommu/intel/iommu.h b/drivers/iommu/intel/iommu.h index 260c7a5b1240..f910e5383e12 100644 --- a/drivers/iommu/intel/iommu.h +++ b/drivers/iommu/intel/iommu.h @@ -1322,6 +1322,9 @@ 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); void intel_iommu_handle_drhd_restore_failure(struct intel_iommu *iommu); +int intel_iommu_attach_restored_device(struct iommu_domain *domain, + struct device *dev); +int intel_iommu_detach_restored_device(struct device *dev); #else static inline void clear_unpreserved_context_entries(struct intel_iommu *iommu) { @@ -1335,6 +1338,17 @@ static inline void intel_iommu_liveupdate_restore_root_table(struct intel_iommu static inline void intel_iommu_handle_drhd_restore_failure(struct intel_iommu *iommu) { } + +static inline int intel_iommu_attach_restored_device(struct iommu_domain *domain, + struct device *dev) +{ + return -EOPNOTSUPP; +} + +static inline int intel_iommu_detach_restored_device(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 36816d3651e6..665ebb81bd61 100644 --- a/drivers/iommu/intel/liveupdate.c +++ b/drivers/iommu/intel/liveupdate.c @@ -394,6 +394,137 @@ void intel_iommu_handle_drhd_restore_failure(struct intel_iommu *iommu) iommu->name); } +static void domain_detach_restored_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_attach_restored_iommu(struct dmar_domain *domain, + struct intel_iommu *iommu, + struct iommu_device_ser *device_ser) +{ + struct iommu_domain_info *info, *curr; + struct iommu_domain_ser *domain_ser; + struct iommu_hw_ser *iommu_hw_ser; + int restored_did; + int ret; + + if (!iommu_domain_restored_state(&domain->domain)) + return -EINVAL; + + if (!device_ser->attachment.domain_phys || + !device_ser->iommu_phys) + return -EINVAL; + + domain_ser = phys_to_virt(device_ser->attachment.domain_phys); + if (domain_ser->restored_domain != &domain->domain) + return -EINVAL; + + iommu_hw_ser = phys_to_virt(device_ser->iommu_phys); + if (iommu_hw_ser->type != IOMMU_SER_TYPE_INTEL || + iommu_hw_ser->intel.phys_addr != iommu->reg_phys) + return -EINVAL; + + restored_did = device_ser->attachment.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_attach_restored_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_attach_restored_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; + + ret = domain_attach_restored_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); + + return 0; +} + +int intel_iommu_detach_restored_device(struct device *dev) +{ + struct device_domain_info *info = dev_iommu_priv_get(dev); + struct intel_iommu *iommu = info->iommu; + struct iommu_domain *domain; + unsigned long flags; + + if (!info->domain_attached || !info->domain) + return -EINVAL; + + domain = &info->domain->domain; + if (!iommu_domain_restored_state(domain)) + return -EINVAL; + + info->domain_attached = false; + + spin_lock_irqsave(&info->domain->lock, flags); + list_del(&info->link); + spin_unlock_irqrestore(&info->domain->lock, flags); + + domain_detach_restored_iommu(info->domain, iommu); + info->domain = NULL; + + return 0; +} + enum pasid_lu_op { PASID_LU_OP_PRESERVE = 1, PASID_LU_OP_UNPRESERVE, -- 2.56.0.257.gf7497c7d27-goog