lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date: Wed, 29 Nov 2023 21:10:19 -0400
From: Jason Gunthorpe <jgg@...dia.com>
To: acpica-devel@...ts.linux.dev,
	Andy Gross <agross@...nel.org>,
	Alim Akhtar <alim.akhtar@...sung.com>,
	Alyssa Rosenzweig <alyssa@...enzweig.io>,
	Bjorn Andersson <andersson@...nel.org>,
	AngeloGioacchino Del Regno <angelogioacchino.delregno@...labora.com>,
	asahi@...ts.linux.dev,
	Baolin Wang <baolin.wang@...ux.alibaba.com>,
	devicetree@...r.kernel.org,
	Frank Rowand <frowand.list@...il.com>,
	Hanjun Guo <guohanjun@...wei.com>,
	"Gustavo A. R. Silva" <gustavoars@...nel.org>,
	Heiko Stuebner <heiko@...ech.de>,
	iommu@...ts.linux.dev,
	Jean-Philippe Brucker <jean-philippe@...aro.org>,
	Jernej Skrabec <jernej.skrabec@...il.com>,
	Jonathan Hunter <jonathanh@...dia.com>,
	Joerg Roedel <joro@...tes.org>,
	Kees Cook <keescook@...omium.org>,
	Konrad Dybcio <konrad.dybcio@...aro.org>,
	Krzysztof Kozlowski <krzysztof.kozlowski@...aro.org>,
	Len Brown <lenb@...nel.org>,
	linux-acpi@...r.kernel.org,
	linux-arm-kernel@...ts.infradead.org,
	linux-arm-msm@...r.kernel.org,
	linux-hardening@...r.kernel.org,
	linux-mediatek@...ts.infradead.org,
	linux-rockchip@...ts.infradead.org,
	linux-samsung-soc@...r.kernel.org,
	linux-sunxi@...ts.linux.dev,
	linux-tegra@...r.kernel.org,
	Lorenzo Pieralisi <lpieralisi@...nel.org>,
	Marek Szyprowski <m.szyprowski@...sung.com>,
	Hector Martin <marcan@...can.st>,
	Matthias Brugger <matthias.bgg@...il.com>,
	Orson Zhai <orsonzhai@...il.com>,
	"Rafael J. Wysocki" <rafael@...nel.org>,
	Rob Clark <robdclark@...il.com>,
	Robert Moore <robert.moore@...el.com>,
	Rob Herring <robh+dt@...nel.org>,
	Robin Murphy <robin.murphy@....com>,
	Samuel Holland <samuel@...lland.org>,
	Sudeep Holla <sudeep.holla@....com>,
	Sven Peter <sven@...npeter.dev>,
	Thierry Reding <thierry.reding@...il.com>,
	Krishna Reddy <vdumpa@...dia.com>,
	virtualization@...ts.linux.dev,
	Chen-Yu Tsai <wens@...e.org>,
	Will Deacon <will@...nel.org>,
	Yong Wu <yong.wu@...iatek.com>,
	Chunyan Zhang <zhang.lyra@...il.com>
Cc: André Draszik <andre.draszik@...aro.org>,
	patches@...ts.linux.dev
Subject: [PATCH 12/30] iommu/of: Add iommu_of_xlate()

This function can be called by drivers in their probe function if they
want to parse their own ID table, almost always because the driver
supports a multi-instance configuration and needs to extract the list of
iommu_driver's and data from the ID into some internal format.

The core code will find the iommu_driver for each ID table entry and
validate that it matches the driver's ops. A driver provided function is
called to handle the (iommu_driver, ID) tuple.

Before calling this function the driver should allocate its per-driver
private data and pass it through the opaque cookie priv argument.

Driver's should follow a typical pattern in their probe_device:

 static int apple_dart_of_xlate(struct iommu_device *iommu,
                                struct of_phandle_args *args, void *priv);
[..]

	cfg = kzalloc(sizeof(*cfg), GFP_KERNEL);
 	if (!cfg) return ERR_PTR(-ENOMEM);

	ret = iommu_of_xlate(pinf, &apple_dart_iommu_ops, 1,
			     &apple_dart_of_xlate, cfg);
	if (ret) goto err_free;

	dev_iommu_priv_set(dev, cfg);
        return &??->iommu; // The first iommu_device parsed

Signed-off-by: Jason Gunthorpe <jgg@...dia.com>
---
 drivers/iommu/of_iommu.c     | 58 ++++++++++++++++++++++++++++++++++++
 include/linux/iommu-driver.h | 13 ++++++++
 2 files changed, 71 insertions(+)

