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

Reply via email to