xref: /dpdk/drivers/common/dpaax/dpaax_iova_table.c (revision fae5c5cf59b13efa1fe40d9dd75e0c8731dc46b1)
12f3d633aSShreyansh Jain /* SPDX-License-Identifier: BSD-3-Clause
23a3cdff4SGagandeep Singh  * Copyright 2018-2023 NXP
32f3d633aSShreyansh Jain  */
42f3d633aSShreyansh Jain 
52f3d633aSShreyansh Jain #include <rte_memory.h>
62f3d633aSShreyansh Jain 
72f3d633aSShreyansh Jain #include "dpaax_iova_table.h"
82f3d633aSShreyansh Jain #include "dpaax_logs.h"
92f3d633aSShreyansh Jain 
102f3d633aSShreyansh Jain /* Global table reference */
112f3d633aSShreyansh Jain struct dpaax_iova_table *dpaax_iova_table_p;
122f3d633aSShreyansh Jain 
132f3d633aSShreyansh Jain static int dpaax_handle_memevents(void);
142f3d633aSShreyansh Jain 
152f3d633aSShreyansh Jain /* A structure representing the device-tree node available in /proc/device-tree.
162f3d633aSShreyansh Jain  */
172f3d633aSShreyansh Jain struct reg_node {
182f3d633aSShreyansh Jain 	phys_addr_t addr;
192f3d633aSShreyansh Jain 	size_t len;
202f3d633aSShreyansh Jain };
212f3d633aSShreyansh Jain 
222f3d633aSShreyansh Jain /* A ntohll equivalent routine
232f3d633aSShreyansh Jain  * XXX: This is only applicable for 64 bit environment.
242f3d633aSShreyansh Jain  */
252f3d633aSShreyansh Jain static void
rotate_8(unsigned char * arr)262f3d633aSShreyansh Jain rotate_8(unsigned char *arr)
272f3d633aSShreyansh Jain {
282f3d633aSShreyansh Jain 	uint32_t temp;
292f3d633aSShreyansh Jain 	uint32_t *first_half;
302f3d633aSShreyansh Jain 	uint32_t *second_half;
312f3d633aSShreyansh Jain 
322f3d633aSShreyansh Jain 	first_half = (uint32_t *)(arr);
332f3d633aSShreyansh Jain 	second_half = (uint32_t *)(arr + 4);
342f3d633aSShreyansh Jain 
352f3d633aSShreyansh Jain 	temp = *first_half;
362f3d633aSShreyansh Jain 	*first_half = *second_half;
372f3d633aSShreyansh Jain 	*second_half = temp;
382f3d633aSShreyansh Jain 
392f3d633aSShreyansh Jain 	*first_half = ntohl(*first_half);
402f3d633aSShreyansh Jain 	*second_half = ntohl(*second_half);
412f3d633aSShreyansh Jain }
422f3d633aSShreyansh Jain 
432f3d633aSShreyansh Jain /* read_memory_nodes
442f3d633aSShreyansh Jain  * Memory layout for DPAAx platforms (LS1043, LS1046, LS1088, LS2088, LX2160)
452f3d633aSShreyansh Jain  * are populated by Uboot and available in device tree:
462f3d633aSShreyansh Jain  * /proc/device-tree/memory@<address>/reg <= register.
472f3d633aSShreyansh Jain  * Entries are of the form:
482f3d633aSShreyansh Jain  *  (<8 byte start addr><8 byte length>)(..more similar blocks of start,len>)..
492f3d633aSShreyansh Jain  *
502f3d633aSShreyansh Jain  * @param count
512f3d633aSShreyansh Jain  *    OUT populate number of entries found in memory node
522f3d633aSShreyansh Jain  * @return
532f3d633aSShreyansh Jain  *    Pointer to array of reg_node elements, count size
542f3d633aSShreyansh Jain  */
552f3d633aSShreyansh Jain static struct reg_node *
read_memory_node(unsigned int * count)562f3d633aSShreyansh Jain read_memory_node(unsigned int *count)
572f3d633aSShreyansh Jain {
582f3d633aSShreyansh Jain 	int fd, ret, i;
592f3d633aSShreyansh Jain 	unsigned int j;
602f3d633aSShreyansh Jain 	glob_t result = {0};
612f3d633aSShreyansh Jain 	struct stat statbuf = {0};
622f3d633aSShreyansh Jain 	char file_data[MEM_NODE_FILE_LEN];
632f3d633aSShreyansh Jain 	struct reg_node *nodes = NULL;
642f3d633aSShreyansh Jain 
652f3d633aSShreyansh Jain 	*count = 0;
662f3d633aSShreyansh Jain 
672f3d633aSShreyansh Jain 	ret = glob(MEM_NODE_PATH_GLOB, 0, NULL, &result);
68c9d9825bSNipun Gupta 	if (ret != 0)
69c9d9825bSNipun Gupta 		ret = glob(MEM_NODE_PATH_GLOB_VM, 0, NULL, &result);
70c9d9825bSNipun Gupta 
712f3d633aSShreyansh Jain 	if (ret != 0) {
72c9d9825bSNipun Gupta 		DPAAX_DEBUG("Unable to glob device-tree memory node (err: %d)",
73c9d9825bSNipun Gupta 			ret);
742f3d633aSShreyansh Jain 		goto out;
752f3d633aSShreyansh Jain 	}
762f3d633aSShreyansh Jain 
772f3d633aSShreyansh Jain 	if (result.gl_pathc != 1) {
782f3d633aSShreyansh Jain 		/* Either more than one memory@<addr> node found, or none.
792f3d633aSShreyansh Jain 		 * In either case, cannot work ahead.
802f3d633aSShreyansh Jain 		 */
8193ec3014SShreyansh Jain 		DPAAX_DEBUG("Found (%zu) entries in device-tree. Not supported!",
822f3d633aSShreyansh Jain 			    result.gl_pathc);
832f3d633aSShreyansh Jain 		goto out;
842f3d633aSShreyansh Jain 	}
852f3d633aSShreyansh Jain 
862f3d633aSShreyansh Jain 	DPAAX_DEBUG("Opening and parsing device-tree node: (%s)",
872f3d633aSShreyansh Jain 		    result.gl_pathv[0]);
882f3d633aSShreyansh Jain 	fd = open(result.gl_pathv[0], O_RDONLY);
892f3d633aSShreyansh Jain 	if (fd < 0) {
9093ec3014SShreyansh Jain 		DPAAX_DEBUG("Unable to open the device-tree node: (%s)(fd=%d)",
912f3d633aSShreyansh Jain 			    MEM_NODE_PATH_GLOB, fd);
922f3d633aSShreyansh Jain 		goto cleanup;
932f3d633aSShreyansh Jain 	}
942f3d633aSShreyansh Jain 
952f3d633aSShreyansh Jain 	/* Stat to get the file size */
962f3d633aSShreyansh Jain 	ret = fstat(fd, &statbuf);
972f3d633aSShreyansh Jain 	if (ret != 0) {
9893ec3014SShreyansh Jain 		DPAAX_DEBUG("Unable to get device-tree memory node size.");
992f3d633aSShreyansh Jain 		goto cleanup;
1002f3d633aSShreyansh Jain 	}
1012f3d633aSShreyansh Jain 
10240af5458SBruce Richardson 	DPAAX_DEBUG("Size of device-tree mem node: %" PRIu64, statbuf.st_size);
1032f3d633aSShreyansh Jain 	if (statbuf.st_size > MEM_NODE_FILE_LEN) {
10493ec3014SShreyansh Jain 		DPAAX_DEBUG("More memory nodes available than assumed.");
10593ec3014SShreyansh Jain 		DPAAX_DEBUG("System may not work properly!");
1062f3d633aSShreyansh Jain 	}
1072f3d633aSShreyansh Jain 
1082f3d633aSShreyansh Jain 	ret = read(fd, file_data, statbuf.st_size > MEM_NODE_FILE_LEN ?
1092f3d633aSShreyansh Jain 				  MEM_NODE_FILE_LEN : statbuf.st_size);
1102f3d633aSShreyansh Jain 	if (ret <= 0) {
11193ec3014SShreyansh Jain 		DPAAX_DEBUG("Unable to read device-tree memory node: (%d)",
11293ec3014SShreyansh Jain 			    ret);
1132f3d633aSShreyansh Jain 		goto cleanup;
1142f3d633aSShreyansh Jain 	}
1152f3d633aSShreyansh Jain 
1162f3d633aSShreyansh Jain 	/* The reg node should be multiple of 16 bytes, 8 bytes each for addr
1172f3d633aSShreyansh Jain 	 * and len.
1182f3d633aSShreyansh Jain 	 */
1192f3d633aSShreyansh Jain 	*count = (statbuf.st_size / 16);
1202f3d633aSShreyansh Jain 	if ((*count) <= 0 || (statbuf.st_size % 16 != 0)) {
12140af5458SBruce Richardson 		DPAAX_DEBUG("Invalid memory node values or count. (size=%" PRIu64 ")",
1222f3d633aSShreyansh Jain 			    statbuf.st_size);
1232f3d633aSShreyansh Jain 		goto cleanup;
1242f3d633aSShreyansh Jain 	}
1252f3d633aSShreyansh Jain 
1262f3d633aSShreyansh Jain 	/* each entry is of 16 bytes, and size/16 is total count of entries */
1272f3d633aSShreyansh Jain 	nodes = malloc(sizeof(struct reg_node) * (*count));
1282f3d633aSShreyansh Jain 	if (!nodes) {
12993ec3014SShreyansh Jain 		DPAAX_DEBUG("Failure in allocating working memory.");
1302f3d633aSShreyansh Jain 		goto cleanup;
1312f3d633aSShreyansh Jain 	}
1322f3d633aSShreyansh Jain 	memset(nodes, 0, sizeof(struct reg_node) * (*count));
1332f3d633aSShreyansh Jain 
1342f3d633aSShreyansh Jain 	for (i = 0, j = 0; i < (statbuf.st_size) && j < (*count); i += 16, j++) {
1352f3d633aSShreyansh Jain 		memcpy(&nodes[j], file_data + i, 16);
1362f3d633aSShreyansh Jain 		/* Rotate (ntohl) each 8 byte entry */
1372f3d633aSShreyansh Jain 		rotate_8((unsigned char *)(&(nodes[j].addr)));
1382f3d633aSShreyansh Jain 		rotate_8((unsigned char *)(&(nodes[j].len)));
1392f3d633aSShreyansh Jain 	}
1402f3d633aSShreyansh Jain 
1412f3d633aSShreyansh Jain 	DPAAX_DEBUG("Device-tree memory node data:");
142*fae5c5cfSApeksha Gupta 
143*fae5c5cfSApeksha Gupta 	while (j > 0) {
144*fae5c5cfSApeksha Gupta 		--j;
1455ae4079dSHemant Agrawal 		DPAAX_DEBUG("    %08" PRIx64 " %08zu",
1465ae4079dSHemant Agrawal 			    nodes[j].addr, nodes[j].len);
147*fae5c5cfSApeksha Gupta 	}
1482f3d633aSShreyansh Jain 
1492f3d633aSShreyansh Jain cleanup:
1502f3d633aSShreyansh Jain 	close(fd);
1512f3d633aSShreyansh Jain 	globfree(&result);
1522f3d633aSShreyansh Jain out:
1532f3d633aSShreyansh Jain 	return nodes;
1542f3d633aSShreyansh Jain }
1552f3d633aSShreyansh Jain 
1562f3d633aSShreyansh Jain int
dpaax_iova_table_populate(void)1572f3d633aSShreyansh Jain dpaax_iova_table_populate(void)
1582f3d633aSShreyansh Jain {
1592f3d633aSShreyansh Jain 	int ret;
1602f3d633aSShreyansh Jain 	unsigned int i, node_count;
1612f3d633aSShreyansh Jain 	size_t tot_memory_size, total_table_size;
1622f3d633aSShreyansh Jain 	struct reg_node *nodes;
1632f3d633aSShreyansh Jain 	struct dpaax_iovat_element *entry;
1642f3d633aSShreyansh Jain 
1652f3d633aSShreyansh Jain 	/* dpaax_iova_table_p is a singleton - only one instance should be
1662f3d633aSShreyansh Jain 	 * created.
1672f3d633aSShreyansh Jain 	 */
1682f3d633aSShreyansh Jain 	if (dpaax_iova_table_p) {
1692f3d633aSShreyansh Jain 		DPAAX_DEBUG("Multiple allocation attempt for IOVA Table (%p)",
1702f3d633aSShreyansh Jain 			    dpaax_iova_table_p);
1712f3d633aSShreyansh Jain 		/* This can be an error case as well - some path not cleaning
1722f3d633aSShreyansh Jain 		 * up table - but, for now, it is assumed that if IOVA Table
1732f3d633aSShreyansh Jain 		 * pointer is valid, table is allocated.
1742f3d633aSShreyansh Jain 		 */
1752f3d633aSShreyansh Jain 		return 0;
1762f3d633aSShreyansh Jain 	}
1772f3d633aSShreyansh Jain 
1782f3d633aSShreyansh Jain 	nodes = read_memory_node(&node_count);
179c390b49dSShreyansh Jain 	if (nodes == NULL) {
1802f3d633aSShreyansh Jain 		DPAAX_WARN("PA->VA translation not available;");
1812f3d633aSShreyansh Jain 		DPAAX_WARN("Expect performance impact.");
1822f3d633aSShreyansh Jain 		return -1;
1832f3d633aSShreyansh Jain 	}
1842f3d633aSShreyansh Jain 
1852f3d633aSShreyansh Jain 	tot_memory_size = 0;
1862f3d633aSShreyansh Jain 	for (i = 0; i < node_count; i++)
1872f3d633aSShreyansh Jain 		tot_memory_size += nodes[i].len;
1882f3d633aSShreyansh Jain 
1892f3d633aSShreyansh Jain 	DPAAX_DEBUG("Total available PA memory size: %zu", tot_memory_size);
1902f3d633aSShreyansh Jain 
1912f3d633aSShreyansh Jain 	/* Total table size = meta data + tot_memory_size/8 */
1922f3d633aSShreyansh Jain 	total_table_size = sizeof(struct dpaax_iova_table) +
1932f3d633aSShreyansh Jain 			   (sizeof(struct dpaax_iovat_element) * node_count) +
1942f3d633aSShreyansh Jain 			   ((tot_memory_size / DPAAX_MEM_SPLIT) * sizeof(uint64_t));
1952f3d633aSShreyansh Jain 
1962f3d633aSShreyansh Jain 	/* TODO: This memory doesn't need to shared but needs to be always
1972f3d633aSShreyansh Jain 	 * pinned to RAM (no swap out) - using hugepage rather than malloc
1982f3d633aSShreyansh Jain 	 */
1992f3d633aSShreyansh Jain 	dpaax_iova_table_p = rte_zmalloc(NULL, total_table_size, 0);
2002f3d633aSShreyansh Jain 	if (dpaax_iova_table_p == NULL) {
2012f3d633aSShreyansh Jain 		DPAAX_WARN("Unable to allocate memory for PA->VA Table;");
2022f3d633aSShreyansh Jain 		DPAAX_WARN("PA->VA translation not available;");
2032f3d633aSShreyansh Jain 		DPAAX_WARN("Expect performance impact.");
2042f3d633aSShreyansh Jain 		free(nodes);
2052f3d633aSShreyansh Jain 		return -1;
2062f3d633aSShreyansh Jain 	}
2072f3d633aSShreyansh Jain 
2082f3d633aSShreyansh Jain 	/* Initialize table */
2092f3d633aSShreyansh Jain 	dpaax_iova_table_p->count = node_count;
2102f3d633aSShreyansh Jain 	entry = dpaax_iova_table_p->entries;
2112f3d633aSShreyansh Jain 
2122f3d633aSShreyansh Jain 	DPAAX_DEBUG("IOVA Table entries: (entry start = %p)", (void *)entry);
2132f3d633aSShreyansh Jain 	DPAAX_DEBUG("\t(entry),(start),(len),(next)");
2142f3d633aSShreyansh Jain 
2152f3d633aSShreyansh Jain 	for (i = 0; i < node_count; i++) {
2162f3d633aSShreyansh Jain 		/* dpaax_iova_table_p
2172f3d633aSShreyansh Jain 		 * |   dpaax_iova_table_p->entries
2182f3d633aSShreyansh Jain 		 * |      |
2192f3d633aSShreyansh Jain 		 * |      |
2202f3d633aSShreyansh Jain 		 * V      V
2212f3d633aSShreyansh Jain 		 * +------+------+-------+---+----------+---------+---
2222f3d633aSShreyansh Jain 		 * |iova_ |entry | entry |   | pages    | pages   |
2232f3d633aSShreyansh Jain 		 * |table | 1    |  2    |...| entry 1  | entry2  |
2242f3d633aSShreyansh Jain 		 * +-----'+.-----+-------+---+;---------+;--------+---
2252f3d633aSShreyansh Jain 		 *         \      \          /          /
2262f3d633aSShreyansh Jain 		 *          `~~~~~~|~~~~~>pages        /
2272f3d633aSShreyansh Jain 		 *                  \                 /
2282f3d633aSShreyansh Jain 		 *                   `~~~~~~~~~~~>pages
2292f3d633aSShreyansh Jain 		 */
2302f3d633aSShreyansh Jain 		entry[i].start = nodes[i].addr;
2312f3d633aSShreyansh Jain 		entry[i].len = nodes[i].len;
2322f3d633aSShreyansh Jain 		if (i > 0)
2332f3d633aSShreyansh Jain 			entry[i].pages = entry[i-1].pages +
2342f3d633aSShreyansh Jain 				((entry[i-1].len/DPAAX_MEM_SPLIT));
2352f3d633aSShreyansh Jain 		else
2362f3d633aSShreyansh Jain 			entry[i].pages = (uint64_t *)((unsigned char *)entry +
2372f3d633aSShreyansh Jain 					 (sizeof(struct dpaax_iovat_element) *
2382f3d633aSShreyansh Jain 					 node_count));
2392f3d633aSShreyansh Jain 
2402f3d633aSShreyansh Jain 		DPAAX_DEBUG("\t(%u),(%8"PRIx64"),(%8zu),(%8p)",
2412f3d633aSShreyansh Jain 			    i, entry[i].start, entry[i].len, entry[i].pages);
2422f3d633aSShreyansh Jain 	}
2432f3d633aSShreyansh Jain 
2442f3d633aSShreyansh Jain 	/* Release memory associated with nodes array - not required now */
2452f3d633aSShreyansh Jain 	free(nodes);
2462f3d633aSShreyansh Jain 
2475ae4079dSHemant Agrawal 	DPAAX_DEBUG("Adding mem-event handler");
2482f3d633aSShreyansh Jain 	ret = dpaax_handle_memevents();
2492f3d633aSShreyansh Jain 	if (ret) {
2502f3d633aSShreyansh Jain 		DPAAX_ERR("Unable to add mem-event handler");
2512f3d633aSShreyansh Jain 		DPAAX_WARN("Cases with non-buffer pool mem won't work!");
2522f3d633aSShreyansh Jain 	}
2532f3d633aSShreyansh Jain 
2542f3d633aSShreyansh Jain 	return 0;
2552f3d633aSShreyansh Jain }
2562f3d633aSShreyansh Jain 
2572f3d633aSShreyansh Jain void
dpaax_iova_table_depopulate(void)2582f3d633aSShreyansh Jain dpaax_iova_table_depopulate(void)
2592f3d633aSShreyansh Jain {
2603a3cdff4SGagandeep Singh 	rte_free(dpaax_iova_table_p);
2612f3d633aSShreyansh Jain 	dpaax_iova_table_p = NULL;
2622f3d633aSShreyansh Jain 
2637be78d02SJosh Soref 	DPAAX_DEBUG("IOVA Table cleaned");
2642f3d633aSShreyansh Jain }
2652f3d633aSShreyansh Jain 
2662f3d633aSShreyansh Jain int
dpaax_iova_table_update(phys_addr_t paddr,void * vaddr,size_t length)2672f3d633aSShreyansh Jain dpaax_iova_table_update(phys_addr_t paddr, void *vaddr, size_t length)
2682f3d633aSShreyansh Jain {
2692f3d633aSShreyansh Jain 	int found = 0;
2702f3d633aSShreyansh Jain 	unsigned int i;
2712f3d633aSShreyansh Jain 	size_t req_length = length, e_offset;
2722f3d633aSShreyansh Jain 	struct dpaax_iovat_element *entry;
2732f3d633aSShreyansh Jain 	uintptr_t align_vaddr;
2742f3d633aSShreyansh Jain 	phys_addr_t align_paddr;
2752f3d633aSShreyansh Jain 
27629ba8d94SShreyansh Jain 	if (unlikely(dpaax_iova_table_p == NULL))
27729ba8d94SShreyansh Jain 		return -1;
27829ba8d94SShreyansh Jain 
2792f3d633aSShreyansh Jain 	align_paddr = paddr & DPAAX_MEM_SPLIT_MASK;
2802f3d633aSShreyansh Jain 	align_vaddr = ((uintptr_t)vaddr & DPAAX_MEM_SPLIT_MASK);
2812f3d633aSShreyansh Jain 
2822f3d633aSShreyansh Jain 	/* Check if paddr is available in table */
2832f3d633aSShreyansh Jain 	entry = dpaax_iova_table_p->entries;
2842f3d633aSShreyansh Jain 	for (i = 0; i < dpaax_iova_table_p->count; i++) {
2852f3d633aSShreyansh Jain 		if (align_paddr < entry[i].start) {
2862f3d633aSShreyansh Jain 			/* Address lower than start, but not found in previous
2872f3d633aSShreyansh Jain 			 * iteration shouldn't exist.
2882f3d633aSShreyansh Jain 			 */
2892f3d633aSShreyansh Jain 			DPAAX_ERR("Add: Incorrect entry for PA->VA Table"
2902f3d633aSShreyansh Jain 				  "(%"PRIu64")", paddr);
2912f3d633aSShreyansh Jain 			DPAAX_ERR("Add: Lowest address: %"PRIu64"",
2922f3d633aSShreyansh Jain 				  entry[i].start);
2932f3d633aSShreyansh Jain 			return -1;
2942f3d633aSShreyansh Jain 		}
2952f3d633aSShreyansh Jain 
2962f3d633aSShreyansh Jain 		if (align_paddr > (entry[i].start + entry[i].len))
2972f3d633aSShreyansh Jain 			continue;
2982f3d633aSShreyansh Jain 
2992f3d633aSShreyansh Jain 		/* align_paddr >= start && align_paddr < (start + len) */
3002f3d633aSShreyansh Jain 		found = 1;
3012f3d633aSShreyansh Jain 
3022f3d633aSShreyansh Jain 		do {
3032f3d633aSShreyansh Jain 			e_offset = ((align_paddr - entry[i].start) / DPAAX_MEM_SPLIT);
3042f3d633aSShreyansh Jain 			/* TODO: Whatif something already exists at this
3052f3d633aSShreyansh Jain 			 * location - is that an error? For now, ignoring the
3062f3d633aSShreyansh Jain 			 * case.
3072f3d633aSShreyansh Jain 			 */
3082f3d633aSShreyansh Jain 			entry[i].pages[e_offset] = align_vaddr;
3095ae4079dSHemant Agrawal #ifdef RTE_COMMON_DPAAX_DEBUG
3102f3d633aSShreyansh Jain 			DPAAX_DEBUG("Added: vaddr=%zu for Phy:%"PRIu64" at %zu"
3112f3d633aSShreyansh Jain 				    " remaining len %zu", align_vaddr,
3122f3d633aSShreyansh Jain 				    align_paddr, e_offset, req_length);
3135ae4079dSHemant Agrawal #endif
3142f3d633aSShreyansh Jain 			/* Incoming request can be larger than the
3152f3d633aSShreyansh Jain 			 * DPAAX_MEM_SPLIT size - in which case, multiple
3162f3d633aSShreyansh Jain 			 * entries in entry->pages[] are filled up.
3172f3d633aSShreyansh Jain 			 */
3182f3d633aSShreyansh Jain 			if (req_length <= DPAAX_MEM_SPLIT)
3192f3d633aSShreyansh Jain 				break;
3202f3d633aSShreyansh Jain 			align_paddr += DPAAX_MEM_SPLIT;
3212f3d633aSShreyansh Jain 			align_vaddr += DPAAX_MEM_SPLIT;
3222f3d633aSShreyansh Jain 			req_length -= DPAAX_MEM_SPLIT;
3232f3d633aSShreyansh Jain 		} while (1);
3242f3d633aSShreyansh Jain 
3252f3d633aSShreyansh Jain 		break;
3262f3d633aSShreyansh Jain 	}
3272f3d633aSShreyansh Jain 
3282f3d633aSShreyansh Jain 	if (!found) {
3292f3d633aSShreyansh Jain 		/* There might be case where the incoming physical address is
3302f3d633aSShreyansh Jain 		 * beyond the address discovered in the memory node of
3312f3d633aSShreyansh Jain 		 * device-tree. Specially if some malloc'd area is used by EAL
3322f3d633aSShreyansh Jain 		 * and the memevent handlers passes that across. But, this is
3332f3d633aSShreyansh Jain 		 * not necessarily an error.
3342f3d633aSShreyansh Jain 		 */
3352f3d633aSShreyansh Jain 		DPAAX_DEBUG("Add: Unable to find slot for vaddr:(%p),"
3362f3d633aSShreyansh Jain 			    " phy(%"PRIu64")",
3372f3d633aSShreyansh Jain 			    vaddr, paddr);
3382f3d633aSShreyansh Jain 		return -1;
3392f3d633aSShreyansh Jain 	}
3405ae4079dSHemant Agrawal #ifdef RTE_COMMON_DPAAX_DEBUG
3412f3d633aSShreyansh Jain 	DPAAX_DEBUG("Add: Found slot at (%"PRIu64")[(%zu)] for vaddr:(%p),"
3422f3d633aSShreyansh Jain 		    " phy(%"PRIu64"), len(%zu)", entry[i].start, e_offset,
3432f3d633aSShreyansh Jain 		    vaddr, paddr, length);
3445ae4079dSHemant Agrawal #endif
3452f3d633aSShreyansh Jain 	return 0;
3462f3d633aSShreyansh Jain }
3472f3d633aSShreyansh Jain 
3482f3d633aSShreyansh Jain /* dpaax_iova_table_dump
3492f3d633aSShreyansh Jain  * Dump the table, with its entries, on screen. Only works in Debug Mode
3502f3d633aSShreyansh Jain  * Not for weak hearted - the tables can get quite large
3512f3d633aSShreyansh Jain  */
3522f3d633aSShreyansh Jain void
dpaax_iova_table_dump(void)3532f3d633aSShreyansh Jain dpaax_iova_table_dump(void)
3542f3d633aSShreyansh Jain {
3552f3d633aSShreyansh Jain 	unsigned int i, j;
3562f3d633aSShreyansh Jain 	struct dpaax_iovat_element *entry;
3572f3d633aSShreyansh Jain 
3582f3d633aSShreyansh Jain 	/* In case DEBUG is not enabled, some 'if' conditions might misbehave
3592f3d633aSShreyansh Jain 	 * as they have nothing else in them  except a DPAAX_DEBUG() which if
3602f3d633aSShreyansh Jain 	 * tuned out would leave 'if' naked.
3612f3d633aSShreyansh Jain 	 */
3622f3d633aSShreyansh Jain 	if (rte_log_get_global_level() < RTE_LOG_DEBUG) {
3632f3d633aSShreyansh Jain 		DPAAX_ERR("Set log level to Debug for PA->Table dump!");
3642f3d633aSShreyansh Jain 		return;
3652f3d633aSShreyansh Jain 	}
3662f3d633aSShreyansh Jain 
3672f3d633aSShreyansh Jain 	DPAAX_DEBUG(" === Start of PA->VA Translation Table ===");
368611c394cSChengwen Feng 	if (dpaax_iova_table_p == NULL) {
3692f3d633aSShreyansh Jain 		DPAAX_DEBUG("\tNULL");
370611c394cSChengwen Feng 		return;
371611c394cSChengwen Feng 	}
3722f3d633aSShreyansh Jain 
3732f3d633aSShreyansh Jain 	entry = dpaax_iova_table_p->entries;
3742f3d633aSShreyansh Jain 	for (i = 0; i < dpaax_iova_table_p->count; i++) {
3752f3d633aSShreyansh Jain 		DPAAX_DEBUG("\t(%16i),(%16"PRIu64"),(%16zu),(%16p)",
3762f3d633aSShreyansh Jain 			    i, entry[i].start, entry[i].len, entry[i].pages);
3772f3d633aSShreyansh Jain 		DPAAX_DEBUG("\t\t          (PA),          (VA)");
3782f3d633aSShreyansh Jain 		for (j = 0; j < (entry->len/DPAAX_MEM_SPLIT); j++) {
3792f3d633aSShreyansh Jain 			if (entry[i].pages[j] == 0)
3802f3d633aSShreyansh Jain 				continue;
3812f3d633aSShreyansh Jain 			DPAAX_DEBUG("\t\t(%16"PRIx64"),(%16"PRIx64")",
3822f3d633aSShreyansh Jain 				    (entry[i].start + (j * sizeof(uint64_t))),
3832f3d633aSShreyansh Jain 				    entry[i].pages[j]);
3842f3d633aSShreyansh Jain 		}
3852f3d633aSShreyansh Jain 	}
3862f3d633aSShreyansh Jain 	DPAAX_DEBUG(" === End of PA->VA Translation Table ===");
3872f3d633aSShreyansh Jain }
3882f3d633aSShreyansh Jain 
3892f3d633aSShreyansh Jain static void
dpaax_memevent_cb(enum rte_mem_event type,const void * addr,size_t len,void * arg __rte_unused)3902f3d633aSShreyansh Jain dpaax_memevent_cb(enum rte_mem_event type, const void *addr, size_t len,
3912f3d633aSShreyansh Jain 		  void *arg __rte_unused)
3922f3d633aSShreyansh Jain {
3932f3d633aSShreyansh Jain 	struct rte_memseg_list *msl;
3942f3d633aSShreyansh Jain 	struct rte_memseg *ms;
3952f3d633aSShreyansh Jain 	size_t cur_len = 0, map_len = 0;
3962f3d633aSShreyansh Jain 	phys_addr_t phys_addr;
3972f3d633aSShreyansh Jain 	void *virt_addr;
3982f3d633aSShreyansh Jain 	int ret;
3992f3d633aSShreyansh Jain 
4002f3d633aSShreyansh Jain 	DPAAX_DEBUG("Called with addr=%p, len=%zu", addr, len);
4012f3d633aSShreyansh Jain 
4022f3d633aSShreyansh Jain 	msl = rte_mem_virt2memseg_list(addr);
4032f3d633aSShreyansh Jain 
4042f3d633aSShreyansh Jain 	while (cur_len < len) {
4052f3d633aSShreyansh Jain 		const void *va = RTE_PTR_ADD(addr, cur_len);
4062f3d633aSShreyansh Jain 
4072f3d633aSShreyansh Jain 		ms = rte_mem_virt2memseg(va, msl);
4082f3d633aSShreyansh Jain 		phys_addr = rte_mem_virt2phy(ms->addr);
4092f3d633aSShreyansh Jain 		virt_addr = ms->addr;
4102f3d633aSShreyansh Jain 		map_len = ms->len;
4115ae4079dSHemant Agrawal #ifdef RTE_COMMON_DPAAX_DEBUG
4122f3d633aSShreyansh Jain 		DPAAX_DEBUG("Request for %s, va=%p, virt_addr=%p,"
4132f3d633aSShreyansh Jain 			    "iova=%"PRIu64", map_len=%zu",
4142f3d633aSShreyansh Jain 			    type == RTE_MEM_EVENT_ALLOC ?
4152f3d633aSShreyansh Jain 			    "alloc" : "dealloc",
4162f3d633aSShreyansh Jain 			    va, virt_addr, phys_addr, map_len);
4175ae4079dSHemant Agrawal #endif
4182f3d633aSShreyansh Jain 		if (type == RTE_MEM_EVENT_ALLOC)
4192f3d633aSShreyansh Jain 			ret = dpaax_iova_table_update(phys_addr, virt_addr,
4202f3d633aSShreyansh Jain 						      map_len);
4212f3d633aSShreyansh Jain 		else
4222f3d633aSShreyansh Jain 			/* In case of mem_events for MEM_EVENT_FREE, complete
4232f3d633aSShreyansh Jain 			 * hugepage is released and its PA entry is set to 0.
4242f3d633aSShreyansh Jain 			 */
4252f3d633aSShreyansh Jain 			ret = dpaax_iova_table_update(phys_addr, 0, map_len);
4262f3d633aSShreyansh Jain 
4272f3d633aSShreyansh Jain 		if (ret != 0) {
42893ec3014SShreyansh Jain 			DPAAX_DEBUG("PA-Table entry update failed. "
4292f3d633aSShreyansh Jain 				    "Map=%d, addr=%p, len=%zu, err:(%d)",
4302f3d633aSShreyansh Jain 				    type, va, map_len, ret);
4312f3d633aSShreyansh Jain 			return;
4322f3d633aSShreyansh Jain 		}
4332f3d633aSShreyansh Jain 
4342f3d633aSShreyansh Jain 		cur_len += map_len;
4352f3d633aSShreyansh Jain 	}
4362f3d633aSShreyansh Jain }
4372f3d633aSShreyansh Jain 
4382f3d633aSShreyansh Jain static int
dpaax_memevent_walk_memsegs(const struct rte_memseg_list * msl __rte_unused,const struct rte_memseg * ms,size_t len,void * arg __rte_unused)4392f3d633aSShreyansh Jain dpaax_memevent_walk_memsegs(const struct rte_memseg_list *msl __rte_unused,
4402f3d633aSShreyansh Jain 			    const struct rte_memseg *ms, size_t len,
4412f3d633aSShreyansh Jain 			    void *arg __rte_unused)
4422f3d633aSShreyansh Jain {
4432f3d633aSShreyansh Jain 	DPAAX_DEBUG("Walking for %p (pa=%"PRIu64") and len %zu",
44472f82c43SThomas Monjalon 		    ms->addr, ms->iova, len);
4452f3d633aSShreyansh Jain 	dpaax_iova_table_update(rte_mem_virt2phy(ms->addr), ms->addr, len);
4462f3d633aSShreyansh Jain 	return 0;
4472f3d633aSShreyansh Jain }
4482f3d633aSShreyansh Jain 
4492f3d633aSShreyansh Jain static int
dpaax_handle_memevents(void)4502f3d633aSShreyansh Jain dpaax_handle_memevents(void)
4512f3d633aSShreyansh Jain {
4522f3d633aSShreyansh Jain 	/* First, walk through all memsegs and pin them, before installing
4532f3d633aSShreyansh Jain 	 * handler. This assures that all memseg which have already been
4542f3d633aSShreyansh Jain 	 * identified/allocated by EAL, are already part of PA->VA Table. This
4552f3d633aSShreyansh Jain 	 * is especially for cases where application allocates memory before
4562f3d633aSShreyansh Jain 	 * the EAL or this is an externally allocated memory passed to EAL.
4572f3d633aSShreyansh Jain 	 */
4582f3d633aSShreyansh Jain 	rte_memseg_contig_walk_thread_unsafe(dpaax_memevent_walk_memsegs, NULL);
4592f3d633aSShreyansh Jain 
4602f3d633aSShreyansh Jain 	return rte_mem_event_callback_register("dpaax_memevents_cb",
4612f3d633aSShreyansh Jain 					       dpaax_memevent_cb, NULL);
4622f3d633aSShreyansh Jain }
4632f3d633aSShreyansh Jain 
464eeded204SDavid Marchand RTE_LOG_REGISTER_DEFAULT(dpaax_logger, ERR);
465