xref: /dpdk/lib/eal/windows/eal_memory.c (revision ae67895b507bb6af22263c79ba0d5c374b396485)
199a2dd95SBruce Richardson /* SPDX-License-Identifier: BSD-3-Clause
299a2dd95SBruce Richardson  * Copyright (c) 2020 Dmitry Kozlyuk
399a2dd95SBruce Richardson  */
499a2dd95SBruce Richardson 
599a2dd95SBruce Richardson #include <inttypes.h>
699a2dd95SBruce Richardson #include <io.h>
799a2dd95SBruce Richardson 
899a2dd95SBruce Richardson #include <rte_eal_paging.h>
999a2dd95SBruce Richardson #include <rte_errno.h>
1099a2dd95SBruce Richardson 
1199a2dd95SBruce Richardson #include "eal_internal_cfg.h"
1299a2dd95SBruce Richardson #include "eal_memalloc.h"
1399a2dd95SBruce Richardson #include "eal_memcfg.h"
1499a2dd95SBruce Richardson #include "eal_options.h"
1599a2dd95SBruce Richardson #include "eal_private.h"
1699a2dd95SBruce Richardson #include "eal_windows.h"
1799a2dd95SBruce Richardson 
1899a2dd95SBruce Richardson #include <rte_virt2phys.h>
1999a2dd95SBruce Richardson 
2099a2dd95SBruce Richardson /* MinGW-w64 headers lack VirtualAlloc2() in some distributions.
2199a2dd95SBruce Richardson  * Note: definitions are copied verbatim from Microsoft documentation
2299a2dd95SBruce Richardson  * and don't follow DPDK code style.
2399a2dd95SBruce Richardson  */
2499a2dd95SBruce Richardson #ifndef MEM_EXTENDED_PARAMETER_TYPE_BITS
2599a2dd95SBruce Richardson 
2699a2dd95SBruce Richardson #define MEM_EXTENDED_PARAMETER_TYPE_BITS 4
2799a2dd95SBruce Richardson 
2899a2dd95SBruce Richardson /* https://docs.microsoft.com/en-us/windows/win32/api/winnt/ne-winnt-mem_extended_parameter_type */
2999a2dd95SBruce Richardson typedef enum MEM_EXTENDED_PARAMETER_TYPE {
3099a2dd95SBruce Richardson 	MemExtendedParameterInvalidType,
3199a2dd95SBruce Richardson 	MemExtendedParameterAddressRequirements,
3299a2dd95SBruce Richardson 	MemExtendedParameterNumaNode,
3399a2dd95SBruce Richardson 	MemExtendedParameterPartitionHandle,
3499a2dd95SBruce Richardson 	MemExtendedParameterUserPhysicalHandle,
3599a2dd95SBruce Richardson 	MemExtendedParameterAttributeFlags,
3699a2dd95SBruce Richardson 	MemExtendedParameterMax
3799a2dd95SBruce Richardson } *PMEM_EXTENDED_PARAMETER_TYPE;
3899a2dd95SBruce Richardson 
3999a2dd95SBruce Richardson /* https://docs.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-mem_extended_parameter */
4099a2dd95SBruce Richardson typedef struct MEM_EXTENDED_PARAMETER {
4199a2dd95SBruce Richardson 	struct {
4299a2dd95SBruce Richardson 		DWORD64 Type : MEM_EXTENDED_PARAMETER_TYPE_BITS;
4399a2dd95SBruce Richardson 		DWORD64 Reserved : 64 - MEM_EXTENDED_PARAMETER_TYPE_BITS;
4499a2dd95SBruce Richardson 	} DUMMYSTRUCTNAME;
4599a2dd95SBruce Richardson 	union {
4699a2dd95SBruce Richardson 		DWORD64 ULong64;
4799a2dd95SBruce Richardson 		PVOID   Pointer;
4899a2dd95SBruce Richardson 		SIZE_T  Size;
4999a2dd95SBruce Richardson 		HANDLE  Handle;
5099a2dd95SBruce Richardson 		DWORD   ULong;
5199a2dd95SBruce Richardson 	} DUMMYUNIONNAME;
5299a2dd95SBruce Richardson } MEM_EXTENDED_PARAMETER, *PMEM_EXTENDED_PARAMETER;
5399a2dd95SBruce Richardson 
5499a2dd95SBruce Richardson #endif /* defined(MEM_EXTENDED_PARAMETER_TYPE_BITS) */
5599a2dd95SBruce Richardson 
5699a2dd95SBruce Richardson /* https://docs.microsoft.com/en-us/windows/win32/api/memoryapi/nf-memoryapi-virtualalloc2 */
5799a2dd95SBruce Richardson typedef PVOID (*VirtualAlloc2_type)(
5899a2dd95SBruce Richardson 	HANDLE                 Process,
5999a2dd95SBruce Richardson 	PVOID                  BaseAddress,
6099a2dd95SBruce Richardson 	SIZE_T                 Size,
6199a2dd95SBruce Richardson 	ULONG                  AllocationType,
6299a2dd95SBruce Richardson 	ULONG                  PageProtection,
6399a2dd95SBruce Richardson 	MEM_EXTENDED_PARAMETER *ExtendedParameters,
6499a2dd95SBruce Richardson 	ULONG                  ParameterCount
6599a2dd95SBruce Richardson );
6699a2dd95SBruce Richardson 
6799a2dd95SBruce Richardson /* MinGW-w64 distributions, even those that declare VirtualAlloc2(),
6899a2dd95SBruce Richardson  * lack it in import libraries, which results in a failure at link time.
6999a2dd95SBruce Richardson  * Link it dynamically in such case.
7099a2dd95SBruce Richardson  */
7199a2dd95SBruce Richardson static VirtualAlloc2_type VirtualAlloc2_ptr;
7299a2dd95SBruce Richardson 
7399a2dd95SBruce Richardson #ifdef RTE_TOOLCHAIN_GCC
7499a2dd95SBruce Richardson 
75c6221c66SGregory Etelson #ifndef MEM_COALESCE_PLACEHOLDERS
7699a2dd95SBruce Richardson #define MEM_COALESCE_PLACEHOLDERS 0x00000001
77c6221c66SGregory Etelson #endif
78c6221c66SGregory Etelson #ifndef MEM_PRESERVE_PLACEHOLDER
7999a2dd95SBruce Richardson #define MEM_PRESERVE_PLACEHOLDER  0x00000002
80c6221c66SGregory Etelson #endif
81c6221c66SGregory Etelson #ifndef MEM_REPLACE_PLACEHOLDER
8299a2dd95SBruce Richardson #define MEM_REPLACE_PLACEHOLDER   0x00004000
83c6221c66SGregory Etelson #endif
84c6221c66SGregory Etelson #ifndef MEM_RESERVE_PLACEHOLDER
8599a2dd95SBruce Richardson #define MEM_RESERVE_PLACEHOLDER   0x00040000
86c6221c66SGregory Etelson #endif
8799a2dd95SBruce Richardson 
8899a2dd95SBruce Richardson int
eal_mem_win32api_init(void)8999a2dd95SBruce Richardson eal_mem_win32api_init(void)
9099a2dd95SBruce Richardson {
9199a2dd95SBruce Richardson 	/* Contrary to the docs, VirtualAlloc2() is not in kernel32.dll,
9299a2dd95SBruce Richardson 	 * see https://github.com/MicrosoftDocs/feedback/issues/1129.
9399a2dd95SBruce Richardson 	 */
9499a2dd95SBruce Richardson 	static const char library_name[] = "kernelbase.dll";
9599a2dd95SBruce Richardson 	static const char function[] = "VirtualAlloc2";
9699a2dd95SBruce Richardson 
9799a2dd95SBruce Richardson 	HMODULE library = NULL;
9899a2dd95SBruce Richardson 	int ret = 0;
9999a2dd95SBruce Richardson 
10099a2dd95SBruce Richardson 	/* Already done. */
10199a2dd95SBruce Richardson 	if (VirtualAlloc2_ptr != NULL)
10299a2dd95SBruce Richardson 		return 0;
10399a2dd95SBruce Richardson 
10499a2dd95SBruce Richardson 	library = LoadLibraryA(library_name);
10599a2dd95SBruce Richardson 	if (library == NULL) {
10699a2dd95SBruce Richardson 		RTE_LOG_WIN32_ERR("LoadLibraryA(\"%s\")", library_name);
10799a2dd95SBruce Richardson 		return -1;
10899a2dd95SBruce Richardson 	}
10999a2dd95SBruce Richardson 
11099a2dd95SBruce Richardson 	VirtualAlloc2_ptr = (VirtualAlloc2_type)(
11199a2dd95SBruce Richardson 		(void *)GetProcAddress(library, function));
11299a2dd95SBruce Richardson 	if (VirtualAlloc2_ptr == NULL) {
113ae282b06SDavid Marchand 		RTE_LOG_WIN32_ERR("GetProcAddress(\"%s\", \"%s\")",
11499a2dd95SBruce Richardson 			library_name, function);
11599a2dd95SBruce Richardson 
11699a2dd95SBruce Richardson 		/* Contrary to the docs, Server 2016 is not supported. */
117*ae67895bSDavid Marchand 		EAL_LOG(ERR, "Windows 10 or Windows Server 2019 "
118*ae67895bSDavid Marchand 			" is required for memory management");
11999a2dd95SBruce Richardson 		ret = -1;
12099a2dd95SBruce Richardson 	}
12199a2dd95SBruce Richardson 
12299a2dd95SBruce Richardson 	FreeLibrary(library);
12399a2dd95SBruce Richardson 
12499a2dd95SBruce Richardson 	return ret;
12599a2dd95SBruce Richardson }
12699a2dd95SBruce Richardson 
12799a2dd95SBruce Richardson #else
12899a2dd95SBruce Richardson 
12999a2dd95SBruce Richardson /* Stub in case VirtualAlloc2() is provided by the toolchain. */
13099a2dd95SBruce Richardson int
eal_mem_win32api_init(void)13199a2dd95SBruce Richardson eal_mem_win32api_init(void)
13299a2dd95SBruce Richardson {
13399a2dd95SBruce Richardson 	VirtualAlloc2_ptr = VirtualAlloc2;
13499a2dd95SBruce Richardson 	return 0;
13599a2dd95SBruce Richardson }
13699a2dd95SBruce Richardson 
13799a2dd95SBruce Richardson #endif /* defined(RTE_TOOLCHAIN_GCC) */
13899a2dd95SBruce Richardson 
13999a2dd95SBruce Richardson static HANDLE virt2phys_device = INVALID_HANDLE_VALUE;
14099a2dd95SBruce Richardson 
14199a2dd95SBruce Richardson int
eal_mem_virt2iova_init(void)14299a2dd95SBruce Richardson eal_mem_virt2iova_init(void)
14399a2dd95SBruce Richardson {
14499a2dd95SBruce Richardson 	HDEVINFO list = INVALID_HANDLE_VALUE;
14599a2dd95SBruce Richardson 	SP_DEVICE_INTERFACE_DATA ifdata;
14699a2dd95SBruce Richardson 	SP_DEVICE_INTERFACE_DETAIL_DATA *detail = NULL;
14799a2dd95SBruce Richardson 	DWORD detail_size;
14899a2dd95SBruce Richardson 	int ret = -1;
14999a2dd95SBruce Richardson 
15099a2dd95SBruce Richardson 	list = SetupDiGetClassDevs(
15199a2dd95SBruce Richardson 		&GUID_DEVINTERFACE_VIRT2PHYS, NULL, NULL,
15299a2dd95SBruce Richardson 		DIGCF_DEVICEINTERFACE | DIGCF_PRESENT);
15399a2dd95SBruce Richardson 	if (list == INVALID_HANDLE_VALUE) {
15499a2dd95SBruce Richardson 		RTE_LOG_WIN32_ERR("SetupDiGetClassDevs()");
15599a2dd95SBruce Richardson 		goto exit;
15699a2dd95SBruce Richardson 	}
15799a2dd95SBruce Richardson 
15899a2dd95SBruce Richardson 	ifdata.cbSize = sizeof(ifdata);
15999a2dd95SBruce Richardson 	if (!SetupDiEnumDeviceInterfaces(
16099a2dd95SBruce Richardson 		list, NULL, &GUID_DEVINTERFACE_VIRT2PHYS, 0, &ifdata)) {
16199a2dd95SBruce Richardson 		RTE_LOG_WIN32_ERR("SetupDiEnumDeviceInterfaces()");
16299a2dd95SBruce Richardson 		goto exit;
16399a2dd95SBruce Richardson 	}
16499a2dd95SBruce Richardson 
16599a2dd95SBruce Richardson 	if (!SetupDiGetDeviceInterfaceDetail(
16699a2dd95SBruce Richardson 		list, &ifdata, NULL, 0, &detail_size, NULL)) {
16799a2dd95SBruce Richardson 		if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
16899a2dd95SBruce Richardson 			RTE_LOG_WIN32_ERR(
16999a2dd95SBruce Richardson 				"SetupDiGetDeviceInterfaceDetail(probe)");
17099a2dd95SBruce Richardson 			goto exit;
17199a2dd95SBruce Richardson 		}
17299a2dd95SBruce Richardson 	}
17399a2dd95SBruce Richardson 
17499a2dd95SBruce Richardson 	detail = malloc(detail_size);
17599a2dd95SBruce Richardson 	if (detail == NULL) {
176*ae67895bSDavid Marchand 		EAL_LOG(ERR, "Cannot allocate virt2phys "
177*ae67895bSDavid Marchand 			"device interface detail data");
17899a2dd95SBruce Richardson 		goto exit;
17999a2dd95SBruce Richardson 	}
18099a2dd95SBruce Richardson 
18199a2dd95SBruce Richardson 	detail->cbSize = sizeof(*detail);
18299a2dd95SBruce Richardson 	if (!SetupDiGetDeviceInterfaceDetail(
18399a2dd95SBruce Richardson 		list, &ifdata, detail, detail_size, NULL, NULL)) {
18499a2dd95SBruce Richardson 		RTE_LOG_WIN32_ERR("SetupDiGetDeviceInterfaceDetail(read)");
18599a2dd95SBruce Richardson 		goto exit;
18699a2dd95SBruce Richardson 	}
18799a2dd95SBruce Richardson 
188*ae67895bSDavid Marchand 	EAL_LOG(DEBUG, "Found virt2phys device: %s", detail->DevicePath);
18999a2dd95SBruce Richardson 
19099a2dd95SBruce Richardson 	virt2phys_device = CreateFile(
19199a2dd95SBruce Richardson 		detail->DevicePath, 0, 0, NULL, OPEN_EXISTING, 0, NULL);
19299a2dd95SBruce Richardson 	if (virt2phys_device == INVALID_HANDLE_VALUE) {
19399a2dd95SBruce Richardson 		RTE_LOG_WIN32_ERR("CreateFile()");
19499a2dd95SBruce Richardson 		goto exit;
19599a2dd95SBruce Richardson 	}
19699a2dd95SBruce Richardson 
19799a2dd95SBruce Richardson 	/* Indicate success. */
19899a2dd95SBruce Richardson 	ret = 0;
19999a2dd95SBruce Richardson 
20099a2dd95SBruce Richardson exit:
20199a2dd95SBruce Richardson 	free(detail);
20299a2dd95SBruce Richardson 	if (list != INVALID_HANDLE_VALUE)
20399a2dd95SBruce Richardson 		SetupDiDestroyDeviceInfoList(list);
20499a2dd95SBruce Richardson 
20599a2dd95SBruce Richardson 	return ret;
20699a2dd95SBruce Richardson }
20799a2dd95SBruce Richardson 
20823ce9e0aSDmitry Kozlyuk void
eal_mem_virt2iova_cleanup(void)20923ce9e0aSDmitry Kozlyuk eal_mem_virt2iova_cleanup(void)
21023ce9e0aSDmitry Kozlyuk {
21123ce9e0aSDmitry Kozlyuk 	if (virt2phys_device != INVALID_HANDLE_VALUE)
21223ce9e0aSDmitry Kozlyuk 		CloseHandle(virt2phys_device);
21323ce9e0aSDmitry Kozlyuk }
21423ce9e0aSDmitry Kozlyuk 
21599a2dd95SBruce Richardson phys_addr_t
rte_mem_virt2phy(const void * virt)21699a2dd95SBruce Richardson rte_mem_virt2phy(const void *virt)
21799a2dd95SBruce Richardson {
21899a2dd95SBruce Richardson 	LARGE_INTEGER phys;
21999a2dd95SBruce Richardson 	DWORD bytes_returned;
22099a2dd95SBruce Richardson 
22199a2dd95SBruce Richardson 	if (virt2phys_device == INVALID_HANDLE_VALUE)
22299a2dd95SBruce Richardson 		return RTE_BAD_PHYS_ADDR;
22399a2dd95SBruce Richardson 
22499a2dd95SBruce Richardson 	if (!DeviceIoControl(
22599a2dd95SBruce Richardson 			virt2phys_device, IOCTL_VIRT2PHYS_TRANSLATE,
22699a2dd95SBruce Richardson 			&virt, sizeof(virt), &phys, sizeof(phys),
22799a2dd95SBruce Richardson 			&bytes_returned, NULL)) {
22899a2dd95SBruce Richardson 		RTE_LOG_WIN32_ERR("DeviceIoControl(IOCTL_VIRT2PHYS_TRANSLATE)");
22999a2dd95SBruce Richardson 		return RTE_BAD_PHYS_ADDR;
23099a2dd95SBruce Richardson 	}
23199a2dd95SBruce Richardson 
23299a2dd95SBruce Richardson 	return phys.QuadPart;
23399a2dd95SBruce Richardson }
23499a2dd95SBruce Richardson 
23599a2dd95SBruce Richardson rte_iova_t
rte_mem_virt2iova(const void * virt)23699a2dd95SBruce Richardson rte_mem_virt2iova(const void *virt)
23799a2dd95SBruce Richardson {
23899a2dd95SBruce Richardson 	phys_addr_t phys;
23999a2dd95SBruce Richardson 
2400c8fc83aSDmitry Kozlyuk 	if (rte_eal_iova_mode() == RTE_IOVA_VA)
2410c8fc83aSDmitry Kozlyuk 		return (rte_iova_t)virt;
24299a2dd95SBruce Richardson 
24399a2dd95SBruce Richardson 	phys = rte_mem_virt2phy(virt);
24499a2dd95SBruce Richardson 	if (phys == RTE_BAD_PHYS_ADDR)
24599a2dd95SBruce Richardson 		return RTE_BAD_IOVA;
24699a2dd95SBruce Richardson 	return (rte_iova_t)phys;
24799a2dd95SBruce Richardson }
24899a2dd95SBruce Richardson 
24999a2dd95SBruce Richardson /* Always using physical addresses under Windows if they can be obtained. */
25099a2dd95SBruce Richardson int
rte_eal_using_phys_addrs(void)25199a2dd95SBruce Richardson rte_eal_using_phys_addrs(void)
25299a2dd95SBruce Richardson {
25399a2dd95SBruce Richardson 	return virt2phys_device != INVALID_HANDLE_VALUE;
25499a2dd95SBruce Richardson }
25599a2dd95SBruce Richardson 
25699a2dd95SBruce Richardson /* Approximate error mapping from VirtualAlloc2() to POSIX mmap(3). */
25799a2dd95SBruce Richardson static void
set_errno_from_win32_alloc_error(DWORD code)25899a2dd95SBruce Richardson set_errno_from_win32_alloc_error(DWORD code)
25999a2dd95SBruce Richardson {
26099a2dd95SBruce Richardson 	switch (code) {
26199a2dd95SBruce Richardson 	case ERROR_SUCCESS:
26299a2dd95SBruce Richardson 		rte_errno = 0;
26399a2dd95SBruce Richardson 		break;
26499a2dd95SBruce Richardson 
26599a2dd95SBruce Richardson 	case ERROR_INVALID_ADDRESS:
26699a2dd95SBruce Richardson 		/* A valid requested address is not available. */
26799a2dd95SBruce Richardson 	case ERROR_COMMITMENT_LIMIT:
26899a2dd95SBruce Richardson 		/* May occur when committing regular memory. */
26999a2dd95SBruce Richardson 	case ERROR_NO_SYSTEM_RESOURCES:
27099a2dd95SBruce Richardson 		/* Occurs when the system runs out of hugepages. */
27199a2dd95SBruce Richardson 		rte_errno = ENOMEM;
27299a2dd95SBruce Richardson 		break;
27399a2dd95SBruce Richardson 
27499a2dd95SBruce Richardson 	case ERROR_INVALID_PARAMETER:
27599a2dd95SBruce Richardson 	default:
27699a2dd95SBruce Richardson 		rte_errno = EINVAL;
27799a2dd95SBruce Richardson 		break;
27899a2dd95SBruce Richardson 	}
27999a2dd95SBruce Richardson }
28099a2dd95SBruce Richardson 
28199a2dd95SBruce Richardson void *
eal_mem_reserve(void * requested_addr,size_t size,int flags)28299a2dd95SBruce Richardson eal_mem_reserve(void *requested_addr, size_t size, int flags)
28399a2dd95SBruce Richardson {
28499a2dd95SBruce Richardson 	HANDLE process;
28599a2dd95SBruce Richardson 	void *virt;
28699a2dd95SBruce Richardson 
28799a2dd95SBruce Richardson 	/* Windows requires hugepages to be committed. */
28899a2dd95SBruce Richardson 	if (flags & EAL_RESERVE_HUGEPAGES) {
28999a2dd95SBruce Richardson 		rte_errno = ENOTSUP;
29099a2dd95SBruce Richardson 		return NULL;
29199a2dd95SBruce Richardson 	}
29299a2dd95SBruce Richardson 
29399a2dd95SBruce Richardson 	process = GetCurrentProcess();
29499a2dd95SBruce Richardson 
29599a2dd95SBruce Richardson 	virt = VirtualAlloc2_ptr(process, requested_addr, size,
29699a2dd95SBruce Richardson 		MEM_RESERVE | MEM_RESERVE_PLACEHOLDER, PAGE_NOACCESS,
29799a2dd95SBruce Richardson 		NULL, 0);
29899a2dd95SBruce Richardson 	if (virt == NULL) {
29999a2dd95SBruce Richardson 		DWORD err = GetLastError();
30099a2dd95SBruce Richardson 		RTE_LOG_WIN32_ERR("VirtualAlloc2()");
30199a2dd95SBruce Richardson 		set_errno_from_win32_alloc_error(err);
30299a2dd95SBruce Richardson 		return NULL;
30399a2dd95SBruce Richardson 	}
30499a2dd95SBruce Richardson 
30599a2dd95SBruce Richardson 	if ((flags & EAL_RESERVE_FORCE_ADDRESS) && (virt != requested_addr)) {
30699a2dd95SBruce Richardson 		if (!VirtualFreeEx(process, virt, 0, MEM_RELEASE))
30799a2dd95SBruce Richardson 			RTE_LOG_WIN32_ERR("VirtualFreeEx()");
30899a2dd95SBruce Richardson 		rte_errno = ENOMEM;
30999a2dd95SBruce Richardson 		return NULL;
31099a2dd95SBruce Richardson 	}
31199a2dd95SBruce Richardson 
31299a2dd95SBruce Richardson 	return virt;
31399a2dd95SBruce Richardson }
31499a2dd95SBruce Richardson 
31599a2dd95SBruce Richardson void *
eal_mem_alloc_socket(size_t size,int socket_id)31699a2dd95SBruce Richardson eal_mem_alloc_socket(size_t size, int socket_id)
31799a2dd95SBruce Richardson {
31899a2dd95SBruce Richardson 	DWORD flags = MEM_RESERVE | MEM_COMMIT;
31999a2dd95SBruce Richardson 	void *addr;
32099a2dd95SBruce Richardson 
32199a2dd95SBruce Richardson 	flags = MEM_RESERVE | MEM_COMMIT | MEM_LARGE_PAGES;
32299a2dd95SBruce Richardson 	addr = VirtualAllocExNuma(GetCurrentProcess(), NULL, size, flags,
32399a2dd95SBruce Richardson 		PAGE_READWRITE, eal_socket_numa_node(socket_id));
32499a2dd95SBruce Richardson 	if (addr == NULL)
32599a2dd95SBruce Richardson 		rte_errno = ENOMEM;
32699a2dd95SBruce Richardson 	return addr;
32799a2dd95SBruce Richardson }
32899a2dd95SBruce Richardson 
32999a2dd95SBruce Richardson void *
eal_mem_commit(void * requested_addr,size_t size,int socket_id)33099a2dd95SBruce Richardson eal_mem_commit(void *requested_addr, size_t size, int socket_id)
33199a2dd95SBruce Richardson {
33299a2dd95SBruce Richardson 	HANDLE process;
33399a2dd95SBruce Richardson 	MEM_EXTENDED_PARAMETER param;
33499a2dd95SBruce Richardson 	DWORD param_count = 0;
33599a2dd95SBruce Richardson 	DWORD flags;
33699a2dd95SBruce Richardson 	void *addr;
33799a2dd95SBruce Richardson 
33899a2dd95SBruce Richardson 	process = GetCurrentProcess();
33999a2dd95SBruce Richardson 
34099a2dd95SBruce Richardson 	if (requested_addr != NULL) {
34199a2dd95SBruce Richardson 		MEMORY_BASIC_INFORMATION info;
34299a2dd95SBruce Richardson 
34399a2dd95SBruce Richardson 		if (VirtualQueryEx(process, requested_addr, &info,
34499a2dd95SBruce Richardson 				sizeof(info)) != sizeof(info)) {
34599a2dd95SBruce Richardson 			RTE_LOG_WIN32_ERR("VirtualQuery(%p)", requested_addr);
34699a2dd95SBruce Richardson 			return NULL;
34799a2dd95SBruce Richardson 		}
34899a2dd95SBruce Richardson 
34999a2dd95SBruce Richardson 		/* Split reserved region if only a part is committed. */
35099a2dd95SBruce Richardson 		flags = MEM_RELEASE | MEM_PRESERVE_PLACEHOLDER;
35199a2dd95SBruce Richardson 		if ((info.RegionSize > size) && !VirtualFreeEx(
35299a2dd95SBruce Richardson 				process, requested_addr, size, flags)) {
35399a2dd95SBruce Richardson 			RTE_LOG_WIN32_ERR(
35499a2dd95SBruce Richardson 				"VirtualFreeEx(%p, %zu, preserve placeholder)",
35599a2dd95SBruce Richardson 				requested_addr, size);
35699a2dd95SBruce Richardson 			return NULL;
35799a2dd95SBruce Richardson 		}
35899a2dd95SBruce Richardson 
35999a2dd95SBruce Richardson 		/* Temporarily release the region to be committed.
36099a2dd95SBruce Richardson 		 *
36199a2dd95SBruce Richardson 		 * There is an inherent race for this memory range
36299a2dd95SBruce Richardson 		 * if another thread allocates memory via OS API.
36399a2dd95SBruce Richardson 		 * However, VirtualAlloc2(MEM_REPLACE_PLACEHOLDER)
36499a2dd95SBruce Richardson 		 * doesn't work with MEM_LARGE_PAGES on Windows Server.
36599a2dd95SBruce Richardson 		 */
36699a2dd95SBruce Richardson 		if (!VirtualFreeEx(process, requested_addr, 0, MEM_RELEASE)) {
36799a2dd95SBruce Richardson 			RTE_LOG_WIN32_ERR("VirtualFreeEx(%p, 0, release)",
36899a2dd95SBruce Richardson 				requested_addr);
36999a2dd95SBruce Richardson 			return NULL;
37099a2dd95SBruce Richardson 		}
37199a2dd95SBruce Richardson 	}
37299a2dd95SBruce Richardson 
37399a2dd95SBruce Richardson 	if (socket_id != SOCKET_ID_ANY) {
37499a2dd95SBruce Richardson 		param_count = 1;
37599a2dd95SBruce Richardson 		memset(&param, 0, sizeof(param));
37699a2dd95SBruce Richardson 		param.Type = MemExtendedParameterNumaNode;
37799a2dd95SBruce Richardson 		param.ULong = eal_socket_numa_node(socket_id);
37899a2dd95SBruce Richardson 	}
37999a2dd95SBruce Richardson 
38099a2dd95SBruce Richardson 	flags = MEM_RESERVE | MEM_COMMIT | MEM_LARGE_PAGES;
38199a2dd95SBruce Richardson 	addr = VirtualAlloc2_ptr(process, requested_addr, size,
38299a2dd95SBruce Richardson 		flags, PAGE_READWRITE, &param, param_count);
38399a2dd95SBruce Richardson 	if (addr == NULL) {
38499a2dd95SBruce Richardson 		/* Logging may overwrite GetLastError() result. */
38599a2dd95SBruce Richardson 		DWORD err = GetLastError();
38699a2dd95SBruce Richardson 		RTE_LOG_WIN32_ERR("VirtualAlloc2(%p, %zu, commit large pages)",
38799a2dd95SBruce Richardson 			requested_addr, size);
38899a2dd95SBruce Richardson 		set_errno_from_win32_alloc_error(err);
38999a2dd95SBruce Richardson 		return NULL;
39099a2dd95SBruce Richardson 	}
39199a2dd95SBruce Richardson 
39299a2dd95SBruce Richardson 	if ((requested_addr != NULL) && (addr != requested_addr)) {
39399a2dd95SBruce Richardson 		/* We lost the race for the requested_addr. */
39499a2dd95SBruce Richardson 		if (!VirtualFreeEx(process, addr, 0, MEM_RELEASE))
39599a2dd95SBruce Richardson 			RTE_LOG_WIN32_ERR("VirtualFreeEx(%p, release)", addr);
39699a2dd95SBruce Richardson 
39799a2dd95SBruce Richardson 		rte_errno = EADDRNOTAVAIL;
39899a2dd95SBruce Richardson 		return NULL;
39999a2dd95SBruce Richardson 	}
40099a2dd95SBruce Richardson 
40199a2dd95SBruce Richardson 	return addr;
40299a2dd95SBruce Richardson }
40399a2dd95SBruce Richardson 
40499a2dd95SBruce Richardson int
eal_mem_decommit(void * addr,size_t size)40599a2dd95SBruce Richardson eal_mem_decommit(void *addr, size_t size)
40699a2dd95SBruce Richardson {
40799a2dd95SBruce Richardson 	HANDLE process;
40899a2dd95SBruce Richardson 	void *stub;
40999a2dd95SBruce Richardson 	DWORD flags;
41099a2dd95SBruce Richardson 
41199a2dd95SBruce Richardson 	process = GetCurrentProcess();
41299a2dd95SBruce Richardson 
41399a2dd95SBruce Richardson 	/* Hugepages cannot be decommited on Windows,
41499a2dd95SBruce Richardson 	 * so free them and replace the block with a placeholder.
41599a2dd95SBruce Richardson 	 * There is a race for VA in this block until VirtualAlloc2 call.
41699a2dd95SBruce Richardson 	 */
41799a2dd95SBruce Richardson 	if (!VirtualFreeEx(process, addr, 0, MEM_RELEASE)) {
41899a2dd95SBruce Richardson 		RTE_LOG_WIN32_ERR("VirtualFreeEx(%p, 0, release)", addr);
41999a2dd95SBruce Richardson 		return -1;
42099a2dd95SBruce Richardson 	}
42199a2dd95SBruce Richardson 
42299a2dd95SBruce Richardson 	flags = MEM_RESERVE | MEM_RESERVE_PLACEHOLDER;
42399a2dd95SBruce Richardson 	stub = VirtualAlloc2_ptr(
42499a2dd95SBruce Richardson 		process, addr, size, flags, PAGE_NOACCESS, NULL, 0);
42599a2dd95SBruce Richardson 	if (stub == NULL) {
42699a2dd95SBruce Richardson 		/* We lost the race for the VA. */
42799a2dd95SBruce Richardson 		if (!VirtualFreeEx(process, stub, 0, MEM_RELEASE))
42899a2dd95SBruce Richardson 			RTE_LOG_WIN32_ERR("VirtualFreeEx(%p, release)", stub);
42999a2dd95SBruce Richardson 		rte_errno = EADDRNOTAVAIL;
43099a2dd95SBruce Richardson 		return -1;
43199a2dd95SBruce Richardson 	}
43299a2dd95SBruce Richardson 
43399a2dd95SBruce Richardson 	/* No need to join reserved regions adjacent to the freed one:
43499a2dd95SBruce Richardson 	 * eal_mem_commit() will just pick up the page-size placeholder
43599a2dd95SBruce Richardson 	 * created here.
43699a2dd95SBruce Richardson 	 */
43799a2dd95SBruce Richardson 	return 0;
43899a2dd95SBruce Richardson }
43999a2dd95SBruce Richardson 
44099a2dd95SBruce Richardson /**
44199a2dd95SBruce Richardson  * Free a reserved memory region in full or in part.
44299a2dd95SBruce Richardson  *
44399a2dd95SBruce Richardson  * @param addr
44499a2dd95SBruce Richardson  *  Starting address of the area to free.
44599a2dd95SBruce Richardson  * @param size
44699a2dd95SBruce Richardson  *  Number of bytes to free. Must be a multiple of page size.
44799a2dd95SBruce Richardson  * @param reserved
44899a2dd95SBruce Richardson  *  Fail if the region is not in reserved state.
44999a2dd95SBruce Richardson  * @return
45099a2dd95SBruce Richardson  *  * 0 on successful deallocation;
45199a2dd95SBruce Richardson  *  * 1 if region must be in reserved state but it is not;
45299a2dd95SBruce Richardson  *  * (-1) on system API failures.
45399a2dd95SBruce Richardson  */
45499a2dd95SBruce Richardson static int
mem_free(void * addr,size_t size,bool reserved)45599a2dd95SBruce Richardson mem_free(void *addr, size_t size, bool reserved)
45699a2dd95SBruce Richardson {
45799a2dd95SBruce Richardson 	MEMORY_BASIC_INFORMATION info;
45899a2dd95SBruce Richardson 	HANDLE process;
45999a2dd95SBruce Richardson 
46099a2dd95SBruce Richardson 	process = GetCurrentProcess();
46199a2dd95SBruce Richardson 
46299a2dd95SBruce Richardson 	if (VirtualQueryEx(
46399a2dd95SBruce Richardson 			process, addr, &info, sizeof(info)) != sizeof(info)) {
46499a2dd95SBruce Richardson 		RTE_LOG_WIN32_ERR("VirtualQueryEx(%p)", addr);
46599a2dd95SBruce Richardson 		return -1;
46699a2dd95SBruce Richardson 	}
46799a2dd95SBruce Richardson 
46899a2dd95SBruce Richardson 	if (reserved && (info.State != MEM_RESERVE))
46999a2dd95SBruce Richardson 		return 1;
47099a2dd95SBruce Richardson 
47199a2dd95SBruce Richardson 	/* Free complete region. */
47299a2dd95SBruce Richardson 	if ((addr == info.AllocationBase) && (size == info.RegionSize)) {
47399a2dd95SBruce Richardson 		if (!VirtualFreeEx(process, addr, 0, MEM_RELEASE)) {
47499a2dd95SBruce Richardson 			RTE_LOG_WIN32_ERR("VirtualFreeEx(%p, 0, release)",
47599a2dd95SBruce Richardson 				addr);
47699a2dd95SBruce Richardson 		}
47799a2dd95SBruce Richardson 		return 0;
47899a2dd95SBruce Richardson 	}
47999a2dd95SBruce Richardson 
48099a2dd95SBruce Richardson 	/* Split the part to be freed and the remaining reservation. */
48199a2dd95SBruce Richardson 	if (!VirtualFreeEx(process, addr, size,
48299a2dd95SBruce Richardson 			MEM_RELEASE | MEM_PRESERVE_PLACEHOLDER)) {
48399a2dd95SBruce Richardson 		RTE_LOG_WIN32_ERR(
48499a2dd95SBruce Richardson 			"VirtualFreeEx(%p, %zu, preserve placeholder)",
48599a2dd95SBruce Richardson 			addr, size);
48699a2dd95SBruce Richardson 		return -1;
48799a2dd95SBruce Richardson 	}
48899a2dd95SBruce Richardson 
48999a2dd95SBruce Richardson 	/* Actually free reservation part. */
49099a2dd95SBruce Richardson 	if (!VirtualFreeEx(process, addr, 0, MEM_RELEASE)) {
49199a2dd95SBruce Richardson 		RTE_LOG_WIN32_ERR("VirtualFreeEx(%p, 0, release)", addr);
49299a2dd95SBruce Richardson 		return -1;
49399a2dd95SBruce Richardson 	}
49499a2dd95SBruce Richardson 
49599a2dd95SBruce Richardson 	return 0;
49699a2dd95SBruce Richardson }
49799a2dd95SBruce Richardson 
49899a2dd95SBruce Richardson void
eal_mem_free(void * virt,size_t size)49999a2dd95SBruce Richardson eal_mem_free(void *virt, size_t size)
50099a2dd95SBruce Richardson {
50199a2dd95SBruce Richardson 	mem_free(virt, size, false);
50299a2dd95SBruce Richardson }
50399a2dd95SBruce Richardson 
50499a2dd95SBruce Richardson int
eal_mem_set_dump(void * virt,size_t size,bool dump)50599a2dd95SBruce Richardson eal_mem_set_dump(void *virt, size_t size, bool dump)
50699a2dd95SBruce Richardson {
50799a2dd95SBruce Richardson 	RTE_SET_USED(virt);
50899a2dd95SBruce Richardson 	RTE_SET_USED(size);
50999a2dd95SBruce Richardson 	RTE_SET_USED(dump);
51099a2dd95SBruce Richardson 
51199a2dd95SBruce Richardson 	/* Windows does not dump reserved memory by default.
51299a2dd95SBruce Richardson 	 *
51399a2dd95SBruce Richardson 	 * There is <werapi.h> to include or exclude regions from the dump,
51499a2dd95SBruce Richardson 	 * but this is not currently required by EAL.
51599a2dd95SBruce Richardson 	 */
51699a2dd95SBruce Richardson 
51799a2dd95SBruce Richardson 	rte_errno = ENOTSUP;
51899a2dd95SBruce Richardson 	return -1;
51999a2dd95SBruce Richardson }
52099a2dd95SBruce Richardson 
52199a2dd95SBruce Richardson void *
rte_mem_map(void * requested_addr,size_t size,int prot,int flags,int fd,uint64_t offset)52299a2dd95SBruce Richardson rte_mem_map(void *requested_addr, size_t size, int prot, int flags,
5236beb2d29SLance Richardson 	int fd, uint64_t offset)
52499a2dd95SBruce Richardson {
52599a2dd95SBruce Richardson 	HANDLE file_handle = INVALID_HANDLE_VALUE;
52699a2dd95SBruce Richardson 	HANDLE mapping_handle = INVALID_HANDLE_VALUE;
52799a2dd95SBruce Richardson 	DWORD sys_prot = 0;
52899a2dd95SBruce Richardson 	DWORD sys_access = 0;
52999a2dd95SBruce Richardson 	DWORD size_high = (DWORD)(size >> 32);
53099a2dd95SBruce Richardson 	DWORD size_low = (DWORD)size;
53199a2dd95SBruce Richardson 	DWORD offset_high = (DWORD)(offset >> 32);
53299a2dd95SBruce Richardson 	DWORD offset_low = (DWORD)offset;
53399a2dd95SBruce Richardson 	LPVOID virt = NULL;
53499a2dd95SBruce Richardson 
53599a2dd95SBruce Richardson 	if (prot & RTE_PROT_EXECUTE) {
53699a2dd95SBruce Richardson 		if (prot & RTE_PROT_READ) {
53799a2dd95SBruce Richardson 			sys_prot = PAGE_EXECUTE_READ;
53899a2dd95SBruce Richardson 			sys_access = FILE_MAP_READ | FILE_MAP_EXECUTE;
53999a2dd95SBruce Richardson 		}
54099a2dd95SBruce Richardson 		if (prot & RTE_PROT_WRITE) {
54199a2dd95SBruce Richardson 			sys_prot = PAGE_EXECUTE_READWRITE;
54299a2dd95SBruce Richardson 			sys_access = FILE_MAP_WRITE | FILE_MAP_EXECUTE;
54399a2dd95SBruce Richardson 		}
54499a2dd95SBruce Richardson 	} else {
54599a2dd95SBruce Richardson 		if (prot & RTE_PROT_READ) {
54699a2dd95SBruce Richardson 			sys_prot = PAGE_READONLY;
54799a2dd95SBruce Richardson 			sys_access = FILE_MAP_READ;
54899a2dd95SBruce Richardson 		}
54999a2dd95SBruce Richardson 		if (prot & RTE_PROT_WRITE) {
55099a2dd95SBruce Richardson 			sys_prot = PAGE_READWRITE;
55199a2dd95SBruce Richardson 			sys_access = FILE_MAP_WRITE;
55299a2dd95SBruce Richardson 		}
55399a2dd95SBruce Richardson 	}
55499a2dd95SBruce Richardson 
55599a2dd95SBruce Richardson 	if (flags & RTE_MAP_PRIVATE)
55699a2dd95SBruce Richardson 		sys_access |= FILE_MAP_COPY;
55799a2dd95SBruce Richardson 
55899a2dd95SBruce Richardson 	if ((flags & RTE_MAP_ANONYMOUS) == 0)
55999a2dd95SBruce Richardson 		file_handle = (HANDLE)_get_osfhandle(fd);
56099a2dd95SBruce Richardson 
56199a2dd95SBruce Richardson 	mapping_handle = CreateFileMapping(
56299a2dd95SBruce Richardson 		file_handle, NULL, sys_prot, size_high, size_low, NULL);
56399a2dd95SBruce Richardson 	if (mapping_handle == INVALID_HANDLE_VALUE) {
56499a2dd95SBruce Richardson 		RTE_LOG_WIN32_ERR("CreateFileMapping()");
56599a2dd95SBruce Richardson 		return NULL;
56699a2dd95SBruce Richardson 	}
56799a2dd95SBruce Richardson 
56899a2dd95SBruce Richardson 	/* There is a race for the requested_addr between mem_free()
56999a2dd95SBruce Richardson 	 * and MapViewOfFileEx(). MapViewOfFile3() that can replace a reserved
57099a2dd95SBruce Richardson 	 * region with a mapping in a single operation, but it does not support
57199a2dd95SBruce Richardson 	 * private mappings.
57299a2dd95SBruce Richardson 	 */
57399a2dd95SBruce Richardson 	if (requested_addr != NULL) {
57499a2dd95SBruce Richardson 		int ret = mem_free(requested_addr, size, true);
57599a2dd95SBruce Richardson 		if (ret) {
57699a2dd95SBruce Richardson 			if (ret > 0) {
577*ae67895bSDavid Marchand 				EAL_LOG(ERR, "Cannot map memory "
578*ae67895bSDavid Marchand 					"to a region not reserved");
57999a2dd95SBruce Richardson 				rte_errno = EADDRNOTAVAIL;
58099a2dd95SBruce Richardson 			}
58199a2dd95SBruce Richardson 			return NULL;
58299a2dd95SBruce Richardson 		}
58399a2dd95SBruce Richardson 	}
58499a2dd95SBruce Richardson 
58599a2dd95SBruce Richardson 	virt = MapViewOfFileEx(mapping_handle, sys_access,
58699a2dd95SBruce Richardson 		offset_high, offset_low, size, requested_addr);
58799a2dd95SBruce Richardson 	if (!virt) {
58899a2dd95SBruce Richardson 		RTE_LOG_WIN32_ERR("MapViewOfFileEx()");
58999a2dd95SBruce Richardson 		return NULL;
59099a2dd95SBruce Richardson 	}
59199a2dd95SBruce Richardson 
59299a2dd95SBruce Richardson 	if ((flags & RTE_MAP_FORCE_ADDRESS) && (virt != requested_addr)) {
59399a2dd95SBruce Richardson 		if (!UnmapViewOfFile(virt))
59499a2dd95SBruce Richardson 			RTE_LOG_WIN32_ERR("UnmapViewOfFile()");
59599a2dd95SBruce Richardson 		virt = NULL;
59699a2dd95SBruce Richardson 	}
59799a2dd95SBruce Richardson 
59899a2dd95SBruce Richardson 	if (!CloseHandle(mapping_handle))
59999a2dd95SBruce Richardson 		RTE_LOG_WIN32_ERR("CloseHandle()");
60099a2dd95SBruce Richardson 
60199a2dd95SBruce Richardson 	return virt;
60299a2dd95SBruce Richardson }
60399a2dd95SBruce Richardson 
60499a2dd95SBruce Richardson int
rte_mem_unmap(void * virt,size_t size)60599a2dd95SBruce Richardson rte_mem_unmap(void *virt, size_t size)
60699a2dd95SBruce Richardson {
60799a2dd95SBruce Richardson 	RTE_SET_USED(size);
60899a2dd95SBruce Richardson 
60999a2dd95SBruce Richardson 	if (!UnmapViewOfFile(virt)) {
61099a2dd95SBruce Richardson 		RTE_LOG_WIN32_ERR("UnmapViewOfFile()");
61199a2dd95SBruce Richardson 		rte_errno = EINVAL;
61299a2dd95SBruce Richardson 		return -1;
61399a2dd95SBruce Richardson 	}
61499a2dd95SBruce Richardson 	return 0;
61599a2dd95SBruce Richardson }
61699a2dd95SBruce Richardson 
61799a2dd95SBruce Richardson uint64_t
eal_get_baseaddr(void)61899a2dd95SBruce Richardson eal_get_baseaddr(void)
61999a2dd95SBruce Richardson {
62099a2dd95SBruce Richardson 	/* Windows strategy for memory allocation is undocumented.
62199a2dd95SBruce Richardson 	 * Returning 0 here effectively disables address guessing
62299a2dd95SBruce Richardson 	 * unless user provides an address hint.
62399a2dd95SBruce Richardson 	 */
62499a2dd95SBruce Richardson 	return 0;
62599a2dd95SBruce Richardson }
62699a2dd95SBruce Richardson 
62799a2dd95SBruce Richardson size_t
rte_mem_page_size(void)62899a2dd95SBruce Richardson rte_mem_page_size(void)
62999a2dd95SBruce Richardson {
63099a2dd95SBruce Richardson 	static SYSTEM_INFO info;
63199a2dd95SBruce Richardson 
63299a2dd95SBruce Richardson 	if (info.dwPageSize == 0)
63399a2dd95SBruce Richardson 		GetSystemInfo(&info);
63499a2dd95SBruce Richardson 
63599a2dd95SBruce Richardson 	return info.dwPageSize;
63699a2dd95SBruce Richardson }
63799a2dd95SBruce Richardson 
63899a2dd95SBruce Richardson int
rte_mem_lock(const void * virt,size_t size)63999a2dd95SBruce Richardson rte_mem_lock(const void *virt, size_t size)
64099a2dd95SBruce Richardson {
64199a2dd95SBruce Richardson 	/* VirtualLock() takes `void*`, work around compiler warning. */
64299a2dd95SBruce Richardson 	void *addr = (void *)((uintptr_t)virt);
64399a2dd95SBruce Richardson 
64499a2dd95SBruce Richardson 	if (!VirtualLock(addr, size)) {
64599a2dd95SBruce Richardson 		RTE_LOG_WIN32_ERR("VirtualLock(%p %#zx)", virt, size);
64699a2dd95SBruce Richardson 		return -1;
64799a2dd95SBruce Richardson 	}
64899a2dd95SBruce Richardson 
64999a2dd95SBruce Richardson 	return 0;
65099a2dd95SBruce Richardson }
65199a2dd95SBruce Richardson 
65299a2dd95SBruce Richardson int
rte_eal_memseg_init(void)65399a2dd95SBruce Richardson rte_eal_memseg_init(void)
65499a2dd95SBruce Richardson {
65599a2dd95SBruce Richardson 	if (rte_eal_process_type() != RTE_PROC_PRIMARY) {
65699a2dd95SBruce Richardson 		EAL_LOG_NOT_IMPLEMENTED();
65799a2dd95SBruce Richardson 		return -1;
65899a2dd95SBruce Richardson 	}
65999a2dd95SBruce Richardson 
66099a2dd95SBruce Richardson 	return eal_dynmem_memseg_lists_init();
66199a2dd95SBruce Richardson }
66299a2dd95SBruce Richardson 
66399a2dd95SBruce Richardson static int
eal_nohuge_init(void)66499a2dd95SBruce Richardson eal_nohuge_init(void)
66599a2dd95SBruce Richardson {
66699a2dd95SBruce Richardson 	struct rte_mem_config *mcfg;
66799a2dd95SBruce Richardson 	struct rte_memseg_list *msl;
66899a2dd95SBruce Richardson 	int n_segs;
66999a2dd95SBruce Richardson 	uint64_t mem_sz, page_sz;
67099a2dd95SBruce Richardson 	void *addr;
67199a2dd95SBruce Richardson 
67299a2dd95SBruce Richardson 	mcfg = rte_eal_get_configuration()->mem_config;
67399a2dd95SBruce Richardson 	struct internal_config *internal_conf =
67499a2dd95SBruce Richardson 		eal_get_internal_configuration();
67599a2dd95SBruce Richardson 
67699a2dd95SBruce Richardson 	/* nohuge mode is legacy mode */
67799a2dd95SBruce Richardson 	internal_conf->legacy_mem = 1;
67899a2dd95SBruce Richardson 
67999a2dd95SBruce Richardson 	msl = &mcfg->memsegs[0];
68099a2dd95SBruce Richardson 
68199a2dd95SBruce Richardson 	mem_sz = internal_conf->memory;
68299a2dd95SBruce Richardson 	page_sz = RTE_PGSIZE_4K;
68399a2dd95SBruce Richardson 	n_segs = mem_sz / page_sz;
68499a2dd95SBruce Richardson 
68599a2dd95SBruce Richardson 	if (eal_memseg_list_init_named(
68699a2dd95SBruce Richardson 			msl, "nohugemem", page_sz, n_segs, 0, true)) {
68799a2dd95SBruce Richardson 		return -1;
68899a2dd95SBruce Richardson 	}
68999a2dd95SBruce Richardson 
69099a2dd95SBruce Richardson 	addr = VirtualAlloc(
69199a2dd95SBruce Richardson 		NULL, mem_sz, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
69299a2dd95SBruce Richardson 	if (addr == NULL) {
69399a2dd95SBruce Richardson 		RTE_LOG_WIN32_ERR("VirtualAlloc(size=%#zx)", mem_sz);
694*ae67895bSDavid Marchand 		EAL_LOG(ERR, "Cannot allocate memory");
69599a2dd95SBruce Richardson 		return -1;
69699a2dd95SBruce Richardson 	}
69799a2dd95SBruce Richardson 
69899a2dd95SBruce Richardson 	msl->base_va = addr;
69999a2dd95SBruce Richardson 	msl->len = mem_sz;
70099a2dd95SBruce Richardson 
70199a2dd95SBruce Richardson 	eal_memseg_list_populate(msl, addr, n_segs);
70299a2dd95SBruce Richardson 
70399a2dd95SBruce Richardson 	if (mcfg->dma_maskbits &&
70499a2dd95SBruce Richardson 		rte_mem_check_dma_mask_thread_unsafe(mcfg->dma_maskbits)) {
705*ae67895bSDavid Marchand 		EAL_LOG(ERR,
70699a2dd95SBruce Richardson 			"%s(): couldn't allocate memory due to IOVA "
707*ae67895bSDavid Marchand 			"exceeding limits of current DMA mask.", __func__);
70899a2dd95SBruce Richardson 		return -1;
70999a2dd95SBruce Richardson 	}
71099a2dd95SBruce Richardson 
71199a2dd95SBruce Richardson 	return 0;
71299a2dd95SBruce Richardson }
71399a2dd95SBruce Richardson 
71499a2dd95SBruce Richardson int
rte_eal_hugepage_init(void)71599a2dd95SBruce Richardson rte_eal_hugepage_init(void)
71699a2dd95SBruce Richardson {
71799a2dd95SBruce Richardson 	const struct internal_config *internal_conf =
71899a2dd95SBruce Richardson 		eal_get_internal_configuration();
71999a2dd95SBruce Richardson 
72099a2dd95SBruce Richardson 	return internal_conf->no_hugetlbfs ?
72199a2dd95SBruce Richardson 		eal_nohuge_init() : eal_dynmem_hugepage_init();
72299a2dd95SBruce Richardson }
72399a2dd95SBruce Richardson 
72499a2dd95SBruce Richardson int
rte_eal_hugepage_attach(void)72599a2dd95SBruce Richardson rte_eal_hugepage_attach(void)
72699a2dd95SBruce Richardson {
72799a2dd95SBruce Richardson 	EAL_LOG_NOT_IMPLEMENTED();
72899a2dd95SBruce Richardson 	return -1;
72999a2dd95SBruce Richardson }
730