[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20251202230303.1017519-18-skhawaja@google.com>
Date: Tue, 2 Dec 2025 23:02:47 +0000
From: Samiullah Khawaja <skhawaja@...gle.com>
To: David Woodhouse <dwmw2@...radead.org>, Lu Baolu <baolu.lu@...ux.intel.com>,
Joerg Roedel <joro@...tes.org>, Will Deacon <will@...nel.org>,
Pasha Tatashin <pasha.tatashin@...een.com>, Jason Gunthorpe <jgg@...pe.ca>, iommu@...ts.linux.dev
Cc: Samiullah Khawaja <skhawaja@...gle.com>, Robin Murphy <robin.murphy@....com>,
Pratyush Yadav <pratyush@...nel.org>, Kevin Tian <kevin.tian@...el.com>,
Alex Williamson <alex@...zbot.org>, linux-kernel@...r.kernel.org,
Saeed Mahameed <saeedm@...dia.com>, Adithya Jayachandran <ajayachandra@...dia.com>,
Parav Pandit <parav@...dia.com>, Leon Romanovsky <leonro@...dia.com>, William Tu <witu@...dia.com>,
Vipin Sharma <vipinsh@...gle.com>, dmatlack@...gle.com, YiFei Zhu <zhuyifei@...gle.com>,
Chris Li <chrisl@...nel.org>, praan@...gle.com
Subject: [RFC PATCH v2 17/32] iommu/vt-d: Implement device and iommu
preserve/unpreserve ops
Add implementation of the device and iommu presevation in a separate
file. Also set the device and iommu preserve/unpreserve ops in the
struct iommu_ops
Signed-off-by: Samiullah Khawaja <skhawaja@...gle.com>
---
drivers/iommu/intel/Makefile | 1 +
drivers/iommu/intel/iommu.c | 6 +-
drivers/iommu/intel/iommu.h | 9 +++
drivers/iommu/intel/liveupdate.c | 127 +++++++++++++++++++++++++++++++
4 files changed, 141 insertions(+), 2 deletions(-)
create mode 100644 drivers/iommu/intel/liveupdate.c
diff --git a/drivers/iommu/intel/Makefile b/drivers/iommu/intel/Makefile
index ada651c4a01b..58922d580c79 100644
--- a/drivers/iommu/intel/Makefile
+++ b/drivers/iommu/intel/Makefile
@@ -6,3 +6,4 @@ obj-$(CONFIG_INTEL_IOMMU_DEBUGFS) += debugfs.o
obj-$(CONFIG_INTEL_IOMMU_SVM) += svm.o
obj-$(CONFIG_IRQ_REMAP) += irq_remapping.o
obj-$(CONFIG_INTEL_IOMMU_PERF_EVENTS) += perfmon.o
+obj-$(CONFIG_LIVEUPDATE) += liveupdate.o
diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c
index d745f833d8b5..3f69a073b2d8 100644
--- a/drivers/iommu/intel/iommu.c
+++ b/drivers/iommu/intel/iommu.c
@@ -60,8 +60,6 @@ static int force_on = 0;
static int intel_iommu_tboot_noforce;
static int no_platform_optin;
-#define ROOT_ENTRY_NR (VTD_PAGE_SIZE/sizeof(struct root_entry))
-
/*
* Take a root_entry and return the Lower Context Table Pointer (LCTP)
* if marked present.
@@ -3909,6 +3907,10 @@ const struct iommu_ops intel_iommu_ops = {
.is_attach_deferred = intel_iommu_is_attach_deferred,
.def_domain_type = device_def_domain_type,
.page_response = intel_iommu_page_response,
+ .preserve_device = intel_iommu_preserve_device,
+ .unpreserve_device = intel_iommu_unpreserve_device,
+ .preserve = intel_iommu_preserve,
+ .unpreserve = intel_iommu_unpreserve,
};
static void quirk_iommu_igfx(struct pci_dev *dev)
diff --git a/drivers/iommu/intel/iommu.h b/drivers/iommu/intel/iommu.h
index 25c5e22096d4..ea88c86030bb 100644
--- a/drivers/iommu/intel/iommu.h
+++ b/drivers/iommu/intel/iommu.h
@@ -557,6 +557,8 @@ struct root_entry {
u64 hi;
};
+#define ROOT_ENTRY_NR (VTD_PAGE_SIZE/sizeof(struct root_entry))
+
/*
* low 64 bits:
* 0: present
@@ -1276,6 +1278,13 @@ static inline int iopf_for_domain_replace(struct iommu_domain *new,
return 0;
}
+#ifdef CONFIG_LIVEUPDATE
+int intel_iommu_preserve_device(struct device *dev, struct device_ser *device_ser);
+void intel_iommu_unpreserve_device(struct device *dev, struct device_ser *device_ser);
+int intel_iommu_preserve(struct iommu_device *iommu, struct iommu_ser *iommu_ser);
+void intel_iommu_unpreserve(struct iommu_device *iommu, struct iommu_ser *iommu_ser);
+#endif
+
#ifdef CONFIG_INTEL_IOMMU_SVM
void intel_svm_check(struct intel_iommu *iommu);
struct iommu_domain *intel_svm_domain_alloc(struct device *dev,
diff --git a/drivers/iommu/intel/liveupdate.c b/drivers/iommu/intel/liveupdate.c
new file mode 100644
index 000000000000..491075802e4b
--- /dev/null
+++ b/drivers/iommu/intel/liveupdate.c
@@ -0,0 +1,127 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
+/*
+ * Copyright (C) 2025, Google LLC
+ * Author: Samiullah Khawaja <skhawaja@...gle.com>
+ */
+
+#define pr_fmt(fmt) "iommu: liveupdate: " fmt
+
+#include <linux/kexec_handover.h>
+#include <linux/liveupdate.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+
+#include "iommu.h"
+#include "../iommu-pages.h"
+
+static void unpreserve_iommu_context(struct intel_iommu *iommu, int end)
+{
+ struct context_entry *context;
+ int i;
+
+ if (end < 0)
+ end = ROOT_ENTRY_NR;
+
+ for (i = 0; i < end; i++) {
+ context = iommu_context_addr(iommu, i, 0, 0);
+ if (context)
+ iommu_unpreserve_page(context);
+
+ if (!sm_supported(iommu))
+ continue;
+
+ context = iommu_context_addr(iommu, i, 0x80, 0);
+ if (context)
+ iommu_unpreserve_page(context);
+ }
+}
+
+static int preserve_iommu_context(struct intel_iommu *iommu)
+{
+ struct context_entry *context;
+ int ret;
+ int i;
+
+ for (i = 0; i < ROOT_ENTRY_NR; i++) {
+ context = iommu_context_addr(iommu, i, 0, 0);
+ if (context) {
+ ret = iommu_preserve_page(context);
+ if (ret)
+ goto error;
+ }
+
+ if (!sm_supported(iommu))
+ continue;
+
+ context = iommu_context_addr(iommu, i, 0x80, 0);
+ if (context) {
+ ret = iommu_preserve_page(context);
+ if (ret)
+ goto error_sm;
+ }
+ }
+
+ return 0;
+
+error_sm:
+ context = iommu_context_addr(iommu, i, 0, 0);
+ iommu_unpreserve_page(context);
+error:
+ unpreserve_iommu_context(iommu, i);
+ return ret;
+}
+
+int intel_iommu_preserve_device(struct device *dev, struct device_ser *device_ser)
+{
+ struct device_domain_info *info = dev_iommu_priv_get(dev);
+
+ if (!dev_is_pci(dev))
+ return -EOPNOTSUPP;
+
+ if (!info)
+ return -EINVAL;
+
+ device_ser->domain_iommu_ser.did = domain_id_iommu(info->domain, info->iommu);
+
+ /* TODO: Add support preservation of PASIDs. */
+ return 0;
+}
+
+void intel_iommu_unpreserve_device(struct device *dev, struct device_ser *device_ser)
+{
+}
+
+int intel_iommu_preserve(struct iommu_device *iommu_dev, struct iommu_ser *ser)
+{
+ struct intel_iommu *iommu;
+ int ret;
+
+ iommu = container_of(iommu_dev, struct intel_iommu, iommu);
+
+ spin_lock(&iommu->lock);
+ ret = preserve_iommu_context(iommu);
+ if (ret)
+ goto err;
+
+ ret = iommu_preserve_page(iommu->root_entry);
+ if (ret) {
+ unpreserve_iommu_context(iommu, -1);
+ goto err;
+ }
+
+ ser->intel.phys_addr = iommu->reg_phys;
+ ser->intel.root_table = __pa(iommu->root_entry);
+ ser->type = IOMMU_INTEL;
+ ser->token = ser->intel.phys_addr;
+ spin_unlock(&iommu->lock);
+
+ return 0;
+err:
+ spin_unlock(&iommu->lock);
+ return ret;
+}
+
+void intel_iommu_unpreserve(struct iommu_device *iommu, struct iommu_ser *iommu_ser)
+{
+}
--
2.52.0.158.g65b55ccf14-goog
Powered by blists - more mailing lists