[dpdk-dev] [PATCH v2 2/5] EAL: Add new EAL "--qtest-virtio" option

Tetsuya Mukawa mukawa at igel.co.jp
Wed Feb 10 04:40:10 CET 2016


To work with qtest virtio-net PMD, virtual address that maps hugepages
should be between (1 << 31) to (1 << 44). This patch adds one more option
to map like this. Also all hugepages should consists of one file.
Because of this, the option will work only when '--single-file' option is
specified.

Signed-off-by: Tetsuya Mukawa <mukawa at igel.co.jp>
---
 lib/librte_eal/common/eal_common_options.c | 10 ++++
 lib/librte_eal/common/eal_internal_cfg.h   |  1 +
 lib/librte_eal/common/eal_options.h        |  2 +
 lib/librte_eal/linuxapp/eal/eal_memory.c   | 81 +++++++++++++++++++++++++++++-
 4 files changed, 93 insertions(+), 1 deletion(-)

diff --git a/lib/librte_eal/common/eal_common_options.c b/lib/librte_eal/common/eal_common_options.c
index 65bccbd..34c8bd1 100644
--- a/lib/librte_eal/common/eal_common_options.c
+++ b/lib/librte_eal/common/eal_common_options.c
@@ -96,6 +96,7 @@ eal_long_options[] = {
 	{OPT_VMWARE_TSC_MAP,    0, NULL, OPT_VMWARE_TSC_MAP_NUM   },
 	{OPT_XEN_DOM0,          0, NULL, OPT_XEN_DOM0_NUM         },
 	{OPT_SINGLE_FILE,       0, NULL, OPT_SINGLE_FILE_NUM      },
+	{OPT_QTEST_VIRTIO,      0, NULL, OPT_QTEST_VIRTIO_NUM     },
 	{0,                     0, NULL, 0                        }
 };
 
@@ -902,6 +903,10 @@ eal_parse_common_option(int opt, const char *optarg,
 		conf->single_file = 1;
 		break;
 
+	case OPT_QTEST_VIRTIO_NUM:
+		conf->qtest_virtio = 1;
+		break;
+
 	/* don't know what to do, leave this to caller */
 	default:
 		return 1;
@@ -971,6 +976,11 @@ eal_check_common_options(struct internal_config *internal_cfg)
 			"be specified together with --"OPT_SINGLE_FILE"\n");
 		return -1;
 	}
