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