Add hugepages discovery ("large pages" in Windows terminology)
and update documentation for required privilege setup.

Signed-off-by: Dmitry Kozlyuk <dmitry.kozl...@gmail.com>
---
 config/meson.build                         |   2 +
 doc/guides/windows_gsg/build_dpdk.rst      |  20 ----
 doc/guides/windows_gsg/index.rst           |   1 +
 doc/guides/windows_gsg/run_apps.rst        |  47 +++++++++
 lib/librte_eal/windows/eal/eal.c           |  14 +++
 lib/librte_eal/windows/eal/eal_hugepages.c | 108 +++++++++++++++++++++
 lib/librte_eal/windows/eal/meson.build     |   1 +
 7 files changed, 173 insertions(+), 20 deletions(-)
 create mode 100644 doc/guides/windows_gsg/run_apps.rst
 create mode 100644 lib/librte_eal/windows/eal/eal_hugepages.c

diff --git a/config/meson.build b/config/meson.build
index abedd76f2..73cf69814 100644
--- a/config/meson.build
+++ b/config/meson.build
@@ -263,6 +263,8 @@ if is_windows
        if cc.get_id() == 'gcc'
                add_project_arguments('-D__USE_MINGW_ANSI_STDIO', language: 'c')
        endif
+
+       add_project_link_arguments('-ladvapi32', language: 'c')
 endif
 
 if get_option('b_lto')
diff --git a/doc/guides/windows_gsg/build_dpdk.rst 
b/doc/guides/windows_gsg/build_dpdk.rst
index d46e84e3f..650483e3b 100644
--- a/doc/guides/windows_gsg/build_dpdk.rst
+++ b/doc/guides/windows_gsg/build_dpdk.rst
@@ -111,23 +111,3 @@ Depending on the distribution, paths in this file may need 
adjustments.
 
     meson --cross-file config/x86/meson_mingw.txt -Dexamples=helloworld build
     ninja -C build
-
-
-Run the helloworld example
-==========================
-
-Navigate to the examples in the build directory and run `dpdk-helloworld.exe`.
-
-.. code-block:: console
-
-    cd C:\Users\me\dpdk\build\examples
-    dpdk-helloworld.exe
-    hello from core 1
-    hello from core 3
-    hello from core 0
-    hello from core 2
-
-Note for MinGW-w64: applications are linked to ``libwinpthread-1.dll``
-by default. To run the example, either add toolchain executables directory
-to the PATH or copy the library to the working directory.
-Alternatively, static linking may be used (mind the LGPLv2.1 license).
diff --git a/doc/guides/windows_gsg/index.rst b/doc/guides/windows_gsg/index.rst
index d9b7990a8..e94593572 100644
--- a/doc/guides/windows_gsg/index.rst
+++ b/doc/guides/windows_gsg/index.rst
@@ -12,3 +12,4 @@ Getting Started Guide for Windows
 
     intro
     build_dpdk
+    run_apps
diff --git a/doc/guides/windows_gsg/run_apps.rst 
b/doc/guides/windows_gsg/run_apps.rst
new file mode 100644
index 000000000..21ac7f6c1
--- /dev/null
+++ b/doc/guides/windows_gsg/run_apps.rst
@@ -0,0 +1,47 @@
+..  SPDX-License-Identifier: BSD-3-Clause
+    Copyright(c) 2020 Dmitry Kozlyuk
+
+Running DPDK Applications
+=========================
+
+Grant *Lock pages in memory* Privilege
+--------------------------------------
+
+Use of hugepages ("large pages" in Windows terminolocy) requires
+``SeLockMemoryPrivilege`` for the user running an application.
+
+1. Open *Local Security Policy* snap in, either:
+
+   * Control Panel / Computer Management / Local Security Policy;
+   * or Win+R, type ``secpol``, press Enter.
+
+2. Open *Local Policies / User Rights Assignment / Lock pages in memory.*
+
+3. Add desired users or groups to the list of grantees.
+
+4. Privilege is applied upon next logon. In particular, if privilege has been
+   granted to current user, a logoff is required before it is available.
+
+See `Large-Page Support`_ in MSDN for details.
+
+.. _Large-page Support: 
https://docs.microsoft.com/en-us/windows/win32/memory/large-page-support
+
+
+Run the ``helloworld`` Example
+------------------------------
+
+Navigate to the examples in the build directory and run `dpdk-helloworld.exe`.
+
+.. code-block:: console
+
+    cd C:\Users\me\dpdk\build\examples
+    dpdk-helloworld.exe
+    hello from core 1
+    hello from core 3
+    hello from core 0
+    hello from core 2
+
+Note for MinGW-w64: applications are linked to ``libwinpthread-1.dll``
+by default. To run the example, either add toolchain executables directory
+to the PATH or copy the library to the working directory.
+Alternatively, static linking may be used (mind the LGPLv2.1 license).
diff --git a/lib/librte_eal/windows/eal/eal.c b/lib/librte_eal/windows/eal/eal.c
index 2cf7a04ef..a84b6147a 100644
--- a/lib/librte_eal/windows/eal/eal.c
+++ b/lib/librte_eal/windows/eal/eal.c
@@ -18,8 +18,11 @@
 #include <eal_options.h>
 #include <eal_private.h>
 
+#include "eal_hugepages.h"
 #include "eal_windows.h"
 
