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