[v9,11/12] eal/windows: initialize hugepage info

Message ID 20200615004354.14380-12-dmitry.kozliuk@gmail.com (mailing list archive)
State Accepted, archived
Delegated to: Thomas Monjalon
Headers
Series Windows basic memory management |

Checks

Context Check Description
ci/checkpatch success coding style OK
ci/Intel-compilation fail apply issues

Commit Message

Dmitry Kozlyuk June 15, 2020, 12:43 a.m. UTC
  Add hugepages discovery ("large pages" in Windows terminology)
and update documentation for required privilege setup. Only 2MB
hugepages are supported and their number is estimated roughly
due to the lack or unstable status of suitable OS APIs.
Assign myself as maintainer for the implementation file.

Signed-off-by: Dmitry Kozlyuk <dmitry.kozliuk@gmail.com>
---
 MAINTAINERS                            |   4 +
 config/meson.build                     |   2 +
 doc/guides/windows_gsg/run_apps.rst    |  23 ++++++
 lib/librte_eal/windows/eal.c           |  14 ++++
 lib/librte_eal/windows/eal_hugepages.c | 108 +++++++++++++++++++++++++
 lib/librte_eal/windows/meson.build     |   1 +
 6 files changed, 152 insertions(+)
 create mode 100644 lib/librte_eal/windows/eal_hugepages.c
  

Patch

diff --git a/MAINTAINERS b/MAINTAINERS
index 241dbc3d7..9d5dacc23 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -334,6 +334,10 @@  F: lib/librte_eal/windows/
 F: lib/librte_eal/rte_eal_exports.def
 F: doc/guides/windows_gsg/
 
+Windows memory allocation
+M: Dmitry Kozlyuk <dmitry.kozliuk@gmail.com>
+F: lib/librte_eal/windows/eal_hugepages.c
+
 
 Core Libraries
 --------------
diff --git a/config/meson.build b/config/meson.build
index 43ab11310..c1e80de4b 100644
--- a/config/meson.build
+++ b/config/meson.build
@@ -268,6 +268,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/run_apps.rst b/doc/guides/windows_gsg/run_apps.rst
index ff4c4654f..21ac7f6c1 100644
--- a/doc/guides/windows_gsg/run_apps.rst
+++ b/doc/guides/windows_gsg/run_apps.rst
@@ -4,6 +4,29 @@ 
 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
 ------------------------------
 
diff --git a/lib/librte_eal/windows/eal.c b/lib/librte_eal/windows/eal.c
index dfc10b494..759bf4be5 100644
--- a/lib/librte_eal/windows/eal.c
+++ b/lib/librte_eal/windows/eal.c
@@ -19,8 +19,11 @@ 
 #include <eal_private.h>
 #include <rte_trace_point.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;
 
@@ -279,6 +282,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_hugepages.c b/lib/librte_eal/windows/eal_hugepages.c
new file mode 100644
index 000000000..61d0dcd3c
--- /dev/null
+++ b/lib/librte_eal/windows/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 on 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 on 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/meson.build b/lib/librte_eal/windows/meson.build
index adfc8b9b7..52978e9d7 100644
--- a/lib/librte_eal/windows/meson.build
+++ b/lib/librte_eal/windows/meson.build
@@ -6,6 +6,7 @@  subdir('include')
 sources += files(
 	'eal.c',
 	'eal_debug.c',
+	'eal_hugepages.c',
 	'eal_lcore.c',
 	'eal_log.c',
 	'eal_thread.c',