+#define MEMSIZE_IF_NO_HUGE_PAGE (64ULL * 1024ULL * 1024ULL)
+
  /* Allow the application to print its usage message too if set */
 static rte_usage_hook_t        rte_application_usage_hook;
 
@@ -242,6 +245,17 @@ rte_eal_init(int argc, char **argv)
        if (fctret < 0)
                exit(1);
 
+       if (!internal_config.no_hugetlbfs && (eal_hugepage_info_init() < 0)) {
+               rte_eal_init_alert("Cannot get hugepage information.");
+               rte_errno = EACCES;
+               return -1;
+       }
+
+       if (internal_config.memory == 0 && !internal_config.force_sockets) {
+               if (internal_config.no_hugetlbfs)
+                       internal_config.memory = MEMSIZE_IF_NO_HUGE_PAGE;
+       }
+
        eal_thread_init_master(rte_config.master_lcore);
 
        RTE_LCORE_FOREACH_SLAVE(i) {
diff --git a/lib/librte_eal/windows/eal/eal_hugepages.c 
b/lib/librte_eal/windows/eal/eal_hugepages.c
new file mode 100644
index 000000000..b099d13f9
--- /dev/null
+++ b/lib/librte_eal/windows/eal/eal_hugepages.c
@@ -0,0 +1,108 @@
+#include <rte_errno.h>
+#include <rte_log.h>
+#include <rte_memory.h>
+#include <rte_memzone.h>
+#include <rte_os.h>
+
+#include "eal_filesystem.h"
+#include "eal_hugepages.h"
+#include "eal_internal_cfg.h"
+#include "eal_windows.h"
+
+static int
+hugepage_claim_privilege(void)
+{
+       static const wchar_t privilege[] = L"SeLockMemoryPrivilege";
+
+       HANDLE token;
+       LUID luid;
+       TOKEN_PRIVILEGES tp;
+       int ret = -1;
+
+       if (!OpenProcessToken(GetCurrentProcess(),
+                       TOKEN_ADJUST_PRIVILEGES, &token)) {
+               RTE_LOG_WIN32_ERR("OpenProcessToken()");
+               return -1;
+       }
+
+       if (!LookupPrivilegeValueW(NULL, privilege, &luid)) {
+               RTE_LOG_WIN32_ERR("LookupPrivilegeValue(\"%S\")", privilege);
+               goto exit;
+       }
+
+       tp.PrivilegeCount = 1;
+       tp.Privileges[0].Luid = luid;
+       tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
+
+       if (!AdjustTokenPrivileges(
+                       token, FALSE, &tp, sizeof(tp), NULL, NULL)) {
+               RTE_LOG_WIN32_ERR("AdjustTokenPrivileges()");
+               goto exit;
+       }
+
+       ret = 0;
+
+exit:
+       CloseHandle(token);
+
+       return ret;
+}
+
+static int
+hugepage_info_init(void)
+{
+       struct hugepage_info *hpi;
+       unsigned int socket_id;
+       int ret = 0;
+
+       /* Only one hugepage size available in Windows. */
+       internal_config.num_hugepage_sizes = 1;
+       hpi = &internal_config.hugepage_info[0];
+
+       hpi->hugepage_sz = GetLargePageMinimum();
+       if (hpi->hugepage_sz == 0)
+               return -ENOTSUP;
+
+       /* Assume all memory on each NUMA node available for hugepages,
+        * because Windows neither advertises additional limits,
+        * nor provides an API to query them.
+        */
+       for (socket_id = 0; socket_id < rte_socket_count(); socket_id++) {
+               ULONGLONG bytes;
+               unsigned int numa_node;
+
+               numa_node = eal_socket_numa_node(socket_id);
+               if (!GetNumaAvailableMemoryNodeEx(numa_node, &bytes)) {
+                       RTE_LOG_WIN32_ERR("GetNumaAvailableMemoryNodeEx(%u)",
+                               numa_node);
+                       continue;
+               }
+
+               hpi->num_pages[socket_id] = bytes / hpi->hugepage_sz;
+               RTE_LOG(DEBUG, EAL,
+                       "Found %u hugepages of %zu bytes on socket %u\n",
+                       hpi->num_pages[socket_id], hpi->hugepage_sz, socket_id);
+       }
+
+       /* No hugepage filesystem in Windows. */
+       hpi->lock_descriptor = -1;
+       memset(hpi->hugedir, 0, sizeof(hpi->hugedir));
+
+       return ret;
+}
+
+int
+eal_hugepage_info_init(void)
+{
+       if (hugepage_claim_privilege() < 0) {
+               RTE_LOG(ERR, EAL, "Cannot claim hugepage privilege\n");
+               return -1;
+       }
+
+       if (hugepage_info_init() < 0) {
+               RTE_LOG(ERR, EAL, "Cannot get hugepage information\n");
+               return -1;
+       }
+
+       return 0;
+}
diff --git a/lib/librte_eal/windows/eal/meson.build 
b/lib/librte_eal/windows/eal/meson.build
index 21cd84459..8b407c9ae 100644
--- a/lib/librte_eal/windows/eal/meson.build
+++ b/lib/librte_eal/windows/eal/meson.build
@@ -22,6 +22,7 @@ common_sources = files(
 )
 env_sources = files('eal.c',
        'eal_debug.c',
+       'eal_hugepages.c',
        'eal_lcore.c',
        'eal_thread.c',
        'getopt.c',
-- 
2.25.1

Reply via email to