xref: /linux/drivers/acpi/riscv/rimt.c (revision 68a052239fc4b351e961f698b824f7654a346091)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Copyright (C) 2024-2025, Ventana Micro Systems Inc
4  *	Author: Sunil V L <sunilvl@ventanamicro.com>
5  *
6  */
7 
8 #define pr_fmt(fmt)	"ACPI: RIMT: " fmt
9 
10 #include <linux/acpi.h>
11 #include <linux/acpi_rimt.h>
12 #include <linux/iommu.h>
13 #include <linux/list.h>
14 #include <linux/pci.h>
15 #include <linux/platform_device.h>
16 #include "init.h"
17 
18 struct rimt_fwnode {
19 	struct list_head list;
20 	struct acpi_rimt_node *rimt_node;
21 	struct fwnode_handle *fwnode;
22 };
23 
24 static LIST_HEAD(rimt_fwnode_list);
25 static DEFINE_SPINLOCK(rimt_fwnode_lock);
26 
27 #define RIMT_TYPE_MASK(type)	(1 << (type))
28 #define RIMT_IOMMU_TYPE		BIT(0)
29 
30 /* Root pointer to the mapped RIMT table */
31 static struct acpi_table_header *rimt_table;
32 
33 /**
34  * rimt_set_fwnode() - Create rimt_fwnode and use it to register
35  *		       iommu data in the rimt_fwnode_list
36  *
37  * @rimt_node: RIMT table node associated with the IOMMU
38  * @fwnode: fwnode associated with the RIMT node
39  *
40  * Returns: 0 on success
41  *          <0 on failure
42  */
43 static int rimt_set_fwnode(struct acpi_rimt_node *rimt_node,
44 			   struct fwnode_handle *fwnode)
45 {
46 	struct rimt_fwnode *np;
47 
48 	np = kzalloc(sizeof(*np), GFP_ATOMIC);
49 
50 	if (WARN_ON(!np))
51 		return -ENOMEM;
52 
53 	INIT_LIST_HEAD(&np->list);
54 	np->rimt_node = rimt_node;
55 	np->fwnode = fwnode;
56 
57 	spin_lock(&rimt_fwnode_lock);
58 	list_add_tail(&np->list, &rimt_fwnode_list);
59 	spin_unlock(&rimt_fwnode_lock);
60 
61 	return 0;
62 }
63 
64 /**
65  * rimt_get_fwnode() - Retrieve fwnode associated with an RIMT node
66  *
67  * @node: RIMT table node to be looked-up
68  *
69  * Returns: fwnode_handle pointer on success, NULL on failure
70  */
71 static struct fwnode_handle *rimt_get_fwnode(struct acpi_rimt_node *node)
72 {
73 	struct fwnode_handle *fwnode = NULL;
74 	struct rimt_fwnode *curr;
75 
76 	spin_lock(&rimt_fwnode_lock);
77 	list_for_each_entry(curr, &rimt_fwnode_list, list) {
78 		if (curr->rimt_node == node) {
79 			fwnode = curr->fwnode;
80 			break;
81 		}
82 	}
83 	spin_unlock(&rimt_fwnode_lock);
84 
85 	return fwnode;
86 }
87 
88 static acpi_status rimt_match_node_callback(struct acpi_rimt_node *node,
89 					    void *context)
90 {
91 	acpi_status status = AE_NOT_FOUND;
92 	struct device *dev = context;
93 
94 	if (node->type == ACPI_RIMT_NODE_TYPE_IOMMU) {
95 		struct acpi_rimt_iommu *iommu_node = (struct acpi_rimt_iommu *)&node->node_data;
96 
97 		if (dev_is_pci(dev)) {
98 			struct pci_dev *pdev;
99 			u16 bdf;
100 
101 			pdev = to_pci_dev(dev);
102 			bdf = PCI_DEVID(pdev->bus->number, pdev->devfn);
103 			if ((pci_domain_nr(pdev->bus) == iommu_node->pcie_segment_number) &&
104 			    bdf == iommu_node->pcie_bdf) {
105 				status = AE_OK;
106 			} else {
107 				status = AE_NOT_FOUND;
108 			}
109 		} else {
110 			struct platform_device *pdev = to_platform_device(dev);
111 			struct resource *res;
112 
113 			res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
114 			if (res && res->start == iommu_node->base_address)
115 				status = AE_OK;
116 			else
117 				status = AE_NOT_FOUND;
118 		}
119 	} else if (node->type == ACPI_RIMT_NODE_TYPE_PCIE_ROOT_COMPLEX) {
120 		struct acpi_rimt_pcie_rc *pci_rc;
121 		struct pci_bus *bus;
122 
123 		bus = to_pci_bus(dev);
124 		pci_rc = (struct acpi_rimt_pcie_rc *)node->node_data;
125 
126 		/*
127 		 * It is assumed that PCI segment numbers maps one-to-one
128 		 * with root complexes. Each segment number can represent only
129 		 * one root complex.
130 		 */
131 		status = pci_rc->pcie_segment_number == pci_domain_nr(bus) ?
132 							AE_OK : AE_NOT_FOUND;
133 	} else if (node->type == ACPI_RIMT_NODE_TYPE_PLAT_DEVICE) {
134 		struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER, NULL };
135 		struct acpi_rimt_platform_device *ncomp;
136 		struct device *plat_dev = dev;
137 		struct acpi_device *adev;
138 
139 		/*
140 		 * Walk the device tree to find a device with an
141 		 * ACPI companion; there is no point in scanning
142 		 * RIMT for a device matching a platform device if
143 		 * the device does not have an ACPI companion to
144 		 * start with.
145 		 */
146 		do {
147 			adev = ACPI_COMPANION(plat_dev);
148 			if (adev)
149 				break;
150 
151 			plat_dev = plat_dev->parent;
152 		} while (plat_dev);
153 
154 		if (!adev)
155 			return status;
156 
157 		status = acpi_get_name(adev->handle, ACPI_FULL_PATHNAME, &buf);
158 		if (ACPI_FAILURE(status)) {
159 			dev_warn(plat_dev, "Can't get device full path name\n");
160 			return status;
161 		}
162 
163 		ncomp = (struct acpi_rimt_platform_device *)node->node_data;
164 		status = !strcmp(ncomp->device_name, buf.pointer) ?
165 							AE_OK : AE_NOT_FOUND;
166 		acpi_os_free(buf.pointer);
167 	}
168 
169 	return status;
170 }
171 
172 static struct acpi_rimt_node *rimt_scan_node(enum acpi_rimt_node_type type,
173 					     void *context)
174 {
175 	struct acpi_rimt_node *rimt_node, *rimt_end;
176 	struct acpi_table_rimt *rimt;
177 	int i;
178 
179 	if (!rimt_table)
180 		return NULL;
181 
182 	/* Get the first RIMT node */
183 	rimt = (struct acpi_table_rimt *)rimt_table;
184 	rimt_node = ACPI_ADD_PTR(struct acpi_rimt_node, rimt,
185 				 rimt->node_offset);
186 	rimt_end = ACPI_ADD_PTR(struct acpi_rimt_node, rimt_table,
187 				rimt_table->length);
188 
189 	for (i = 0; i < rimt->num_nodes; i++) {
190 		if (WARN_TAINT(rimt_node >= rimt_end, TAINT_FIRMWARE_WORKAROUND,
191 			       "RIMT node pointer overflows, bad table!\n"))
192 			return NULL;
193 
194 		if (rimt_node->type == type &&
195 		    ACPI_SUCCESS(rimt_match_node_callback(rimt_node, context)))
196 			return rimt_node;
197 
198 		rimt_node = ACPI_ADD_PTR(struct acpi_rimt_node, rimt_node,
199 					 rimt_node->length);
200 	}
201 
202 	return NULL;
203 }
204 
205 static bool rimt_pcie_rc_supports_ats(struct acpi_rimt_node *node)
206 {
207 	struct acpi_rimt_pcie_rc *pci_rc;
208 
209 	pci_rc = (struct acpi_rimt_pcie_rc *)node->node_data;
210 	return pci_rc->flags & ACPI_RIMT_PCIE_ATS_SUPPORTED;
211 }
212 
213 static int rimt_iommu_xlate(struct device *dev, struct acpi_rimt_node *node, u32 deviceid)
214 {
215 	struct fwnode_handle *rimt_fwnode;
216 
217 	if (!node)
218 		return -ENODEV;
219 
220 	rimt_fwnode = rimt_get_fwnode(node);
221 
222 	/*
223 	 * The IOMMU drivers may not be probed yet.
224 	 * Defer the IOMMU configuration
225 	 */
226 	if (!rimt_fwnode)
227 		return -EPROBE_DEFER;
228 
229 	return acpi_iommu_fwspec_init(dev, deviceid, rimt_fwnode);
230 }
231 
232 struct rimt_pci_alias_info {
233 	struct device *dev;
234 	struct acpi_rimt_node *node;
235 	const struct iommu_ops *ops;
236 };
237 
238 static int rimt_id_map(struct acpi_rimt_id_mapping *map, u8 type, u32 rid_in, u32 *rid_out)
239 {
240 	if (rid_in < map->source_id_base ||
241 	    (rid_in > map->source_id_base + map->num_ids))
242 		return -ENXIO;
243 
244 	*rid_out = map->dest_id_base + (rid_in - map->source_id_base);
245 	return 0;
246 }
247 
248 static struct acpi_rimt_node *rimt_node_get_id(struct acpi_rimt_node *node,
249 					       u32 *id_out, int index)
250 {
251 	struct acpi_rimt_platform_device *plat_node;
252 	u32 id_mapping_offset, num_id_mapping;
253 	struct acpi_rimt_pcie_rc *pci_node;
254 	struct acpi_rimt_id_mapping *map;
255 	struct acpi_rimt_node *parent;
256 
257 	if (node->type == ACPI_RIMT_NODE_TYPE_PCIE_ROOT_COMPLEX) {
258 		pci_node = (struct acpi_rimt_pcie_rc *)&node->node_data;
259 		id_mapping_offset = pci_node->id_mapping_offset;
260 		num_id_mapping = pci_node->num_id_mappings;
261 	} else if (node->type == ACPI_RIMT_NODE_TYPE_PLAT_DEVICE) {
262 		plat_node = (struct acpi_rimt_platform_device *)&node->node_data;
263 		id_mapping_offset = plat_node->id_mapping_offset;
264 		num_id_mapping = plat_node->num_id_mappings;
265 	} else {
266 		return NULL;
267 	}
268 
269 	if (!id_mapping_offset || !num_id_mapping || index >= num_id_mapping)
270 		return NULL;
271 
272 	map = ACPI_ADD_PTR(struct acpi_rimt_id_mapping, node,
273 			   id_mapping_offset + index * sizeof(*map));
274 
275 	/* Firmware bug! */
276 	if (!map->dest_offset) {
277 		pr_err(FW_BUG "[node %p type %d] ID map has NULL parent reference\n",
278 		       node, node->type);
279 		return NULL;
280 	}
281 
282 	parent = ACPI_ADD_PTR(struct acpi_rimt_node, rimt_table, map->dest_offset);
283 
284 	if (node->type == ACPI_RIMT_NODE_TYPE_PLAT_DEVICE ||
285 	    node->type == ACPI_RIMT_NODE_TYPE_PCIE_ROOT_COMPLEX) {
286 		*id_out = map->dest_id_base;
287 		return parent;
288 	}
289 
290 	return NULL;
291 }
292 
293 /*
294  * RISC-V supports IOMMU as a PCI device or a platform device.
295  * When it is a platform device, there should be a namespace device as
296  * well along with RIMT. To create the link between RIMT information and
297  * the platform device, the IOMMU driver should register itself with the
298  * RIMT module. This is true for PCI based IOMMU as well.
299  */
300 int rimt_iommu_register(struct device *dev)
301 {
302 	struct fwnode_handle *rimt_fwnode;
303 	struct acpi_rimt_node *node;
304 
305 	node = rimt_scan_node(ACPI_RIMT_NODE_TYPE_IOMMU, dev);
306 	if (!node) {
307 		pr_err("Could not find IOMMU node in RIMT\n");
308 		return -ENODEV;
309 	}
310 
311 	if (dev_is_pci(dev)) {
312 		rimt_fwnode = acpi_alloc_fwnode_static();
313 		if (!rimt_fwnode)
314 			return -ENOMEM;
315 
316 		rimt_fwnode->dev = dev;
317 		if (!dev->fwnode)
318 			dev->fwnode = rimt_fwnode;
319 
320 		rimt_set_fwnode(node, rimt_fwnode);
321 	} else {
322 		rimt_set_fwnode(node, dev->fwnode);
323 	}
324 
325 	return 0;
326 }
327 
328 #ifdef CONFIG_IOMMU_API
329 
330 static struct acpi_rimt_node *rimt_node_map_id(struct acpi_rimt_node *node,
331 					       u32 id_in, u32 *id_out,
332 					       u8 type_mask)
333 {
334 	struct acpi_rimt_platform_device *plat_node;
335 	u32 id_mapping_offset, num_id_mapping;
336 	struct acpi_rimt_pcie_rc *pci_node;
337 	u32 id = id_in;
338 
339 	/* Parse the ID mapping tree to find specified node type */
340 	while (node) {
341 		struct acpi_rimt_id_mapping *map;
342 		int i, rc = 0;
343 		u32 map_id = id;
344 
345 		if (RIMT_TYPE_MASK(node->type) & type_mask) {
346 			if (id_out)
347 				*id_out = id;
348 			return node;
349 		}
350 
351 		if (node->type == ACPI_RIMT_NODE_TYPE_PCIE_ROOT_COMPLEX) {
352 			pci_node = (struct acpi_rimt_pcie_rc *)&node->node_data;
353 			id_mapping_offset = pci_node->id_mapping_offset;
354 			num_id_mapping = pci_node->num_id_mappings;
355 		} else if (node->type == ACPI_RIMT_NODE_TYPE_PLAT_DEVICE) {
356 			plat_node = (struct acpi_rimt_platform_device *)&node->node_data;
357 			id_mapping_offset = plat_node->id_mapping_offset;
358 			num_id_mapping = plat_node->num_id_mappings;
359 		} else {
360 			goto fail_map;
361 		}
362 
363 		if (!id_mapping_offset || !num_id_mapping)
364 			goto fail_map;
365 
366 		map = ACPI_ADD_PTR(struct acpi_rimt_id_mapping, node,
367 				   id_mapping_offset);
368 
369 		/* Firmware bug! */
370 		if (!map->dest_offset) {
371 			pr_err(FW_BUG "[node %p type %d] ID map has NULL parent reference\n",
372 			       node, node->type);
373 			goto fail_map;
374 		}
375 
376 		/* Do the ID translation */
377 		for (i = 0; i < num_id_mapping; i++, map++) {
378 			rc = rimt_id_map(map, node->type, map_id, &id);
379 			if (!rc)
380 				break;
381 		}
382 
383 		if (i == num_id_mapping)
384 			goto fail_map;
385 
386 		node = ACPI_ADD_PTR(struct acpi_rimt_node, rimt_table,
387 				    rc ? 0 : map->dest_offset);
388 	}
389 
390 fail_map:
391 	/* Map input ID to output ID unchanged on mapping failure */
392 	if (id_out)
393 		*id_out = id_in;
394 
395 	return NULL;
396 }
397 
398 static struct acpi_rimt_node *rimt_node_map_platform_id(struct acpi_rimt_node *node, u32 *id_out,
399 							u8 type_mask, int index)
400 {
401 	struct acpi_rimt_node *parent;
402 	u32 id;
403 
404 	parent = rimt_node_get_id(node, &id, index);
405 	if (!parent)
406 		return NULL;
407 
408 	if (!(RIMT_TYPE_MASK(parent->type) & type_mask))
409 		parent = rimt_node_map_id(parent, id, id_out, type_mask);
410 	else
411 		if (id_out)
412 			*id_out = id;
413 
414 	return parent;
415 }
416 
417 static int rimt_pci_iommu_init(struct pci_dev *pdev, u16 alias, void *data)
418 {
419 	struct rimt_pci_alias_info *info = data;
420 	struct acpi_rimt_node *parent;
421 	u32 deviceid;
422 
423 	parent = rimt_node_map_id(info->node, alias, &deviceid, RIMT_IOMMU_TYPE);
424 	return rimt_iommu_xlate(info->dev, parent, deviceid);
425 }
426 
427 static int rimt_plat_iommu_map(struct device *dev, struct acpi_rimt_node *node)
428 {
429 	struct acpi_rimt_node *parent;
430 	int err = -ENODEV, i = 0;
431 	u32 deviceid = 0;
432 
433 	do {
434 		parent = rimt_node_map_platform_id(node, &deviceid,
435 						   RIMT_IOMMU_TYPE,
436 						   i++);
437 
438 		if (parent)
439 			err = rimt_iommu_xlate(dev, parent, deviceid);
440 	} while (parent && !err);
441 
442 	return err;
443 }
444 
445 static int rimt_plat_iommu_map_id(struct device *dev,
446 				  struct acpi_rimt_node *node,
447 				  const u32 *in_id)
448 {
449 	struct acpi_rimt_node *parent;
450 	u32 deviceid;
451 
452 	parent = rimt_node_map_id(node, *in_id, &deviceid, RIMT_IOMMU_TYPE);
453 	if (parent)
454 		return rimt_iommu_xlate(dev, parent, deviceid);
455 
456 	return -ENODEV;
457 }
458 
459 /**
460  * rimt_iommu_configure_id - Set-up IOMMU configuration for a device.
461  *
462  * @dev: device to configure
463  * @id_in: optional input id const value pointer
464  *
465  * Returns: 0 on success, <0 on failure
466  */
467 int rimt_iommu_configure_id(struct device *dev, const u32 *id_in)
468 {
469 	struct acpi_rimt_node *node;
470 	int err = -ENODEV;
471 
472 	if (dev_is_pci(dev)) {
473 		struct iommu_fwspec *fwspec;
474 		struct pci_bus *bus = to_pci_dev(dev)->bus;
475 		struct rimt_pci_alias_info info = { .dev = dev };
476 
477 		node = rimt_scan_node(ACPI_RIMT_NODE_TYPE_PCIE_ROOT_COMPLEX, &bus->dev);
478 		if (!node)
479 			return -ENODEV;
480 
481 		info.node = node;
482 		err = pci_for_each_dma_alias(to_pci_dev(dev),
483 					     rimt_pci_iommu_init, &info);
484 
485 		fwspec = dev_iommu_fwspec_get(dev);
486 		if (fwspec && rimt_pcie_rc_supports_ats(node))
487 			fwspec->flags |= IOMMU_FWSPEC_PCI_RC_ATS;
488 	} else {
489 		node = rimt_scan_node(ACPI_RIMT_NODE_TYPE_PLAT_DEVICE, dev);
490 		if (!node)
491 			return -ENODEV;
492 
493 		err = id_in ? rimt_plat_iommu_map_id(dev, node, id_in) :
494 			      rimt_plat_iommu_map(dev, node);
495 	}
496 
497 	return err;
498 }
499 
500 #endif
501 
502 void __init riscv_acpi_rimt_init(void)
503 {
504 	acpi_status status;
505 
506 	/* rimt_table will be used at runtime after the rimt init,
507 	 * so we don't need to call acpi_put_table() to release
508 	 * the RIMT table mapping.
509 	 */
510 	status = acpi_get_table(ACPI_SIG_RIMT, 0, &rimt_table);
511 	if (ACPI_FAILURE(status)) {
512 		if (status != AE_NOT_FOUND) {
513 			const char *msg = acpi_format_exception(status);
514 
515 			pr_err("Failed to get table, %s\n", msg);
516 		}
517 
518 		return;
519 	}
520 }
521