diff --git a/drivers/iommu/of_iommu.c b/drivers/iommu/of_iommu.c
index 37af32a6bc84e5..9c1d398aa2cd9c 100644
--- a/drivers/iommu/of_iommu.c
+++ b/drivers/iommu/of_iommu.c
@@ -285,6 +285,8 @@ struct parse_info {
 	struct iommu_probe_info *pinf;
 	const struct iommu_ops *ops;
 	int num_cells;
+	iommu_of_xlate_fn xlate_fn;
+	void *priv;
 };
 
 static struct iommu_device *parse_iommu(struct parse_info *info,
@@ -336,3 +338,59 @@ struct iommu_device *__iommu_of_get_single_iommu(struct iommu_probe_info *pinf,
 	return iommu_fw_finish_get_single(pinf);
 }
 EXPORT_SYMBOL_GPL(__iommu_of_get_single_iommu);
+
+static int parse_of_xlate(struct of_phandle_args *iommu_spec, void *_info)
+{
+	struct parse_info *info = _info;
+	struct iommu_device *iommu;
+
+	iommu = parse_iommu(info, iommu_spec);
+	if (IS_ERR(iommu))
+		return PTR_ERR(iommu);
+	info->pinf->num_ids++;
+	return info->xlate_fn(iommu, iommu_spec, info->priv);
+}
+
+/**
+ * iommu_of_xlate - Parse all OF ids for an IOMMU
+ * @pinf: The iommu_probe_info
+ * @ops: The ops the iommu instance must have
+ * @num_cells: #iommu-cells value to enforce, -1 is no check
+ * @fn: Call for each Instance and ID
+ * @priv: Opaque cookie for fn
+ *
+ * Drivers that support multiple iommu instances must call this function to
+ * parse each instance from the OF table. fn will be called with the driver's
+ * iommu_driver instance and the raw of_phandle_args that contains the ID.
+ *
+ * Drivers that need to parse a complex ID format should also use this function.
+ */
+int iommu_of_xlate(struct iommu_probe_info *pinf, const struct iommu_ops *ops,
+		   int num_cells, iommu_of_xlate_fn fn, void *priv)
+{
+	struct parse_info info = { .pinf = pinf,
+				   .ops = ops,
+				   .num_cells = num_cells,
+				   .xlate_fn = fn,
+				   .priv = priv };
+
+	pinf->num_ids = 0;
+	return of_iommu_for_each_id(pinf->dev, pinf->of_master_np,
+				    pinf->of_map_id, parse_of_xlate, &info);
+}
+EXPORT_SYMBOL_GPL(iommu_of_xlate);
+
+/*
+ * Temporary approach to allow drivers to opt into the bus probe. It configures
+ * the iommu_probe_info to probe the dev->of_node. This is a bit hacky because
+ * it mutates the iommu_probe_info and thus assumes there is only one op in the
+ * system. Remove when we call probe from the bus always anyhow.
+ */
+void iommu_of_allow_bus_probe(struct iommu_probe_info *pinf)
+{
+	if (pinf->is_dma_configure)
+		return;
+	pinf->of_master_np = pinf->dev->of_node;
+	pinf->is_dma_configure = true;
+}
+EXPORT_SYMBOL_GPL(iommu_of_allow_bus_probe);
diff --git a/include/linux/iommu-driver.h b/include/linux/iommu-driver.h
index 597998a62b0dd6..622d6ad9056ce0 100644
--- a/include/linux/iommu-driver.h
+++ b/include/linux/iommu-driver.h
@@ -60,9 +60,16 @@ iommu_device_from_fwnode_pinf(struct iommu_probe_info *pinf,
 			      struct fwnode_handle *fwnode);
 struct iommu_device *iommu_fw_finish_get_single(struct iommu_probe_info *pinf);
 
+typedef int (*iommu_of_xlate_fn)(struct iommu_device *iommu,
+				struct of_phandle_args *args, void *priv);
+void iommu_of_allow_bus_probe(struct iommu_probe_info *pinf);
+
 #if IS_ENABLED(CONFIG_OF_IOMMU)
 void of_iommu_get_resv_regions(struct device *dev, struct list_head *list);
 
+int iommu_of_xlate(struct iommu_probe_info *pinf, const struct iommu_ops *ops,
+		   int num_cells, iommu_of_xlate_fn fn, void *priv);
+
 struct iommu_device *__iommu_of_get_single_iommu(struct iommu_probe_info *pinf,
 						 const struct iommu_ops *ops,
 						 int num_cells);
@@ -71,6 +78,12 @@ static inline void of_iommu_get_resv_regions(struct device *dev,
 					     struct list_head *list)
 {
 }
+static inline int iommu_of_xlate(struct iommu_probe_info *pinf,
+				 const struct iommu_ops *ops, int num_cells,
+				 iommu_of_xlate_fn fn, void *priv)
+{
+	return -ENODEV;
+}
 static inline
 struct iommu_device *__iommu_of_get_single_iommu(struct iommu_probe_info *pinf,
 						 const struct iommu_ops *ops,
-- 
2.42.0


Powered by blists - more mailing lists