+	if (internal_cfg->qtest_virtio && !internal_cfg->single_file) {
+		RTE_LOG(ERR, EAL, "Option --"OPT_QTEST_VIRTIO" cannot "
+			"be specified without --"OPT_SINGLE_FILE"\n");
+		return -1;
+	}
 
 	if (internal_cfg->no_hugetlbfs && internal_cfg->hugepage_unlink) {
 		RTE_LOG(ERR, EAL, "Option --"OPT_HUGE_UNLINK" cannot "
diff --git a/lib/librte_eal/common/eal_internal_cfg.h b/lib/librte_eal/common/eal_internal_cfg.h
index 9117ed9..7f3df39 100644
--- a/lib/librte_eal/common/eal_internal_cfg.h
+++ b/lib/librte_eal/common/eal_internal_cfg.h
@@ -71,6 +71,7 @@ struct internal_config {
 	volatile unsigned no_hpet;        /**< true to disable HPET */
 	volatile unsigned vmware_tsc_map; /**< true to use VMware TSC mapping
 										* instead of native TSC */
+	volatile unsigned qtest_virtio;    /**< mmap hugepages to fit qtest virtio PMD */
 	volatile unsigned no_shconf;      /**< true if there is no shared config */
 	volatile unsigned create_uio_dev; /**< true to create /dev/uioX devices */
 	volatile enum rte_proc_type_t process_type; /**< multi-process proc type */
diff --git a/lib/librte_eal/common/eal_options.h b/lib/librte_eal/common/eal_options.h
index e5da14a..b33a3c3 100644
--- a/lib/librte_eal/common/eal_options.h
+++ b/lib/librte_eal/common/eal_options.h
@@ -85,6 +85,8 @@ enum {
 	OPT_XEN_DOM0_NUM,
 #define OPT_SINGLE_FILE       "single-file"
 	OPT_SINGLE_FILE_NUM,
+#define OPT_QTEST_VIRTIO      "qtest-virtio"
+	OPT_QTEST_VIRTIO_NUM,
 	OPT_LONG_MAX_NUM
 };
 
diff --git a/lib/librte_eal/linuxapp/eal/eal_memory.c b/lib/librte_eal/linuxapp/eal/eal_memory.c
index a6b3616..677d6a7 100644
--- a/lib/librte_eal/linuxapp/eal/eal_memory.c
+++ b/lib/librte_eal/linuxapp/eal/eal_memory.c
@@ -1092,6 +1092,73 @@ calc_num_pages_per_socket(uint64_t * memory,
 }
 
 /*
+ * Find memory space that fits qtest virtio-net PMD.
+ */
+static void *
+rte_eal_get_free_region(uint64_t alloc_size, uint64_t pagesz)
+{
+	uint64_t start, end, next_start;
+	uint64_t high_limit, low_limit;
+	char buf[1024], *p;
+	FILE *fp;
+	void *addr = NULL;
+
+	/* all hugepages should be mapped between below values */
+	low_limit = 1UL << 31;
+	high_limit = 1UL << 44;
+
+	/* allocation size should be aligned by page size */
+	if (alloc_size != RTE_ALIGN_CEIL(alloc_size, pagesz)) {
+		rte_panic("Invalid allocation size 0x%lx\n", alloc_size);
+		return NULL;
+	}
+
+	/*
+	 * address should be aligned by allocation size because
+	 * BAR register requiers such an address
+	 */
+	low_limit = RTE_ALIGN_CEIL(low_limit, alloc_size);
+	high_limit = RTE_ALIGN_FLOOR(high_limit, alloc_size);
+
+	fp = fopen("/proc/self/maps", "r");
+	if (fp == NULL) {
+		rte_panic("Cannot open /proc/self/maps\n");
+		return NULL;
+	}
+
+	next_start = 0;
+	do {
+		start = next_start;
+
+		if ((p = fgets(buf, sizeof(buf), fp)) != NULL) {
+			if (sscanf(p, "%lx-%lx ", &end, &next_start) < 2)
+				break;
+
+			next_start = RTE_ALIGN_CEIL(next_start, alloc_size);
+			end = RTE_ALIGN_CEIL(end, alloc_size) - 1;
+		} else
+			end = UINT64_MAX;
+
+		if (start >= high_limit)
+			break;
+		if (end < low_limit)
+			continue;
+
+		start = RTE_MAX(start, low_limit);
+		end = RTE_MIN(end, high_limit - 1);
+
+		if (end - start >= alloc_size - 1) {
+			addr = (void *)start;
+			break;
+		}
+	} while (end != UINT64_MAX);
+
+	fclose(fp);
+
+	return addr;
+}
+
+/*
  * Prepare physical memory mapping: fill configuration structure with
  * these infos, return 0 on success.
  *  1. map N huge pages in separate files in hugetlbfs
@@ -1132,6 +1199,7 @@ rte_eal_hugepage_init(void)
 		uint64_t pagesize;
 		unsigned socket_id = rte_socket_id();
 		char filepath[MAX_HUGEPAGE_PATH];
+		void *fixed;
 
 		if (internal_config.no_hugetlbfs) {
 			eal_get_hugefile_path(filepath, sizeof(filepath),
@@ -1158,7 +1226,18 @@ rte_eal_hugepage_init(void)
 			return -1;
 		}
 
-		addr = mmap(NULL, internal_config.memory,
+		if (internal_config.qtest_virtio) {
+			fixed = rte_eal_get_free_region(
+					internal_config.memory, pagesize);
+			if (fixed == NULL) {
+				RTE_LOG(ERR, EAL, "no free space to mmap %s\n",
+						filepath);
+				return -1;
+			}
+		} else
+			fixed = NULL;
+
+		addr = mmap(fixed, internal_config.memory,
 			    PROT_READ | PROT_WRITE,
 			    MAP_SHARED | MAP_POPULATE, fd, 0);
 		if (addr == MAP_FAILED) {
-- 
2.1.4



More information about the dev mailing list