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(¶m, 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, ¶m, 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