From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail-pf1-f201.google.com (mail-pf1-f201.google.com [209.85.210.201]) (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 9310E38E8B6 for ; Sun, 14 Jun 2026 23:37:43 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.201 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1781480266; cv=none; b=kUr2vmjPh98JRQSmhlUGNfaNuZ1JsIyKh/W4btt4C2X4n/dwqVquUPI9z3KvJBhgcDY+tl1GLSCbOWpspRKVdVXCgZyWCQ9xmqrZANYYzQmxM3B4nN+hyXXT8yb0Qu9yASEfs6lUuHfUrFjBM8ziJT1tiVMkuKcCA3YgI0rsjEA= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1781480266; c=relaxed/simple; bh=w1Nrt1DPDRflTkd7XZpFoQm8H8bCpYk151oEiyENXZw=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=JT8cgEE5Ddu0QDOWc6PoryZHs7DDEj3tEyN2WIht5xBiYh5DehIZskICTt/JgSyx/h030264wOHXvOKak9Vof7GXKCi7AtX7bnsXEhSvEEPnOcUgPlyTVEC7ZtU4FcxkuunqrQenwKIM12Mcgj8x0ktHuOIXTnFMZ7u205xQ1Qc= 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=dCwAJ+Dq; arc=none smtp.client-ip=209.85.210.201 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="dCwAJ+Dq" Received: by mail-pf1-f201.google.com with SMTP id d2e1a72fcca58-84240683a82so1996629b3a.1 for ; Sun, 14 Jun 2026 16:37:43 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20251104; t=1781480263; x=1782085063; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=Gjm+J/sDlpbKzFCPRSBGIw0iFcduYCgoTrVDKBULpsY=; b=dCwAJ+DqhEJtok3RdmFzE6/Iq3meyg0wl6QfbQJM9zH7+t/6Y3JEwK7up/fGsQamsL mYe0th2HoUol/fzIMVHO3BTllub0GmEuH/PMEG1FwThyodU/19xX23IwUoUajuSK0IDB VbDH7wTJHqEjnnVWpEDtEmUjxZ0+Ogba54vMGoD3LhJt32AiMO4otZXK2LSWFmiXlyYQ 7hzYTZn3+D5KYbqwG8uXlJgaPzZVW2YMq8QvZtKp70vtfHAZtqP/WGBaf7Sjxy+rruoB SgA/+J2SX8HQUbVeagaznJxZk6iLgwlgiVWddfWWBYFCTXY4qzkUNXNOaBUDLxkAeCY1 PCpA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1781480263; x=1782085063; h=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; bh=Gjm+J/sDlpbKzFCPRSBGIw0iFcduYCgoTrVDKBULpsY=; b=g2LAKfreL0rxZ6YSk69nttFV45UnjYW4xlmmWXv+tvlzhu4omszzMlCmRgSFwHAEGb HO2tRaoPKoG3LdRwij0d+esckFGcMcNmt89d9lClanbal2sx/577WjH/4VFuwJjKzo27 9tKQ/v/gAveNGM+clOjVW+pKQeVQolxQwEETi7a6gj8sTxEp3XkggrS4rfOI4NF/oZ2/ ZGX6o8qKXRuXVWJ5qzrYYgQtP4QB5jXCbz6f1OtBaHCpTYuLrs9DChz62ABhIYXh9uey 1IBm7h2YzstH9xu+zIhY4eYzHlWwu7SrdRyI470AGT9l8GqdSvO2MIlTuhgMezZR6qK5 CEtQ== X-Forwarded-Encrypted: i=1; AFNElJ+ruy/hnKPm4/httpRTVHP33FcqgOMa1wRgY9khwnooBD7nc+2+IfxfrtE98+541iyu9Qz74SZEXAqfa6s=@vger.kernel.org X-Gm-Message-State: AOJu0YzR+iJ0rycvsEKn7LMI/Tf23ZQSN53ucacpydjNjmR6H8u9SxgZ ii6OiIg7Bfd8Sb4O9E9A8QIJtCTlxAh23xZ4EKaoor49S7/w88P+cc3jj2q5DBw/jYX4K52GrSc bdoAD6DKU2tEZVQ== X-Received: from pfw3.prod.google.com ([2002:a05:6a00:a263:b0:82f:4d28:b8c5]) (user=skhawaja job=prod-delivery.src-stubby-dispatcher) by 2002:a05:6a00:3993:b0:835:51fd:b7ea with SMTP id d2e1a72fcca58-8434975254bmr9961638b3a.19.1781480262726; Sun, 14 Jun 2026 16:37:42 -0700 (PDT) Date: Sun, 14 Jun 2026 23:37:26 +0000 In-Reply-To: <20260614233728.2212104-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: <20260614233728.2212104-1-skhawaja@google.com> X-Mailer: git-send-email 2.54.0.1136.gdb2ca164c4-goog Message-ID: <20260614233728.2212104-17-skhawaja@google.com> Subject: [PATCH v3 16/18] iommufd: Add APIs to preserve/unpreserve a vfio cdev 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" Add APIs that can be used to preserve and unpreserve a vfio cdev. Use the APIs exported by the IOMMU core to preserve/unpreserve device. The LUO token of the preserved iommufd is fetched and returned back to the caller as that can be used during restore to get the restored iommufd. Handle to the preserved state of the device is also returned to reassociate with the restored state after live update kexec. Reviewed-by: Pranjal Shrivastava Signed-off-by: Samiullah Khawaja --- drivers/iommu/iommufd/device.c | 102 ++++++++++++++++++++++++ drivers/iommu/iommufd/iommufd_private.h | 3 + include/linux/iommufd.h | 29 +++++++ 3 files changed, 134 insertions(+) diff --git a/drivers/iommu/iommufd/device.c b/drivers/iommu/iommufd/device.c index 170a7005f0bc..d19fece00da3 100644 --- a/drivers/iommu/iommufd/device.c +++ b/drivers/iommu/iommufd/device.c @@ -2,6 +2,7 @@ /* Copyright (c) 2021-2022, NVIDIA CORPORATION & AFFILIATES */ #include +#include #include #include #include @@ -610,6 +611,10 @@ int iommufd_hw_pagetable_attach(struct iommufd_hw_pagetable *hwpt, int rc; mutex_lock(&igroup->lock); + if (iommufd_device_is_preserved(idev)) { + rc = -EBUSY; + goto err_unlock; + } attach = xa_cmpxchg(&igroup->pasid_attach, pasid, NULL, XA_ZERO_ENTRY, GFP_KERNEL); @@ -1665,3 +1670,100 @@ int iommufd_get_hw_info(struct iommufd_ucmd *ucmd) iommufd_put_object(ucmd->ictx, &idev->obj); return rc; } + +#ifdef CONFIG_IOMMU_LIVEUPDATE +static bool _iommufd_device_has_pasid_attachments(struct iommufd_device *idev) +{ + struct iommufd_group *igroup = idev->igroup; + unsigned long start = IOMMU_NO_PASID; + + if (xa_find_after(&igroup->pasid_attach, + &start, UINT_MAX, XA_PRESENT)) + return true; + + return false; +} + +int iommufd_device_preserve(struct liveupdate_session *s, + struct iommufd_device *idev, + u64 *iommufd_tokenp, + u64 *preserved_state) +{ + struct iommufd_group *igroup = idev->igroup; + struct iommufd_hwpt_paging *hwpt_paging; + struct iommufd_hw_pagetable *hwpt; + struct iommufd_attach *attach; + int ret; + + mutex_lock(&igroup->lock); + if (_iommufd_device_has_pasid_attachments(idev)) { + ret = -EOPNOTSUPP; + goto out; + } + + attach = xa_load(&igroup->pasid_attach, IOMMU_NO_PASID); + if (!attach) { + ret = -ENOENT; + goto out; + } + + hwpt = attach->hwpt; + hwpt_paging = find_hwpt_paging(hwpt); + if (!hwpt_paging || !hwpt_paging->liveupdate_preserved) { + ret = -EINVAL; + goto out; + } + + ret = liveupdate_get_token_outgoing(s, idev->ictx->file, iommufd_tokenp); + if (ret) + goto out; + + ret = iommu_preserve_device(hwpt_paging->common.domain, + idev->dev, + preserved_state); + + if (!ret) + igroup->liveupdate_preserved = true; +out: + mutex_unlock(&igroup->lock); + return ret; +} +EXPORT_SYMBOL_NS_GPL(iommufd_device_preserve, "IOMMUFD"); + +void iommufd_device_unpreserve(struct liveupdate_session *s, + struct iommufd_device *idev) +{ + struct iommufd_group *igroup = idev->igroup; + struct iommufd_hwpt_paging *hwpt_paging; + struct iommufd_hw_pagetable *hwpt; + struct iommufd_attach *attach; + + mutex_lock(&igroup->lock); + attach = xa_load(&igroup->pasid_attach, IOMMU_NO_PASID); + if (!attach) { + WARN(1, "IOMMU_NO_PASID attachment not found"); + igroup->liveupdate_preserved = false; + goto out; + } + + hwpt = attach->hwpt; + hwpt_paging = find_hwpt_paging(hwpt); + if (!hwpt_paging || !hwpt_paging->liveupdate_preserved) { + WARN(1, "Attached domain is not preserved"); + igroup->liveupdate_preserved = false; + goto out; + } + + iommu_unpreserve_device(hwpt_paging->common.domain, idev->dev); + igroup->liveupdate_preserved = false; +out: + mutex_unlock(&igroup->lock); +} +EXPORT_SYMBOL_NS_GPL(iommufd_device_unpreserve, "IOMMUFD"); + +bool iommufd_device_is_preserved(struct iommufd_device *idev) +{ + return idev && idev->igroup && idev->igroup->liveupdate_preserved; +} +EXPORT_SYMBOL_NS_GPL(iommufd_device_is_preserved, "IOMMUFD"); +#endif diff --git a/drivers/iommu/iommufd/iommufd_private.h b/drivers/iommu/iommufd/iommufd_private.h index 9e0e46f1f7ed..c217d00e2b6d 100644 --- a/drivers/iommu/iommufd/iommufd_private.h +++ b/drivers/iommu/iommufd/iommufd_private.h @@ -486,6 +486,9 @@ struct iommufd_group { struct xarray pasid_attach; struct iommufd_sw_msi_maps required_sw_msi; phys_addr_t sw_msi_start; +#ifdef CONFIG_IOMMU_LIVEUPDATE + bool liveupdate_preserved; +#endif }; /* diff --git a/include/linux/iommufd.h b/include/linux/iommufd.h index 6e7efe83bc5d..d1fd5d71e0fd 100644 --- a/include/linux/iommufd.h +++ b/include/linux/iommufd.h @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -71,6 +72,34 @@ void iommufd_device_detach(struct iommufd_device *idev, ioasid_t pasid); struct iommufd_ctx *iommufd_device_to_ictx(struct iommufd_device *idev); u32 iommufd_device_to_id(struct iommufd_device *idev); +#ifdef CONFIG_IOMMU_LIVEUPDATE +int iommufd_device_preserve(struct liveupdate_session *s, + struct iommufd_device *idev, + u64 *iommufd_tokenp, + u64 *preserved_state); +void iommufd_device_unpreserve(struct liveupdate_session *s, + struct iommufd_device *idev); +bool iommufd_device_is_preserved(struct iommufd_device *idev); +#else +static inline int iommufd_device_preserve(struct liveupdate_session *s, + struct iommufd_device *idev, + u64 *iommufd_tokenp, + u64 *preserved_state) +{ + return -EOPNOTSUPP; +} + +static inline void iommufd_device_unpreserve(struct liveupdate_session *s, + struct iommufd_device *idev) +{ +} + +static inline bool iommufd_device_is_preserved(struct iommufd_device *idev) +{ + return false; +} +#endif + struct iommufd_access_ops { u8 needs_pin_pages : 1; void (*unmap)(void *data, unsigned long iova, unsigned long length); -- 2.54.0.1136.gdb2ca164c4-goog