From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from dpdk.org (dpdk.org [92.243.14.124]) by inbox.dpdk.org (Postfix) with ESMTP id 9D052A034F; Wed, 13 May 2020 10:24:17 +0200 (CEST) Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id 7584B1C2EE; Wed, 13 May 2020 10:24:17 +0200 (CEST) Received: from EUR03-VE1-obe.outbound.protection.outlook.com (mail-eopbgr50042.outbound.protection.outlook.com [40.107.5.42]) by dpdk.org (Postfix) with ESMTP id 720581C24A for ; Wed, 13 May 2020 10:24:15 +0200 (CEST) ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=L+hq/1RDZk/pMyr0d0qcHjmJGchrozyTaFG2McCb4l/wgpt35VxgvSz8aRACVnQ8/HE//fNMejGJ8jvf2Hw+A8bDgXFq/atOsRtTPeU9i9lkxkMA+mdWJA+E03vtTDNgDk+KCspISDmV/BHeMJYoxo2FBGF1wJ6etAkBvN3q5pX70CPNyBKATcDmL7mkLRHXlbE8RSPnvgSlOB/G73J2Ca2QesObU3jt+oA90o5LrfG4BfEqGKouzram1ZvysPWezZwaOk53dWpmKszZr+sK/xWw9myXWVuS+UQzYTd+onvOO2tJQvIj+QB0MPUUE1xSTb8wMhXcXxW203yFGXBamg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=NPqDQ78N20M/O1wYaqycSE+UV3fWyF+n5McgOJmPfaY=; b=NyfQGCUhg1jaCGXH7sJ5KdKNejvoP3L4/qDLCvASiq8Lv5ev7Xl2Nkk6pfEByOQ6v7exJbpiOuh5tTTWvII5AYdDqIuknRbsCNcsOf/76d9Y72aEkkSSdBX1+THlhsVphMYaC7k5s5IHUgOtuiRb2djav9NEmJV+w0hh2oU/4x4mvwfgzBIfUuzzz6O4VVMdxdisoP8v/7OH0eGUgqb6tMlVsegNpPKd4I7e+pSroPNX1Tskd4L8qPskKdkyKwed4mrzslcEJwRq1mHNBHMp1lNRMCg+5qIhSX6awmvG4oFzZ3Msm2u+sm4gcfcBE016KW8/+iAwmg+OTb95xUJWvQ== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=mellanox.com; dmarc=pass action=none header.from=mellanox.com; dkim=pass header.d=mellanox.com; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=Mellanox.com; s=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=NPqDQ78N20M/O1wYaqycSE+UV3fWyF+n5McgOJmPfaY=; b=LGi+49zZTDCShSoSwokk6vNAgWCOmdD7qKHTR6XZ/+Kn8NlSAR6RWW/qIaggpv85U426i3nP6qVcGiuy7GwSYGdeyUOOr52LqaynYN63lF1tOD4ppohllCNTWEZJ7bT93QJJOnK/GCsx2SE/U4aW9MIstJEunEn//bEKqrYpWyE= Received: from AM0PR0502MB4034.eurprd05.prod.outlook.com (2603:10a6:208:12::14) by AM0PR0502MB3860.eurprd05.prod.outlook.com (2603:10a6:208:26::23) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.2979.27; Wed, 13 May 2020 08:24:13 +0000 Received: from AM0PR0502MB4034.eurprd05.prod.outlook.com ([fe80::a0ec:2aee:7f28:8d22]) by AM0PR0502MB4034.eurprd05.prod.outlook.com ([fe80::a0ec:2aee:7f28:8d22%7]) with mapi id 15.20.2979.033; Wed, 13 May 2020 08:24:13 +0000 From: Fady Bader To: Dmitry Kozlyuk , "dev@dpdk.org" CC: "Dmitry Malloy (MESHCHANINOV)" , Narcisa Ana Maria Vasile , Tal Shnaiderman , Thomas Monjalon , Harini Ramakrishnan , Omar Cardona , Pallavi Kadam , Ranjit Menon , John McNamara , Marko Kovacevic , Anatoly Burakov Thread-Topic: [PATCH v4 8/8] eal/windows: implement basic memory management Thread-Index: AQHWHbfQx0ufnJgIC0i7LHh3WkZ/BKilvyyQ Date: Wed, 13 May 2020 08:24:12 +0000 Message-ID: References: <20200410164342.1194634-1-dmitry.kozliuk@gmail.com> <20200428235015.2820677-1-dmitry.kozliuk@gmail.com> <20200428235015.2820677-9-dmitry.kozliuk@gmail.com> In-Reply-To: <20200428235015.2820677-9-dmitry.kozliuk@gmail.com> Accept-Language: en-US Content-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: authentication-results: gmail.com; dkim=none (message not signed) header.d=none;gmail.com; dmarc=none action=none header.from=mellanox.com; x-originating-ip: [79.176.112.213] x-ms-publictraffictype: Email x-ms-office365-filtering-ht: Tenant x-ms-office365-filtering-correlation-id: 25bed2ea-ec5a-46cb-475a-08d7f71704a9 x-ms-traffictypediagnostic: AM0PR0502MB3860:|AM0PR0502MB3860: x-ld-processed: a652971c-7d2e-4d9b-a6a4-d149256f461b,ExtAddr x-ms-exchange-transport-forked: True x-microsoft-antispam-prvs: x-ms-oob-tlc-oobclassifiers: OLM:534; x-forefront-prvs: 0402872DA1 x-ms-exchange-senderadcheck: 1 x-microsoft-antispam: BCL:0; x-microsoft-antispam-message-info: 2jzmI3BA4a/ciqJ06WdKv0WmDV167HCDrYT8UckZIcUz+m6KBqfepthMBfMiruPM3VkEzG8IJ1CNNld9N5SRQZxBNfncrYQ8fZJ76fgJayetxRzTn1yyop6y/128a0JgBIHldJFdOjw5G5haErY/ZGNYA9PjaxzQ/2om9+dLvXIB9yMk43NgRbET9KFP7Sn+BP6MT4A+NSwU7ASVerBssNbdg09AcO+45V52YNcpz35KziwLTvVHkw6JOS2DVNzf7fVS9Rm/7kFmD+985FPt4A9SwpQzrmyDdpohLkzaOwWTRVd0zyZagb8U4NzrLgmAgRNr/L9xpJNclaxsSWm9HeTHlHVkdZxrJETHTnLng2j0PPS3rs+vDbQzqZhjU+JQKza55ZxPDtZ0ng4kVMeuBBv2I/mRjMHlV9z2j5JhG7bQaR/tnZNM5CGpTE/Www8e4jupvpWnr82iOe9KILxUuvlwUajfpjuasun3o7SLPebX5AU0CNzbF2DgBczbupS174rRp5ETHQRnOUAmvDE2evhhfp1g8oCjEOMLu45wyPv97rEHSBv+LbjVH76ho0VNISFfqz4L6oKUXZ60JHNbSvNAWEN9syqT3p+dktd09Js= x-forefront-antispam-report: CIP:255.255.255.255; CTRY:; LANG:en; SCL:1; SRV:; IPV:NLI; SFV:NSPM; H:AM0PR0502MB4034.eurprd05.prod.outlook.com; PTR:; CAT:NONE; SFTY:; SFS:(4636009)(346002)(376002)(396003)(39860400002)(136003)(366004)(33430700001)(53546011)(30864003)(316002)(966005)(55016002)(9686003)(26005)(478600001)(33656002)(4326008)(83080400001)(186003)(52536014)(110136005)(66446008)(7696005)(71200400001)(2906002)(33440700001)(66556008)(66946007)(76116006)(54906003)(45080400002)(64756008)(8936002)(5660300002)(66476007)(86362001)(8676002)(6506007)(7416002)(559001)(579004); DIR:OUT; SFP:1101; x-ms-exchange-antispam-messagedata: SN8YeiQnICE4sTA0kxdag1zPcxwlROtprfTmufW6KGo7Z7TDTLZtXSTUBPbagZlD2w/pcA91wGho2i7prIfD4pOQxlb0LwnY/z+hfvUlfdXZREJPRnM98jmBP+Wv7C5RDRAxIlAA2kcJPflV4GNlNhTqIksO8r6ZkOFc0MbeFFO8f+JmmrFkxPtglv0ylhSqBvyY+YxUQi3Ta5eDzIBymTKF+Rk6oRU1/HTUcNBhpj2qqkXKGV6kKr6j1DOrZuadDnZcXe3OxLZAqK91s0aVmw39sAuhDBm+pUpY0w4Fg7XsVgp/FsiH6WSEp8/XZ9cuN7CHJEUj4T273g/xb2+v29YPWOoI45uSDoZNMtVwHsDSOwIc3pTiLDrS1eaqlpdNnVyY7cK03Y+Pq8eb866LeQZC0wNwcPtpUomMQrqoConmISL+ltTL8pnrelVzJNySm1naQmIeUZgKqqbTsEHhk28wXwscQAUQ8Q1u2//OV2QLglt+HF3VSd33oIk5VfgI Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 X-OriginatorOrg: Mellanox.com X-MS-Exchange-CrossTenant-Network-Message-Id: 25bed2ea-ec5a-46cb-475a-08d7f71704a9 X-MS-Exchange-CrossTenant-originalarrivaltime: 13 May 2020 08:24:12.8736 (UTC) X-MS-Exchange-CrossTenant-fromentityheader: Hosted X-MS-Exchange-CrossTenant-id: a652971c-7d2e-4d9b-a6a4-d149256f461b X-MS-Exchange-CrossTenant-mailboxtype: HOSTED X-MS-Exchange-CrossTenant-userprincipalname: hHxizPjOy1tGnVcX2nIFH9Z14WXJ2t5BJbuKTk1BpR4HLe2IlizL8FBopuwR43DPJXDaBYR/to+irddp3O5/Mw== X-MS-Exchange-Transport-CrossTenantHeadersStamped: AM0PR0502MB3860 Subject: Re: [dpdk-dev] [PATCH v4 8/8] eal/windows: implement basic memory management X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Sender: "dev" Hi Dmitry, I'm using your latest memory management patchset and getting an error in the function VirualAlloc2 in eal_mem_commit, error code: 0x57 (ERROR_INVALI= D_PARAMETER). I'm using Windows server 2019 build 17763, and followed the steps to Grant = *Lock pages in memory* Privilege. The parameters that are sent to the function are: GetCurrentProcess() is -1. requested_addr is 0x0000025b`93800000. Size is 0x200000 (sysInfo.dwAllocationGranularity is 0x10000).=20 Flags is 0x20007000. Also, Socket_id is 0. The call stack is: 00 dpdk_mempool_test!eal_mem_commit+0x253=20 01 dpdk_mempool_test!alloc_seg+0x1b0 02 dpdk_mempool_test!alloc_seg_walk+0x2a1=20 03 dpdk_mempool_test!rte_memseg_list_walk_thread_unsafe+0x81=20 04 dpdk_mempool_test!eal_memalloc_alloc_seg_bulk+0x1a5=20 05 dpdk_mempool_test!alloc_pages_on_heap+0x13a=20 06 dpdk_mempool_test!try_expand_heap_primary+0x1dc=20 07 dpdk_mempool_test!try_expand_heap+0xf5=20 08 dpdk_mempool_test!alloc_more_mem_on_socket+0x693=20 09 dpdk_mempool_test!malloc_heap_alloc_on_heap_id+0x2a7=20 0a dpdk_mempool_test!malloc_heap_alloc+0x184=20 0b dpdk_mempool_test!malloc_socket+0xf9 0c dpdk_mempool_test!rte_malloc_socket+0x39=20 0d dpdk_mempool_test!rte_zmalloc_socket+0x31=20 0e dpdk_mempool_test!rte_zmalloc+0x2d=20 0f dpdk_mempool_test!rte_mempool_create_empty+0x1c9=20 10 dpdk_mempool_test!rte_mempool_create+0xf8=20 > -----Original Message----- > From: Dmitry Kozlyuk > Sent: Wednesday, April 29, 2020 2:50 AM > To: dev@dpdk.org > Cc: Dmitry Malloy (MESHCHANINOV) ; Narcisa > Ana Maria Vasile ; Fady Bader > ; Tal Shnaiderman ; Dmitry > Kozlyuk ; Thomas Monjalon > ; Harini Ramakrishnan > ; Omar Cardona > ; Pallavi Kadam ; > Ranjit Menon ; John McNamara > ; Marko Kovacevic > ; Anatoly Burakov > > Subject: [PATCH v4 8/8] eal/windows: implement basic memory > management >=20 > Basic memory management supports core libraries and PMDs operating in > IOVA as PA mode. It uses a kernel-mode driver, virt2phys, to obtain > IOVAs of hugepages allocated from user-mode. Multi-process mode is not > implemented and is forcefully disabled at startup. >=20 > Signed-off-by: Dmitry Kozlyuk > --- > config/meson.build | 12 +- > doc/guides/windows_gsg/run_apps.rst | 54 +- > lib/librte_eal/common/eal_common_memzone.c | 7 + > lib/librte_eal/common/meson.build | 10 + > lib/librte_eal/common/rte_malloc.c | 9 + > lib/librte_eal/rte_eal_exports.def | 119 ++ > lib/librte_eal/windows/eal.c | 144 ++ > lib/librte_eal/windows/eal_memalloc.c | 418 ++++++ > lib/librte_eal/windows/eal_memory.c | 1155 +++++++++++++++++ > lib/librte_eal/windows/eal_mp.c | 103 ++ > lib/librte_eal/windows/eal_windows.h | 90 ++ > lib/librte_eal/windows/include/meson.build | 1 + > lib/librte_eal/windows/include/rte_os.h | 4 + > .../windows/include/rte_virt2phys.h | 34 + > lib/librte_eal/windows/include/rte_windows.h | 2 + > lib/librte_eal/windows/include/unistd.h | 3 + > lib/librte_eal/windows/meson.build | 5 + > 17 files changed, 2164 insertions(+), 6 deletions(-) > create mode 100644 lib/librte_eal/windows/eal_memalloc.c > create mode 100644 lib/librte_eal/windows/eal_memory.c > create mode 100644 lib/librte_eal/windows/eal_mp.c > create mode 100644 lib/librte_eal/windows/include/rte_virt2phys.h >=20 > diff --git a/config/meson.build b/config/meson.build > index 74f163223..800b5ba33 100644 > --- a/config/meson.build > +++ b/config/meson.build > @@ -264,15 +264,21 @@ if is_freebsd > endif >=20 > if is_windows > - # Minimum supported API is Windows 7. > - add_project_arguments('-D_WIN32_WINNT=3D0x0601', language: 'c') > + # VirtualAlloc2() is available since Windows 10 / Server 2016. > + add_project_arguments('-D_WIN32_WINNT=3D0x0A00', language: 'c') >=20 > # Use MinGW-w64 stdio, because DPDK assumes ANSI-compliant > formatting. > if cc.get_id() =3D=3D 'gcc' > add_project_arguments('-D__USE_MINGW_ANSI_STDIO', > language: 'c') > endif >=20 > - add_project_link_arguments('-ladvapi32', language: 'c') > + # Contrary to docs, VirtualAlloc2() is exported by mincore.lib > + # in Windows SDK, while MinGW exports it by advapi32.a. > + if is_ms_linker > + add_project_link_arguments('-lmincore', language: 'c') > + endif > + > + add_project_link_arguments('-ladvapi32', '-lsetupapi', language: 'c') > endif >=20 > if get_option('b_lto') > diff --git a/doc/guides/windows_gsg/run_apps.rst > b/doc/guides/windows_gsg/run_apps.rst > index 21ac7f6c1..78e5a614f 100644 > --- a/doc/guides/windows_gsg/run_apps.rst > +++ b/doc/guides/windows_gsg/run_apps.rst > @@ -7,10 +7,10 @@ Running DPDK Applications > Grant *Lock pages in memory* Privilege > -------------------------------------- >=20 > -Use of hugepages ("large pages" in Windows terminolocy) requires > +Use of hugepages ("large pages" in Windows terminology) requires > ``SeLockMemoryPrivilege`` for the user running an application. >=20 > -1. Open *Local Security Policy* snap in, either: > +1. Open *Local Security Policy* snap-in, either: >=20 > * Control Panel / Computer Management / Local Security Policy; > * or Win+R, type ``secpol``, press Enter. > @@ -24,7 +24,55 @@ Use of hugepages ("large pages" in Windows > terminolocy) requires >=20 > See `Large-Page Support`_ in MSDN for details. >=20 > -.. _Large-page Support: > https://eur03.safelinks.protection.outlook.com/?url=3Dhttps%3A%2F%2Fdocs. > microsoft.com%2Fen-us%2Fwindows%2Fwin32%2Fmemory%2Flarge-page- > support&data=3D02%7C01%7Cfady%40mellanox.com%7C3c6bd806786c47 > 9c1e3008d7ebcef213%7Ca652971c7d2e4d9ba6a4d149256f461b%7C0%7C0%7 > C637237146372884132&sdata=3Dl41r9A%2FflDmhDInC9L84zvPkO4efbRImC > YmtI9IOkT4%3D&reserved=3D0 > +.. _Large-Page Support: > https://eur03.safelinks.protection.outlook.com/?url=3Dhttps%3A%2F%2Fdocs. > microsoft.com%2Fen-us%2Fwindows%2Fwin32%2Fmemory%2Flarge-page- > support&data=3D02%7C01%7Cfady%40mellanox.com%7C3c6bd806786c47 > 9c1e3008d7ebcef213%7Ca652971c7d2e4d9ba6a4d149256f461b%7C0%7C0%7 > C637237146372884132&sdata=3Dl41r9A%2FflDmhDInC9L84zvPkO4efbRImC > YmtI9IOkT4%3D&reserved=3D0 > + > + > +Load virt2phys Driver > +--------------------- > + > +Access to physical addresses is provided by a kernel-mode driver, virt2p= hys. > +It is mandatory at least for using hardware PMDs, but may also be requir= ed > +for mempools. > + > +Refer to documentation in ``dpdk-kmods`` repository for details on syste= m > +setup, driver build and installation. This driver is not signed, so sign= ature > +checking must be disabled to load it. > + > +.. warning:: > + > + Disabling driver signature enforcement weakens OS security. > + It is discouraged in production environments. > + > +Compiled package consists of ``virt2phys.inf``, ``virt2phys.cat``, > +and ``virt2phys.sys``. It can be installed as follows > +from Elevated Command Prompt: > + > +.. code-block:: console > + > + pnputil /add-driver Z:\path\to\virt2phys.inf /install > + > +On Windows Server additional steps are required: > + > +1. From Device Manager, Action menu, select "Add legacy hardware". > +2. It will launch the "Add Hardware Wizard". Click "Next". > +3. Select second option "Install the hardware that I manually select > + from a list (Advanced)". > +4. On the next screen, "Kernel bypass" will be shown as a device class. > +5. Select it, and click "Next". > +6. The previously installed drivers will now be installed for the > + "Virtual to physical address translator" device. > + > +When loaded successfully, the driver is shown in *Device Manager* as > *Virtual > +to physical address translator* device under *Kernel bypass* category. > +Installed driver persists across reboots. > + > +If DPDK is unable to communicate with the driver, a warning is printed > +on initialization (debug-level logs provide more details): > + > +.. code-block:: text > + > + EAL: Cannot open virt2phys driver interface > + >=20 >=20 > Run the ``helloworld`` Example > diff --git a/lib/librte_eal/common/eal_common_memzone.c > b/lib/librte_eal/common/eal_common_memzone.c > index 7c21aa921..9fa7bf352 100644 > --- a/lib/librte_eal/common/eal_common_memzone.c > +++ b/lib/librte_eal/common/eal_common_memzone.c > @@ -19,7 +19,14 @@ > #include > #include > #include > + > +#ifndef RTE_EXEC_ENV_WINDOWS > #include > +#else > +#define rte_eal_trace_memzone_reserve(...) > +#define rte_eal_trace_memzone_lookup(...) > +#define rte_eal_trace_memzone_free(...) > +#endif >=20 > #include "malloc_heap.h" > #include "malloc_elem.h" > diff --git a/lib/librte_eal/common/meson.build > b/lib/librte_eal/common/meson.build > index 155da29b4..9bb234009 100644 > --- a/lib/librte_eal/common/meson.build > +++ b/lib/librte_eal/common/meson.build > @@ -9,11 +9,21 @@ if is_windows > 'eal_common_class.c', > 'eal_common_devargs.c', > 'eal_common_errno.c', > + 'eal_common_fbarray.c', > 'eal_common_launch.c', > 'eal_common_lcore.c', > 'eal_common_log.c', > + 'eal_common_mcfg.c', > + 'eal_common_memalloc.c', > + 'eal_common_memory.c', > + 'eal_common_memzone.c', > 'eal_common_options.c', > + 'eal_common_string_fns.c', > + 'eal_common_tailqs.c', > 'eal_common_thread.c', > + 'malloc_elem.c', > + 'malloc_heap.c', > + 'rte_malloc.c', > 'rte_option.c', > ) > subdir_done() > diff --git a/lib/librte_eal/common/rte_malloc.c > b/lib/librte_eal/common/rte_malloc.c > index f1b73168b..34b416927 100644 > --- a/lib/librte_eal/common/rte_malloc.c > +++ b/lib/librte_eal/common/rte_malloc.c > @@ -20,7 +20,16 @@ > #include > #include > #include > + > +#ifndef RTE_EXEC_ENV_WINDOWS > #include > +#else > +/* Suppress -Wempty-body for tracepoints used as "if" body. */ > +#define rte_eal_trace_mem_malloc(...) do {} while (0) > +#define rte_eal_trace_mem_zmalloc(...) do {} while (0) > +#define rte_eal_trace_mem_realloc(...) do {} while (0) > +#define rte_eal_trace_mem_free(...) do {} while (0) > +#endif >=20 > #include > #include "malloc_elem.h" > diff --git a/lib/librte_eal/rte_eal_exports.def > b/lib/librte_eal/rte_eal_exports.def > index 12a6c79d6..854b83bcd 100644 > --- a/lib/librte_eal/rte_eal_exports.def > +++ b/lib/librte_eal/rte_eal_exports.def > @@ -1,9 +1,128 @@ > EXPORTS > __rte_panic > + rte_calloc > + rte_calloc_socket > rte_eal_get_configuration > + rte_eal_has_hugepages > rte_eal_init > + rte_eal_iova_mode > rte_eal_mp_remote_launch > rte_eal_mp_wait_lcore > + rte_eal_process_type > rte_eal_remote_launch > + rte_eal_tailq_lookup > + rte_eal_tailq_register > + rte_eal_using_phys_addrs > + rte_free > rte_log > + rte_malloc > + rte_malloc_dump_stats > + rte_malloc_get_socket_stats > + rte_malloc_set_limit > + rte_malloc_socket > + rte_malloc_validate > + rte_malloc_virt2iova > + rte_mcfg_mem_read_lock > + rte_mcfg_mem_read_unlock > + rte_mcfg_mem_write_lock > + rte_mcfg_mem_write_unlock > + rte_mcfg_mempool_read_lock > + rte_mcfg_mempool_read_unlock > + rte_mcfg_mempool_write_lock > + rte_mcfg_mempool_write_unlock > + rte_mcfg_tailq_read_lock > + rte_mcfg_tailq_read_unlock > + rte_mcfg_tailq_write_lock > + rte_mcfg_tailq_write_unlock > + rte_mem_lock_page > + rte_mem_virt2iova > + rte_mem_virt2phy > + rte_memory_get_nchannel > + rte_memory_get_nrank > + rte_memzone_dump > + rte_memzone_free > + rte_memzone_lookup > + rte_memzone_reserve > + rte_memzone_reserve_aligned > + rte_memzone_reserve_bounded > + rte_memzone_walk > rte_vlog > + rte_realloc > + rte_zmalloc > + rte_zmalloc_socket > + > + rte_mp_action_register > + rte_mp_action_unregister > + rte_mp_reply > + rte_mp_sendmsg > + > + rte_fbarray_attach > + rte_fbarray_destroy > + rte_fbarray_detach > + rte_fbarray_dump_metadata > + rte_fbarray_find_contig_free > + rte_fbarray_find_contig_used > + rte_fbarray_find_idx > + rte_fbarray_find_next_free > + rte_fbarray_find_next_n_free > + rte_fbarray_find_next_n_used > + rte_fbarray_find_next_used > + rte_fbarray_get > + rte_fbarray_init > + rte_fbarray_is_used > + rte_fbarray_set_free > + rte_fbarray_set_used > + rte_malloc_dump_heaps > + rte_mem_alloc_validator_register > + rte_mem_alloc_validator_unregister > + rte_mem_check_dma_mask > + rte_mem_event_callback_register > + rte_mem_event_callback_unregister > + rte_mem_iova2virt > + rte_mem_virt2memseg > + rte_mem_virt2memseg_list > + rte_memseg_contig_walk > + rte_memseg_list_walk > + rte_memseg_walk > + rte_mp_request_async > + rte_mp_request_sync > + > + rte_fbarray_find_prev_free > + rte_fbarray_find_prev_n_free > + rte_fbarray_find_prev_n_used > + rte_fbarray_find_prev_used > + rte_fbarray_find_rev_contig_free > + rte_fbarray_find_rev_contig_used > + rte_memseg_contig_walk_thread_unsafe > + rte_memseg_list_walk_thread_unsafe > + rte_memseg_walk_thread_unsafe > + > + rte_malloc_heap_create > + rte_malloc_heap_destroy > + rte_malloc_heap_get_socket > + rte_malloc_heap_memory_add > + rte_malloc_heap_memory_attach > + rte_malloc_heap_memory_detach > + rte_malloc_heap_memory_remove > + rte_malloc_heap_socket_is_external > + rte_mem_check_dma_mask_thread_unsafe > + rte_mem_set_dma_mask > + rte_memseg_get_fd > + rte_memseg_get_fd_offset > + rte_memseg_get_fd_offset_thread_unsafe > + rte_memseg_get_fd_thread_unsafe > + > + rte_extmem_attach > + rte_extmem_detach > + rte_extmem_register > + rte_extmem_unregister > + > + rte_fbarray_find_biggest_free > + rte_fbarray_find_biggest_used > + rte_fbarray_find_rev_biggest_free > + rte_fbarray_find_rev_biggest_used > + > + rte_get_page_size > + rte_mem_lock > + rte_mem_map > + rte_mem_unmap > diff --git a/lib/librte_eal/windows/eal.c b/lib/librte_eal/windows/eal.c > index 63461f51a..38f17f09c 100644 > --- a/lib/librte_eal/windows/eal.c > +++ b/lib/librte_eal/windows/eal.c > @@ -93,6 +93,24 @@ eal_proc_type_detect(void) > return ptype; > } >=20 > +enum rte_proc_type_t > +rte_eal_process_type(void) > +{ > + return rte_config.process_type; > +} > + > +int > +rte_eal_has_hugepages(void) > +{ > + return !internal_config.no_hugetlbfs; > +} > + > +enum rte_iova_mode > +rte_eal_iova_mode(void) > +{ > + return rte_config.iova_mode; > +} > + > /* display usage */ > static void > eal_usage(const char *prgname) > @@ -224,6 +242,89 @@ rte_eal_init_alert(const char *msg) > RTE_LOG(ERR, EAL, "%s\n", msg); > } >=20 > +int > +eal_file_truncate(int fd, ssize_t size) > +{ > + HANDLE handle; > + DWORD ret; > + LONG low =3D (LONG)((size_t)size); > + LONG high =3D (LONG)((size_t)size >> 32); > + > + handle =3D (HANDLE)_get_osfhandle(fd); > + if (handle =3D=3D INVALID_HANDLE_VALUE) { > + rte_errno =3D EBADF; > + return -1; > + } > + > + ret =3D SetFilePointer(handle, low, &high, FILE_BEGIN); > + if (ret =3D=3D INVALID_SET_FILE_POINTER) { > + RTE_LOG_WIN32_ERR("SetFilePointer()"); > + rte_errno =3D EINVAL; > + return -1; > + } > + > + return 0; > +} > + > +static int > +lock_file(HANDLE handle, enum eal_flock_op op, enum eal_flock_mode > mode) > +{ > + DWORD sys_flags =3D 0; > + OVERLAPPED overlapped; > + > + if (op =3D=3D EAL_FLOCK_EXCLUSIVE) > + sys_flags |=3D LOCKFILE_EXCLUSIVE_LOCK; > + if (mode =3D=3D EAL_FLOCK_RETURN) > + sys_flags |=3D LOCKFILE_FAIL_IMMEDIATELY; > + > + memset(&overlapped, 0, sizeof(overlapped)); > + if (!LockFileEx(handle, sys_flags, 0, 0, 0, &overlapped)) { > + if ((sys_flags & LOCKFILE_FAIL_IMMEDIATELY) && > + (GetLastError() =3D=3D ERROR_IO_PENDING)) { > + rte_errno =3D EWOULDBLOCK; > + } else { > + RTE_LOG_WIN32_ERR("LockFileEx()"); > + rte_errno =3D EINVAL; > + } > + return -1; > + } > + > + return 0; > +} > + > +static int > +unlock_file(HANDLE handle) > +{ > + if (!UnlockFileEx(handle, 0, 0, 0, NULL)) { > + RTE_LOG_WIN32_ERR("UnlockFileEx()"); > + rte_errno =3D EINVAL; > + return -1; > + } > + return 0; > +} > + > +int > +eal_file_lock(int fd, enum eal_flock_op op, enum eal_flock_mode mode) > +{ > + HANDLE handle =3D (HANDLE)_get_osfhandle(fd); > + > + if (handle =3D=3D INVALID_HANDLE_VALUE) { > + rte_errno =3D EBADF; > + return -1; > + } > + > + switch (op) { > + case EAL_FLOCK_EXCLUSIVE: > + case EAL_FLOCK_SHARED: > + return lock_file(handle, op, mode); > + case EAL_FLOCK_UNLOCK: > + return unlock_file(handle); > + default: > + rte_errno =3D EINVAL; > + return -1; > + } > +} > + > /* Launch threads, called at application init(). */ > int > rte_eal_init(int argc, char **argv) > @@ -245,6 +346,13 @@ rte_eal_init(int argc, char **argv) > if (fctret < 0) > exit(1); >=20 > + /* Prevent creation of shared memory files. */ > + if (internal_config.no_shconf =3D=3D 0) { > + RTE_LOG(WARNING, EAL, "Multi-process support is > requested, " > + "but not available.\n"); > + internal_config.no_shconf =3D 1; > + } > + > if (!internal_config.no_hugetlbfs && (eal_hugepage_info_init() < 0)) > { > rte_eal_init_alert("Cannot get hugepage information"); > rte_errno =3D EACCES; > @@ -256,6 +364,42 @@ rte_eal_init(int argc, char **argv) > internal_config.memory =3D > MEMSIZE_IF_NO_HUGE_PAGE; > } >=20 > + if (eal_mem_win32api_init() < 0) { > + rte_eal_init_alert("Cannot access Win32 memory > management"); > + rte_errno =3D ENOTSUP; > + return -1; > + } > + > + if (eal_mem_virt2iova_init() < 0) { > + /* Non-fatal error if physical addresses are not required. */ > + RTE_LOG(WARNING, EAL, "Cannot access virt2phys driver, " > + "PA will not be available\n"); > + } > + > + if (rte_eal_memzone_init() < 0) { > + rte_eal_init_alert("Cannot init memzone"); > + rte_errno =3D ENODEV; > + return -1; > + } > + > + if (rte_eal_memory_init() < 0) { > + rte_eal_init_alert("Cannot init memory"); > + rte_errno =3D ENOMEM; > + return -1; > + } > + > + if (rte_eal_malloc_heap_init() < 0) { > + rte_eal_init_alert("Cannot init malloc heap"); > + rte_errno =3D ENODEV; > + return -1; > + } > + > + if (rte_eal_tailqs_init() < 0) { > + rte_eal_init_alert("Cannot init tail queues for objects"); > + rte_errno =3D EFAULT; > + return -1; > + } > + > eal_thread_init_master(rte_config.master_lcore); >=20 > RTE_LCORE_FOREACH_SLAVE(i) { > diff --git a/lib/librte_eal/windows/eal_memalloc.c > b/lib/librte_eal/windows/eal_memalloc.c > new file mode 100644 > index 000000000..e72e785b8 > --- /dev/null > +++ b/lib/librte_eal/windows/eal_memalloc.c > @@ -0,0 +1,418 @@ > +/* SPDX-License-Identifier: BSD-3-Clause > + * Copyright (c) 2020 Dmitry Kozlyuk > + */ > + > +#include > +#include > +#include > + > +#include "eal_internal_cfg.h" > +#include "eal_memalloc.h" > +#include "eal_memcfg.h" > +#include "eal_private.h" > +#include "eal_windows.h" > + > +int > +eal_memalloc_get_seg_fd(int list_idx, int seg_idx) > +{ > + /* Hugepages have no assiciated files in Windows. */ > + RTE_SET_USED(list_idx); > + RTE_SET_USED(seg_idx); > + EAL_LOG_NOT_IMPLEMENTED(); > + return -1; > +} > + > +int > +eal_memalloc_get_seg_fd_offset(int list_idx, int seg_idx, size_t *offset= ) > +{ > + /* Hugepages have no assiciated files in Windows. */ > + RTE_SET_USED(list_idx); > + RTE_SET_USED(seg_idx); > + RTE_SET_USED(offset); > + EAL_LOG_NOT_IMPLEMENTED(); > + return -1; > +} > + > +static int > +alloc_seg(struct rte_memseg *ms, void *requested_addr, int socket_id, > + struct hugepage_info *hi) > +{ > + HANDLE current_process; > + unsigned int numa_node; > + size_t alloc_sz; > + void *addr; > + rte_iova_t iova =3D RTE_BAD_IOVA; > + PSAPI_WORKING_SET_EX_INFORMATION info; > + PSAPI_WORKING_SET_EX_BLOCK *page; > + > + if (ms->len > 0) { > + /* If a segment is already allocated as needed, return it. */ > + if ((ms->addr =3D=3D requested_addr) && > + (ms->socket_id =3D=3D socket_id) && > + (ms->hugepage_sz =3D=3D hi->hugepage_sz)) { > + return 0; > + } > + > + /* Bugcheck, should not happen. */ > + RTE_LOG(DEBUG, EAL, "Attempted to reallocate segment %p > " > + "(size %zu) on socket %d", ms->addr, > + ms->len, ms->socket_id); > + return -1; > + } > + > + current_process =3D GetCurrentProcess(); > + numa_node =3D eal_socket_numa_node(socket_id); > + alloc_sz =3D hi->hugepage_sz; > + > + if (requested_addr =3D=3D NULL) { > + /* Request a new chunk of memory from OS. */ > + addr =3D eal_mem_alloc_socket(alloc_sz, socket_id); > + if (addr =3D=3D NULL) { > + RTE_LOG(DEBUG, EAL, "Cannot allocate %zu bytes " > + "on socket %d\n", alloc_sz, socket_id); > + return -1; > + } > + } else { > + /* Requested address is already reserved, commit memory. > */ > + addr =3D eal_mem_commit(requested_addr, alloc_sz, > socket_id); > + if (addr =3D=3D NULL) { > + RTE_LOG(DEBUG, EAL, "Cannot commit reserved > memory %p " > + "(size %zu) on socket %d\n", > + requested_addr, alloc_sz, socket_id); > + return -1; > + } > + } > + > + /* Force OS to allocate a physical page and select a NUMA node. > + * Hugepages are not pageable in Windows, so there's no race > + * for physical address. > + */ > + *(volatile int *)addr =3D *(volatile int *)addr; > + > + /* Only try to obtain IOVA if it's available, so that applications > + * that do not need IOVA can use this allocator. > + */ > + if (rte_eal_using_phys_addrs()) { > + iova =3D rte_mem_virt2iova(addr); > + if (iova =3D=3D RTE_BAD_IOVA) { > + RTE_LOG(DEBUG, EAL, > + "Cannot get IOVA of allocated segment\n"); > + goto error; > + } > + } > + > + /* Only "Ex" function can handle hugepages. */ > + info.VirtualAddress =3D addr; > + if (!QueryWorkingSetEx(current_process, &info, sizeof(info))) { > + RTE_LOG_WIN32_ERR("QueryWorkingSetEx()"); > + goto error; > + } > + > + page =3D &info.VirtualAttributes; > + if (!page->Valid || !page->LargePage) { > + RTE_LOG(DEBUG, EAL, "Got regular page instead of a > hugepage\n"); > + goto error; > + } > + if (page->Node !=3D numa_node) { > + RTE_LOG(DEBUG, EAL, > + "NUMA node hint %u (socket %d) not respected, got > %u\n", > + numa_node, socket_id, page->Node); > + goto error; > + } > + > + ms->addr =3D addr; > + ms->hugepage_sz =3D hi->hugepage_sz; > + ms->len =3D alloc_sz; > + ms->nchannel =3D rte_memory_get_nchannel(); > + ms->nrank =3D rte_memory_get_nrank(); > + ms->iova =3D iova; > + ms->socket_id =3D socket_id; > + > + return 0; > + > +error: > + /* Only jump here when `addr` and `alloc_sz` are valid. */ > + eal_mem_decommit(addr, alloc_sz); > + return -1; > +} > + > +static int > +free_seg(struct rte_memseg *ms) > +{ > + if (eal_mem_decommit(ms->addr, ms->len)) > + return -1; > + > + /* Must clear the segment, because alloc_seg() inspects it. */ > + memset(ms, 0, sizeof(*ms)); > + return 0; > +} > + > +struct alloc_walk_param { > + struct hugepage_info *hi; > + struct rte_memseg **ms; > + size_t page_sz; > + unsigned int segs_allocated; > + unsigned int n_segs; > + int socket; > + bool exact; > +}; > + > +static int > +alloc_seg_walk(const struct rte_memseg_list *msl, void *arg) > +{ > + struct rte_mem_config *mcfg =3D rte_eal_get_configuration()- > >mem_config; > + struct alloc_walk_param *wa =3D arg; > + struct rte_memseg_list *cur_msl; > + size_t page_sz; > + int cur_idx, start_idx, j; > + unsigned int msl_idx, need, i; > + > + if (msl->page_sz !=3D wa->page_sz) > + return 0; > + if (msl->socket_id !=3D wa->socket) > + return 0; > + > + page_sz =3D (size_t)msl->page_sz; > + > + msl_idx =3D msl - mcfg->memsegs; > + cur_msl =3D &mcfg->memsegs[msl_idx]; > + > + need =3D wa->n_segs; > + > + /* try finding space in memseg list */ > + if (wa->exact) { > + /* if we require exact number of pages in a list, find them */ > + cur_idx =3D rte_fbarray_find_next_n_free( > + &cur_msl->memseg_arr, 0, need); > + if (cur_idx < 0) > + return 0; > + start_idx =3D cur_idx; > + } else { > + int cur_len; > + > + /* we don't require exact number of pages, so we're going to > go > + * for best-effort allocation. that means finding the biggest > + * unused block, and going with that. > + */ > + cur_idx =3D rte_fbarray_find_biggest_free( > + &cur_msl->memseg_arr, 0); > + if (cur_idx < 0) > + return 0; > + start_idx =3D cur_idx; > + /* adjust the size to possibly be smaller than original > + * request, but do not allow it to be bigger. > + */ > + cur_len =3D rte_fbarray_find_contig_free( > + &cur_msl->memseg_arr, cur_idx); > + need =3D RTE_MIN(need, (unsigned int)cur_len); > + } > + > + for (i =3D 0; i < need; i++, cur_idx++) { > + struct rte_memseg *cur; > + void *map_addr; > + > + cur =3D rte_fbarray_get(&cur_msl->memseg_arr, cur_idx); > + map_addr =3D RTE_PTR_ADD(cur_msl->base_va, cur_idx * > page_sz); > + > + if (alloc_seg(cur, map_addr, wa->socket, wa->hi)) { > + RTE_LOG(DEBUG, EAL, "attempted to allocate %i > segments, " > + "but only %i were allocated\n", need, i); > + > + /* if exact number wasn't requested, stop */ > + if (!wa->exact) > + goto out; > + > + /* clean up */ > + for (j =3D start_idx; j < cur_idx; j++) { > + struct rte_memseg *tmp; > + struct rte_fbarray *arr =3D &cur_msl- > >memseg_arr; > + > + tmp =3D rte_fbarray_get(arr, j); > + rte_fbarray_set_free(arr, j); > + > + if (free_seg(tmp)) > + RTE_LOG(DEBUG, EAL, "Cannot free > page\n"); > + } > + /* clear the list */ > + if (wa->ms) > + memset(wa->ms, 0, sizeof(*wa->ms) * wa- > >n_segs); > + > + return -1; > + } > + if (wa->ms) > + wa->ms[i] =3D cur; > + > + rte_fbarray_set_used(&cur_msl->memseg_arr, cur_idx); > + } > + > +out: > + wa->segs_allocated =3D i; > + if (i > 0) > + cur_msl->version++; > + > + /* if we didn't allocate any segments, move on to the next list */ > + return i > 0; > +} > + > +struct free_walk_param { > + struct hugepage_info *hi; > + struct rte_memseg *ms; > +}; > +static int > +free_seg_walk(const struct rte_memseg_list *msl, void *arg) > +{ > + struct rte_mem_config *mcfg =3D rte_eal_get_configuration()- > >mem_config; > + struct rte_memseg_list *found_msl; > + struct free_walk_param *wa =3D arg; > + uintptr_t start_addr, end_addr; > + int msl_idx, seg_idx, ret; > + > + start_addr =3D (uintptr_t) msl->base_va; > + end_addr =3D start_addr + msl->len; > + > + if ((uintptr_t)wa->ms->addr < start_addr || > + (uintptr_t)wa->ms->addr >=3D end_addr) > + return 0; > + > + msl_idx =3D msl - mcfg->memsegs; > + seg_idx =3D RTE_PTR_DIFF(wa->ms->addr, start_addr) / msl->page_sz; > + > + /* msl is const */ > + found_msl =3D &mcfg->memsegs[msl_idx]; > + found_msl->version++; > + > + rte_fbarray_set_free(&found_msl->memseg_arr, seg_idx); > + > + ret =3D free_seg(wa->ms); > + > + return (ret < 0) ? (-1) : 1; > +} > + > +int > +eal_memalloc_alloc_seg_bulk(struct rte_memseg **ms, int n_segs, > + size_t page_sz, int socket, bool exact) > +{ > + unsigned int i; > + int ret =3D -1; > + struct alloc_walk_param wa; > + struct hugepage_info *hi =3D NULL; > + > + if (internal_config.legacy_mem) { > + RTE_LOG(ERR, EAL, "dynamic allocation not supported in > legacy mode\n"); > + return -ENOTSUP; > + } > + > + for (i =3D 0; i < internal_config.num_hugepage_sizes; i++) { > + struct hugepage_info *hpi =3D > &internal_config.hugepage_info[i]; > + if (page_sz =3D=3D hpi->hugepage_sz) { > + hi =3D hpi; > + break; > + } > + } > + if (!hi) { > + RTE_LOG(ERR, EAL, "cannot find relevant hugepage_info > entry\n"); > + return -1; > + } > + > + memset(&wa, 0, sizeof(wa)); > + wa.exact =3D exact; > + wa.hi =3D hi; > + wa.ms =3D ms; > + wa.n_segs =3D n_segs; > + wa.page_sz =3D page_sz; > + wa.socket =3D socket; > + wa.segs_allocated =3D 0; > + > + /* memalloc is locked, so it's safe to use thread-unsafe version */ > + ret =3D rte_memseg_list_walk_thread_unsafe(alloc_seg_walk, &wa); > + if (ret =3D=3D 0) { > + RTE_LOG(ERR, EAL, "cannot find suitable memseg_list\n"); > + ret =3D -1; > + } else if (ret > 0) { > + ret =3D (int)wa.segs_allocated; > + } > + > + return ret; > +} > + > +struct rte_memseg * > +eal_memalloc_alloc_seg(size_t page_sz, int socket) > +{ > + struct rte_memseg *ms =3D NULL; > + eal_memalloc_alloc_seg_bulk(&ms, 1, page_sz, socket, true); > + return ms; > +} > + > +int > +eal_memalloc_free_seg_bulk(struct rte_memseg **ms, int n_segs) > +{ > + int seg, ret =3D 0; > + > + /* dynamic free not supported in legacy mode */ > + if (internal_config.legacy_mem) > + return -1; > + > + for (seg =3D 0; seg < n_segs; seg++) { > + struct rte_memseg *cur =3D ms[seg]; > + struct hugepage_info *hi =3D NULL; > + struct free_walk_param wa; > + size_t i; > + int walk_res; > + > + /* if this page is marked as unfreeable, fail */ > + if (cur->flags & RTE_MEMSEG_FLAG_DO_NOT_FREE) { > + RTE_LOG(DEBUG, EAL, "Page is not allowed to be > freed\n"); > + ret =3D -1; > + continue; > + } > + > + memset(&wa, 0, sizeof(wa)); > + > + for (i =3D 0; i < RTE_DIM(internal_config.hugepage_info); > + i++) { > + hi =3D &internal_config.hugepage_info[i]; > + if (cur->hugepage_sz =3D=3D hi->hugepage_sz) > + break; > + } > + if (i =3D=3D RTE_DIM(internal_config.hugepage_info)) { > + RTE_LOG(ERR, EAL, "Can't find relevant > hugepage_info entry\n"); > + ret =3D -1; > + continue; > + } > + > + wa.ms =3D cur; > + wa.hi =3D hi; > + > + /* memalloc is locked, so it's safe to use thread-unsafe > version > + */ > + walk_res =3D > rte_memseg_list_walk_thread_unsafe(free_seg_walk, > + &wa); > + if (walk_res =3D=3D 1) > + continue; > + if (walk_res =3D=3D 0) > + RTE_LOG(ERR, EAL, "Couldn't find memseg list\n"); > + ret =3D -1; > + } > + return ret; > +} > + > +int > +eal_memalloc_free_seg(struct rte_memseg *ms) > +{ > + return eal_memalloc_free_seg_bulk(&ms, 1); > +} > + > +int > +eal_memalloc_sync_with_primary(void) > +{ > + /* No multi-process support. */ > + EAL_LOG_NOT_IMPLEMENTED(); > + return -1; > +} > + > +int > +eal_memalloc_init(void) > +{ > + /* No action required. */ > + return 0; > +} > diff --git a/lib/librte_eal/windows/eal_memory.c > b/lib/librte_eal/windows/eal_memory.c > new file mode 100644 > index 000000000..3812b7c67 > --- /dev/null > +++ b/lib/librte_eal/windows/eal_memory.c > @@ -0,0 +1,1155 @@ > +/* SPDX-License-Identifier: BSD-3-Clause > + * Copyright (c) 2010-2014 Intel Corporation (functions from Linux EAL) > + * Copyright (c) 2020 Dmitry Kozlyuk (Windows specifics) > + */ > + > +#include > +#include > + > +#include > +#include > + > +#include "eal_internal_cfg.h" > +#include "eal_memalloc.h" > +#include "eal_memcfg.h" > +#include "eal_options.h" > +#include "eal_private.h" > +#include "eal_windows.h" > + > +#include > + > +/* MinGW-w64 headers lack VirtualAlloc2() in some distributions. > + * Provide a copy of definitions and code to load it dynamically. > + * Note: definitions are copied verbatim from Microsoft documentation > + * and don't follow DPDK code style. > + * > + * MEM_RESERVE_PLACEHOLDER being defined means VirtualAlloc2() is > present too. > + */ > +#ifndef MEM_PRESERVE_PLACEHOLDER > + > +/* > https://eur03.safelinks.protection.outlook.com/?url=3Dhttps%3A%2F%2Fdocs. > microsoft.com%2Fen-us%2Fwindows%2Fwin32%2Fapi%2Fwinnt%2Fne- > winnt- > mem_extended_parameter_type&data=3D02%7C01%7Cfady%40mellano > x.com%7C3c6bd806786c479c1e3008d7ebcef213%7Ca652971c7d2e4d9ba6a4d > 149256f461b%7C0%7C0%7C637237146372884132&sdata=3DPd0bUVDAN8e > iV5zORXJ9r0ZmzIwsfOaeL650gXPpQww%3D&reserved=3D0 */ > +typedef enum MEM_EXTENDED_PARAMETER_TYPE { > + MemExtendedParameterInvalidType, > + MemExtendedParameterAddressRequirements, > + MemExtendedParameterNumaNode, > + MemExtendedParameterPartitionHandle, > + MemExtendedParameterMax, > + MemExtendedParameterUserPhysicalHandle, > + MemExtendedParameterAttributeFlags > +} *PMEM_EXTENDED_PARAMETER_TYPE; > + > +#define MEM_EXTENDED_PARAMETER_TYPE_BITS 4 > + > +/* > https://eur03.safelinks.protection.outlook.com/?url=3Dhttps%3A%2F%2Fdocs. > microsoft.com%2Fen-us%2Fwindows%2Fwin32%2Fapi%2Fwinnt%2Fns- > winnt- > mem_extended_parameter&data=3D02%7C01%7Cfady%40mellanox.com > %7C3c6bd806786c479c1e3008d7ebcef213%7Ca652971c7d2e4d9ba6a4d149256 > f461b%7C0%7C0%7C637237146372884132&sdata=3Ds5nguLunGkdr2hgJUS > MIqV5fw7Qo1SDfo0TC%2BA3CFfY%3D&reserved=3D0 */ > +typedef struct MEM_EXTENDED_PARAMETER { > + struct { > + DWORD64 Type : MEM_EXTENDED_PARAMETER_TYPE_BITS; > + DWORD64 Reserved : 64 - > MEM_EXTENDED_PARAMETER_TYPE_BITS; > + } DUMMYSTRUCTNAME; > + union { > + DWORD64 ULong64; > + PVOID Pointer; > + SIZE_T Size; > + HANDLE Handle; > + DWORD ULong; > + } DUMMYUNIONNAME; > +} MEM_EXTENDED_PARAMETER, *PMEM_EXTENDED_PARAMETER; > + > +/* > https://eur03.safelinks.protection.outlook.com/?url=3Dhttps%3A%2F%2Fdocs. > microsoft.com%2Fen-us%2Fwindows%2Fwin32%2Fapi%2Fmemoryapi%2Fnf- > memoryapi- > virtualalloc2&data=3D02%7C01%7Cfady%40mellanox.com%7C3c6bd806786 > c479c1e3008d7ebcef213%7Ca652971c7d2e4d9ba6a4d149256f461b%7C0%7C0 > %7C637237146372884132&sdata=3D1SsOS8O2lRVD8yqDoTsBM8vTMRlvdJL > fTT38FMAcoec%3D&reserved=3D0 */ > +typedef PVOID (*VirtualAlloc2_type)( > + HANDLE Process, > + PVOID BaseAddress, > + SIZE_T Size, > + ULONG AllocationType, > + ULONG PageProtection, > + MEM_EXTENDED_PARAMETER *ExtendedParameters, > + ULONG ParameterCount > +); > + > +/* VirtualAlloc2() flags. */ > +#define MEM_COALESCE_PLACEHOLDERS 0x00000001 > +#define MEM_PRESERVE_PLACEHOLDER 0x00000002 > +#define MEM_REPLACE_PLACEHOLDER 0x00004000 > +#define MEM_RESERVE_PLACEHOLDER 0x00040000 > + > +/* Named exactly as the function, so that user code does not depend > + * on it being found at compile time or dynamically. > + */ > +static VirtualAlloc2_type VirtualAlloc2; > + > +int > +eal_mem_win32api_init(void) > +{ > + /* Contrary to the docs, VirtualAlloc2() is not in kernel32.dll, > + * see > https://eur03.safelinks.protection.outlook.com/?url=3Dhttps%3A%2F%2Fgithu > b.com%2FMicrosoftDocs%2Ffeedback%2Fissues%2F1129&data=3D02%7C > 01%7Cfady%40mellanox.com%7C3c6bd806786c479c1e3008d7ebcef213%7Ca6 > 52971c7d2e4d9ba6a4d149256f461b%7C0%7C0%7C637237146372884132& > ;sdata=3Dtf%2BSJSNeKcOu9uDinDwsTYsME4R%2BHfdRery%2BUNRWflQ%3D& > amp;reserved=3D0. > + */ > + static const char library_name[] =3D "kernelbase.dll"; > + static const char function[] =3D "VirtualAlloc2"; > + > + HMODULE library =3D NULL; > + int ret =3D 0; > + > + /* Already done. */ > + if (VirtualAlloc2 !=3D NULL) > + return 0; > + > + library =3D LoadLibraryA(library_name); > + if (library =3D=3D NULL) { > + RTE_LOG_WIN32_ERR("LoadLibraryA(\"%s\")", > library_name); > + return -1; > + } > + > + VirtualAlloc2 =3D (VirtualAlloc2_type)( > + (void *)GetProcAddress(library, function)); > + if (VirtualAlloc2 =3D=3D NULL) { > + RTE_LOG_WIN32_ERR("GetProcAddress(\"%s\", \"%s\")\n", > + library_name, function); > + > + /* Contrary to the docs, Server 2016 is not supported. */ > + RTE_LOG(ERR, EAL, "Windows 10 or Windows Server 2019 " > + " is required for memory management\n"); > + ret =3D -1; > + } > + > + FreeLibrary(library); > + > + return ret; > +} > + > +#else > + > +/* Stub in case VirtualAlloc2() is provided by the compiler. */ > +int > +eal_mem_win32api_init(void) > +{ > + return 0; > +} > + > +#endif /* defined(MEM_RESERVE_PLACEHOLDER) */ > + > +static HANDLE virt2phys_device =3D INVALID_HANDLE_VALUE; > + > +int > +eal_mem_virt2iova_init(void) > +{ > + HDEVINFO list =3D INVALID_HANDLE_VALUE; > + SP_DEVICE_INTERFACE_DATA ifdata; > + SP_DEVICE_INTERFACE_DETAIL_DATA *detail =3D NULL; > + DWORD detail_size; > + int ret =3D -1; > + > + list =3D SetupDiGetClassDevs( > + &GUID_DEVINTERFACE_VIRT2PHYS, NULL, NULL, > + DIGCF_DEVICEINTERFACE | DIGCF_PRESENT); > + if (list =3D=3D INVALID_HANDLE_VALUE) { > + RTE_LOG_WIN32_ERR("SetupDiGetClassDevs()"); > + goto exit; > + } > + > + ifdata.cbSize =3D sizeof(ifdata); > + if (!SetupDiEnumDeviceInterfaces( > + list, NULL, &GUID_DEVINTERFACE_VIRT2PHYS, 0, &ifdata)) { > + RTE_LOG_WIN32_ERR("SetupDiEnumDeviceInterfaces()"); > + goto exit; > + } > + > + if (!SetupDiGetDeviceInterfaceDetail( > + list, &ifdata, NULL, 0, &detail_size, NULL)) { > + if (GetLastError() !=3D ERROR_INSUFFICIENT_BUFFER) { > + RTE_LOG_WIN32_ERR( > + "SetupDiGetDeviceInterfaceDetail(probe)"); > + goto exit; > + } > + } > + > + detail =3D malloc(detail_size); > + if (detail =3D=3D NULL) { > + RTE_LOG(ERR, EAL, "Cannot allocate virt2phys " > + "device interface detail data\n"); > + goto exit; > + } > + > + detail->cbSize =3D sizeof(*detail); > + if (!SetupDiGetDeviceInterfaceDetail( > + list, &ifdata, detail, detail_size, NULL, NULL)) { > + > RTE_LOG_WIN32_ERR("SetupDiGetDeviceInterfaceDetail(read)"); > + goto exit; > + } > + > + RTE_LOG(DEBUG, EAL, "Found virt2phys device: %s\n", detail- > >DevicePath); > + > + virt2phys_device =3D CreateFile( > + detail->DevicePath, 0, 0, NULL, OPEN_EXISTING, 0, NULL); > + if (virt2phys_device =3D=3D INVALID_HANDLE_VALUE) { > + RTE_LOG_WIN32_ERR("CreateFile()"); > + goto exit; > + } > + > + /* Indicate success. */ > + ret =3D 0; > + > +exit: > + if (detail !=3D NULL) > + free(detail); > + if (list !=3D INVALID_HANDLE_VALUE) > + SetupDiDestroyDeviceInfoList(list); > + > + return ret; > +} > + > +phys_addr_t > +rte_mem_virt2phy(const void *virt) > +{ > + LARGE_INTEGER phys; > + DWORD bytes_returned; > + > + if (virt2phys_device =3D=3D INVALID_HANDLE_VALUE) > + return RTE_BAD_PHYS_ADDR; > + > + if (!DeviceIoControl( > + virt2phys_device, IOCTL_VIRT2PHYS_TRANSLATE, > + &virt, sizeof(virt), &phys, sizeof(phys), > + &bytes_returned, NULL)) { > + > RTE_LOG_WIN32_ERR("DeviceIoControl(IOCTL_VIRT2PHYS_TRANSL > ATE)"); > + return RTE_BAD_PHYS_ADDR; > + } > + > + return phys.QuadPart; > +} > + > +/* Windows currently only supports IOVA as PA. */ > +rte_iova_t > +rte_mem_virt2iova(const void *virt) > +{ > + phys_addr_t phys; > + > + if (virt2phys_device =3D=3D INVALID_HANDLE_VALUE) > + return RTE_BAD_IOVA; > + > + phys =3D rte_mem_virt2phy(virt); > + if (phys =3D=3D RTE_BAD_PHYS_ADDR) > + return RTE_BAD_IOVA; > + > + return (rte_iova_t)phys; > +} > + > +/* Always using physical addresses under Windows if they can be obtained= . > */ > +int > +rte_eal_using_phys_addrs(void) > +{ > + return virt2phys_device !=3D INVALID_HANDLE_VALUE; > +} > + > +/* Approximate error mapping from VirtualAlloc2() to POSIX mmap(3). */ > +static void > +set_errno_from_win32_alloc_error(DWORD code) > +{ > + switch (code) { > + case ERROR_SUCCESS: > + rte_errno =3D 0; > + break; > + > + case ERROR_INVALID_ADDRESS: > + /* A valid requested address is not available. */ > + case ERROR_COMMITMENT_LIMIT: > + /* May occcur when committing regular memory. */ > + case ERROR_NO_SYSTEM_RESOURCES: > + /* Occurs when the system runs out of hugepages. */ > + rte_errno =3D ENOMEM; > + break; > + > + case ERROR_INVALID_PARAMETER: > + default: > + rte_errno =3D EINVAL; > + break; > + } > +} > + > +void * > +eal_mem_reserve(void *requested_addr, size_t size, int flags) > +{ > + void *virt; > + > + /* Windows requires hugepages to be committed. */ > + if (flags & EAL_RESERVE_HUGEPAGES) { > + rte_errno =3D ENOTSUP; > + return NULL; > + } > + > + virt =3D VirtualAlloc2(GetCurrentProcess(), requested_addr, size, > + MEM_RESERVE | MEM_RESERVE_PLACEHOLDER, > PAGE_NOACCESS, > + NULL, 0); > + if (virt =3D=3D NULL) { > + DWORD err =3D GetLastError(); > + RTE_LOG_WIN32_ERR("VirtualAlloc2()"); > + set_errno_from_win32_alloc_error(err); > + } > + > + if ((flags & EAL_RESERVE_FORCE_ADDRESS) && (virt !=3D > requested_addr)) { > + if (!VirtualFree(virt, 0, MEM_RELEASE)) > + RTE_LOG_WIN32_ERR("VirtualFree()"); > + rte_errno =3D ENOMEM; > + return NULL; > + } > + > + return virt; > +} > + > +void * > +eal_mem_alloc(size_t size, size_t page_size) > +{ > + if (page_size !=3D 0) > + return eal_mem_alloc_socket(size, SOCKET_ID_ANY); > + > + return VirtualAlloc( > + NULL, size, MEM_RESERVE | MEM_COMMIT, > PAGE_READWRITE); > +} > + > +void * > +eal_mem_alloc_socket(size_t size, int socket_id) > +{ > + DWORD flags =3D MEM_RESERVE | MEM_COMMIT; > + void *addr; > + > + flags =3D MEM_RESERVE | MEM_COMMIT | MEM_LARGE_PAGES; > + addr =3D VirtualAllocExNuma(GetCurrentProcess(), NULL, size, flags, > + PAGE_READWRITE, eal_socket_numa_node(socket_id)); > + if (addr =3D=3D NULL) > + rte_errno =3D ENOMEM; > + return addr; > +} > + > +void* > +eal_mem_commit(void *requested_addr, size_t size, int socket_id) > +{ > + MEM_EXTENDED_PARAMETER param; > + DWORD param_count =3D 0; > + DWORD flags; > + void *addr; > + > + if (requested_addr !=3D NULL) { > + MEMORY_BASIC_INFORMATION info; > + if (VirtualQuery(requested_addr, &info, sizeof(info)) =3D=3D 0) { > + RTE_LOG_WIN32_ERR("VirtualQuery()"); > + return NULL; > + } > + > + /* Split reserved region if only a part is committed. */ > + flags =3D MEM_RELEASE | MEM_PRESERVE_PLACEHOLDER; > + if ((info.RegionSize > size) && > + !VirtualFree(requested_addr, size, flags)) { > + RTE_LOG_WIN32_ERR("VirtualFree(%p, %zu, " > + ")", requested_addr, > size); > + return NULL; > + } > + } > + > + if (socket_id !=3D SOCKET_ID_ANY) { > + param_count =3D 1; > + memset(¶m, 0, sizeof(param)); > + param.Type =3D MemExtendedParameterNumaNode; > + param.ULong =3D eal_socket_numa_node(socket_id); > + } > + > + flags =3D MEM_RESERVE | MEM_COMMIT | MEM_LARGE_PAGES; > + if (requested_addr !=3D NULL) > + flags |=3D MEM_REPLACE_PLACEHOLDER; > + > + addr =3D VirtualAlloc2(GetCurrentProcess(), requested_addr, size, > + flags, PAGE_READWRITE, ¶m, param_count); > + if (addr =3D=3D NULL) { > + DWORD err =3D GetLastError(); > + RTE_LOG_WIN32_ERR("VirtualAlloc2(%p, %zu, " > + ")", addr, size); > + set_errno_from_win32_alloc_error(err); > + return NULL; > + } > + > + return addr; > +} > + > +int > +eal_mem_decommit(void *addr, size_t size) > +{ > + /* Decommit memory, which might be a part of a larger reserved > region. > + * Allocator commits hugepage-sized placeholders, so there's no > need > + * to coalesce placeholders back into region, they can be reused as is. > + */ > + if (!VirtualFree(addr, size, MEM_RELEASE | > MEM_PRESERVE_PLACEHOLDER)) { > + RTE_LOG_WIN32_ERR("VirtualFree(%p, %zu, ...)", addr, > size); > + return -1; > + } > + return 0; > +} > + > +/** > + * Free a reserved memory region in full or in part. > + * > + * @param addr > + * Starting address of the area to free. > + * @param size > + * Number of bytes to free. Must be a multiple of page size. > + * @param reserved > + * Fail if the region is not in reserved state. > + * @return > + * * 0 on successful deallocation; > + * * 1 if region mut be in reserved state but it is not; > + * * (-1) on system API failures. > + */ > +static int > +mem_free(void *addr, size_t size, bool reserved) > +{ > + MEMORY_BASIC_INFORMATION info; > + HANDLE process; > + > + if (VirtualQuery(addr, &info, sizeof(info)) =3D=3D 0) { > + RTE_LOG_WIN32_ERR("VirtualQuery()"); > + return -1; > + } > + > + if (reserved && (info.State !=3D MEM_RESERVE)) > + return 1; > + > + process =3D GetCurrentProcess(); > + > + /* Free complete region. */ > + if ((addr =3D=3D info.AllocationBase) && (size =3D=3D info.RegionSize))= { > + if (!VirtualFreeEx(process, addr, 0, MEM_RELEASE)) { > + RTE_LOG_WIN32_ERR("VirtualFree(%p, 0, > MEM_RELEASE)", > + addr); > + } > + return 0; > + } > + > + /* Split the part to be freed and the remaining reservation. */ > + if (!VirtualFreeEx(process, addr, size, > + MEM_RELEASE | MEM_PRESERVE_PLACEHOLDER)) { > + RTE_LOG_WIN32_ERR("VirtualFree(%p, %zu, " > + "MEM_RELEASE | MEM_PRESERVE_PLACEHOLDER)", > addr, size); > + return -1; > + } > + > + /* Actually free reservation part. */ > + if (!VirtualFreeEx(process, addr, 0, MEM_RELEASE)) { > + RTE_LOG_WIN32_ERR("VirtualFree(%p, 0, MEM_RELEASE)", > addr); > + return -1; > + } > + > + return 0; > +} > + > +void > +eal_mem_free(void *virt, size_t size) > +{ > + mem_free(virt, size, false); > +} > + > +int > +eal_mem_set_dump(void *virt, size_t size, bool dump) > +{ > + RTE_SET_USED(virt); > + RTE_SET_USED(size); > + RTE_SET_USED(dump); > + > + /* Windows does not dump reserved memory by default. > + * > + * There is to include or exclude regions from the dump, > + * but this is not currently required by EAL. > + */ > + > + rte_errno =3D ENOTSUP; > + return -1; > +} > + > +void * > +rte_mem_map(void *requested_addr, size_t size, int prot, int flags, > + int fd, size_t offset) > +{ > + HANDLE file_handle =3D INVALID_HANDLE_VALUE; > + HANDLE mapping_handle =3D INVALID_HANDLE_VALUE; > + DWORD sys_prot =3D 0; > + DWORD sys_access =3D 0; > + DWORD size_high =3D (DWORD)(size >> 32); > + DWORD size_low =3D (DWORD)size; > + DWORD offset_high =3D (DWORD)(offset >> 32); > + DWORD offset_low =3D (DWORD)offset; > + LPVOID virt =3D NULL; > + > + if (prot & RTE_PROT_EXECUTE) { > + if (prot & RTE_PROT_READ) { > + sys_prot =3D PAGE_EXECUTE_READ; > + sys_access =3D FILE_MAP_READ | FILE_MAP_EXECUTE; > + } > + if (prot & RTE_PROT_WRITE) { > + sys_prot =3D PAGE_EXECUTE_READWRITE; > + sys_access =3D FILE_MAP_WRITE | > FILE_MAP_EXECUTE; > + } > + } else { > + if (prot & RTE_PROT_READ) { > + sys_prot =3D PAGE_READONLY; > + sys_access =3D FILE_MAP_READ; > + } > + if (prot & RTE_PROT_WRITE) { > + sys_prot =3D PAGE_READWRITE; > + sys_access =3D FILE_MAP_WRITE; > + } > + } > + > + if (flags & RTE_MAP_PRIVATE) > + sys_access |=3D FILE_MAP_COPY; > + > + if ((flags & RTE_MAP_ANONYMOUS) =3D=3D 0) > + file_handle =3D (HANDLE)_get_osfhandle(fd); > + > + mapping_handle =3D CreateFileMapping( > + file_handle, NULL, sys_prot, size_high, size_low, NULL); > + if (mapping_handle =3D=3D INVALID_HANDLE_VALUE) { > + RTE_LOG_WIN32_ERR("CreateFileMapping()"); > + return NULL; > + } > + > + /* There is a race for the requested_addr between mem_free() > + * and MapViewOfFileEx(). MapViewOfFile3() that can replace a > reserved > + * region with a mapping in a single operation, but it does not support > + * private mappings. > + */ > + if (requested_addr !=3D NULL) { > + int ret =3D mem_free(requested_addr, size, true); > + if (ret) { > + if (ret > 0) { > + RTE_LOG(ERR, EAL, "Cannot map memory " > + "to a region not reserved\n"); > + rte_errno =3D EADDRNOTAVAIL; > + } > + return NULL; > + } > + } > + > + virt =3D MapViewOfFileEx(mapping_handle, sys_access, > + offset_high, offset_low, size, requested_addr); > + if (!virt) { > + RTE_LOG_WIN32_ERR("MapViewOfFileEx()"); > + return NULL; > + } > + > + if ((flags & RTE_MAP_FORCE_ADDRESS) && (virt !=3D requested_addr)) > { > + if (!UnmapViewOfFile(virt)) > + RTE_LOG_WIN32_ERR("UnmapViewOfFile()"); > + virt =3D NULL; > + } > + > + if (!CloseHandle(mapping_handle)) > + RTE_LOG_WIN32_ERR("CloseHandle()"); > + > + return virt; > +} > + > +int > +rte_mem_unmap(void *virt, size_t size) > +{ > + RTE_SET_USED(size); > + > + if (!UnmapViewOfFile(virt)) { > + rte_errno =3D GetLastError(); > + RTE_LOG_WIN32_ERR("UnmapViewOfFile()"); > + return -1; > + } > + return 0; > +} > + > +uint64_t > +eal_get_baseaddr(void) > +{ > + /* Windows strategy for memory allocation is undocumented. > + * Returning 0 here effectively disables address guessing > + * unless user provides an address hint. > + */ > + return 0; > +} > + > +size_t > +rte_get_page_size(void) > +{ > + SYSTEM_INFO info; > + GetSystemInfo(&info); > + return info.dwPageSize; > +} > + > +int > +rte_mem_lock(const void *virt, size_t size) > +{ > + /* VirtualLock() takes `void*`, work around compiler warning. */ > + void *addr =3D (void *)((uintptr_t)virt); > + > + if (!VirtualLock(addr, size)) { > + RTE_LOG_WIN32_ERR("VirtualLock()"); > + return -1; > + } > + > + return 0; > +} > + > +static int > +memseg_list_init(struct rte_memseg_list *msl, uint64_t page_sz, > + int n_segs, int socket_id, int type_msl_idx) > +{ > + return eal_memseg_list_init( > + msl, page_sz, n_segs, socket_id, type_msl_idx, true); > +} > + > +static int > +memseg_list_alloc(struct rte_memseg_list *msl) > +{ > + return eal_memseg_list_alloc(msl, 0); > +} > + > +/* > + * Remaining code in this file largely duplicates Linux EAL. > + * Although Windows EAL supports only one hugepage size currently, > + * code structure and comments are preserved so that changes may be > + * easily ported until duplication is removed. > + */ > + > +static int > +memseg_primary_init(void) > +{ > + struct rte_mem_config *mcfg =3D rte_eal_get_configuration()- > >mem_config; > + struct memtype { > + uint64_t page_sz; > + int socket_id; > + } *memtypes =3D NULL; > + int i, hpi_idx, msl_idx, ret =3D -1; /* fail unless told to succeed */ > + struct rte_memseg_list *msl; > + uint64_t max_mem, max_mem_per_type; > + unsigned int max_seglists_per_type; > + unsigned int n_memtypes, cur_type; > + > + /* no-huge does not need this at all */ > + if (internal_config.no_hugetlbfs) > + return 0; > + > + /* > + * figuring out amount of memory we're going to have is a long and > very > + * involved process. the basic element we're operating with is a > memory > + * type, defined as a combination of NUMA node ID and page size (so > that > + * e.g. 2 sockets with 2 page sizes yield 4 memory types in total). > + * > + * deciding amount of memory going towards each memory type is a > + * balancing act between maximum segments per type, maximum > memory per > + * type, and number of detected NUMA nodes. the goal is to make > sure > + * each memory type gets at least one memseg list. > + * > + * the total amount of memory is limited by RTE_MAX_MEM_MB > value. > + * > + * the total amount of memory per type is limited by either > + * RTE_MAX_MEM_MB_PER_TYPE, or by RTE_MAX_MEM_MB > divided by the number > + * of detected NUMA nodes. additionally, maximum number of > segments per > + * type is also limited by RTE_MAX_MEMSEG_PER_TYPE. this is > because for > + * smaller page sizes, it can take hundreds of thousands of segments > to > + * reach the above specified per-type memory limits. > + * > + * additionally, each type may have multiple memseg lists associated > + * with it, each limited by either RTE_MAX_MEM_MB_PER_LIST for > bigger > + * page sizes, or RTE_MAX_MEMSEG_PER_LIST segments for smaller > ones. > + * > + * the number of memseg lists per type is decided based on the > above > + * limits, and also taking number of detected NUMA nodes, to make > sure > + * that we don't run out of memseg lists before we populate all > NUMA > + * nodes with memory. > + * > + * we do this in three stages. first, we collect the number of types. > + * then, we figure out memory constraints and populate the list of > + * would-be memseg lists. then, we go ahead and allocate the > memseg > + * lists. > + */ > + > + /* create space for mem types */ > + n_memtypes =3D internal_config.num_hugepage_sizes * > rte_socket_count(); > + memtypes =3D calloc(n_memtypes, sizeof(*memtypes)); > + if (memtypes =3D=3D NULL) { > + RTE_LOG(ERR, EAL, "Cannot allocate space for memory > types\n"); > + return -1; > + } > + > + /* populate mem types */ > + cur_type =3D 0; > + for (hpi_idx =3D 0; hpi_idx < (int) internal_config.num_hugepage_sizes; > + hpi_idx++) { > + struct hugepage_info *hpi; > + uint64_t hugepage_sz; > + > + hpi =3D &internal_config.hugepage_info[hpi_idx]; > + hugepage_sz =3D hpi->hugepage_sz; > + > + for (i =3D 0; i < (int) rte_socket_count(); i++, cur_type++) { > + int socket_id =3D rte_socket_id_by_idx(i); > + > + memtypes[cur_type].page_sz =3D hugepage_sz; > + memtypes[cur_type].socket_id =3D socket_id; > + > + RTE_LOG(DEBUG, EAL, "Detected memory type: " > + "socket_id:%u hugepage_sz:%" PRIu64 "\n", > + socket_id, hugepage_sz); > + } > + } > + /* number of memtypes could have been lower due to no NUMA > support */ > + n_memtypes =3D cur_type; > + > + /* set up limits for types */ > + max_mem =3D (uint64_t)RTE_MAX_MEM_MB << 20; > + max_mem_per_type =3D > RTE_MIN((uint64_t)RTE_MAX_MEM_MB_PER_TYPE << 20, > + max_mem / n_memtypes); > + > + /* > + * limit maximum number of segment lists per type to ensure there's > + * space for memseg lists for all NUMA nodes with all page sizes > + */ > + max_seglists_per_type =3D RTE_MAX_MEMSEG_LISTS / n_memtypes; > + > + if (max_seglists_per_type =3D=3D 0) { > + RTE_LOG(ERR, EAL, "Cannot accommodate all memory types, > please increase %s\n", > + RTE_STR(CONFIG_RTE_MAX_MEMSEG_LISTS)); > + goto out; > + } > + > + /* go through all mem types and create segment lists */ > + msl_idx =3D 0; > + for (cur_type =3D 0; cur_type < n_memtypes; cur_type++) { > + unsigned int cur_seglist, n_seglists, n_segs; > + unsigned int max_segs_per_type, max_segs_per_list; > + struct memtype *type =3D &memtypes[cur_type]; > + uint64_t max_mem_per_list, pagesz; > + int socket_id; > + > + pagesz =3D type->page_sz; > + socket_id =3D type->socket_id; > + > + /* > + * we need to create segment lists for this type. we must > take > + * into account the following things: > + * > + * 1. total amount of memory we can use for this memory > type > + * 2. total amount of memory per memseg list allowed > + * 3. number of segments needed to fit the amount of > memory > + * 4. number of segments allowed per type > + * 5. number of segments allowed per memseg list > + * 6. number of memseg lists we are allowed to take up > + */ > + > + /* calculate how much segments we will need in total */ > + max_segs_per_type =3D max_mem_per_type / pagesz; > + /* limit number of segments to maximum allowed per type > */ > + max_segs_per_type =3D RTE_MIN(max_segs_per_type, > + (unsigned > int)RTE_MAX_MEMSEG_PER_TYPE); > + /* limit number of segments to maximum allowed per list */ > + max_segs_per_list =3D RTE_MIN(max_segs_per_type, > + (unsigned > int)RTE_MAX_MEMSEG_PER_LIST); > + > + /* calculate how much memory we can have per segment list > */ > + max_mem_per_list =3D RTE_MIN(max_segs_per_list * pagesz, > + (uint64_t)RTE_MAX_MEM_MB_PER_LIST << > 20); > + > + /* calculate how many segments each segment list will have > */ > + n_segs =3D RTE_MIN(max_segs_per_list, max_mem_per_list / > pagesz); > + > + /* calculate how many segment lists we can have */ > + n_seglists =3D RTE_MIN(max_segs_per_type / n_segs, > + max_mem_per_type / max_mem_per_list); > + > + /* limit number of segment lists according to our maximum > */ > + n_seglists =3D RTE_MIN(n_seglists, max_seglists_per_type); > + > + RTE_LOG(DEBUG, EAL, "Creating %i segment lists: " > + "n_segs:%i socket_id:%i hugepage_sz:%" > PRIu64 "\n", > + n_seglists, n_segs, socket_id, pagesz); > + > + /* create all segment lists */ > + for (cur_seglist =3D 0; cur_seglist < n_seglists; cur_seglist++) { > + if (msl_idx >=3D RTE_MAX_MEMSEG_LISTS) { > + RTE_LOG(ERR, EAL, > + "No more space in memseg lists, > please increase %s\n", > + > RTE_STR(CONFIG_RTE_MAX_MEMSEG_LISTS)); > + goto out; > + } > + msl =3D &mcfg->memsegs[msl_idx++]; > + > + if (memseg_list_init(msl, pagesz, n_segs, > + socket_id, cur_seglist)) > + goto out; > + > + if (memseg_list_alloc(msl)) { > + RTE_LOG(ERR, EAL, "Cannot allocate VA > space for memseg list\n"); > + goto out; > + } > + } > + } > + /* we're successful */ > + ret =3D 0; > +out: > + free(memtypes); > + return ret; > +} > + > +static int > +memseg_secondary_init(void) > +{ > + EAL_LOG_NOT_IMPLEMENTED(); > + return -1; > +} > + > +int > +rte_eal_memseg_init(void) > +{ > + if (rte_eal_process_type() =3D=3D RTE_PROC_PRIMARY) > + return memseg_primary_init(); > + return memseg_secondary_init(); > +} > + > +static inline uint64_t > +get_socket_mem_size(int socket) > +{ > + uint64_t size =3D 0; > + unsigned int i; > + > + for (i =3D 0; i < internal_config.num_hugepage_sizes; i++) { > + struct hugepage_info *hpi =3D > &internal_config.hugepage_info[i]; > + size +=3D hpi->hugepage_sz * hpi->num_pages[socket]; > + } > + > + return size; > +} > + > +static int > +calc_num_pages_per_socket(uint64_t *memory, > + struct hugepage_info *hp_info, > + struct hugepage_info *hp_used, > + unsigned int num_hp_info) > +{ > + unsigned int socket, j, i =3D 0; > + unsigned int requested, available; > + int total_num_pages =3D 0; > + uint64_t remaining_mem, cur_mem; > + uint64_t total_mem =3D internal_config.memory; > + > + if (num_hp_info =3D=3D 0) > + return -1; > + > + /* if specific memory amounts per socket weren't requested */ > + if (internal_config.force_sockets =3D=3D 0) { > + size_t total_size; > + int cpu_per_socket[RTE_MAX_NUMA_NODES]; > + size_t default_size; > + unsigned int lcore_id; > + > + /* Compute number of cores per socket */ > + memset(cpu_per_socket, 0, sizeof(cpu_per_socket)); > + RTE_LCORE_FOREACH(lcore_id) { > + > cpu_per_socket[rte_lcore_to_socket_id(lcore_id)]++; > + } > + > + /* > + * Automatically spread requested memory amongst > detected > + * sockets according to number of cores from cpu mask > present > + * on each socket. > + */ > + total_size =3D internal_config.memory; > + for (socket =3D 0; socket < RTE_MAX_NUMA_NODES && > total_size !=3D 0; > + socket++) { > + > + /* Set memory amount per socket */ > + default_size =3D internal_config.memory * > + cpu_per_socket[socket] / rte_lcore_count(); > + > + /* Limit to maximum available memory on socket */ > + default_size =3D RTE_MIN( > + default_size, > get_socket_mem_size(socket)); > + > + /* Update sizes */ > + memory[socket] =3D default_size; > + total_size -=3D default_size; > + } > + > + /* > + * If some memory is remaining, try to allocate it by getting > + * all available memory from sockets, one after the other. > + */ > + for (socket =3D 0; socket < RTE_MAX_NUMA_NODES && > total_size !=3D 0; > + socket++) { > + /* take whatever is available */ > + default_size =3D RTE_MIN( > + get_socket_mem_size(socket) - > memory[socket], > + total_size); > + > + /* Update sizes */ > + memory[socket] +=3D default_size; > + total_size -=3D default_size; > + } > + } > + > + for (socket =3D 0; socket < RTE_MAX_NUMA_NODES && total_mem !=3D > 0; > + socket++) { > + /* skips if the memory on specific socket wasn't requested */ > + for (i =3D 0; i < num_hp_info && memory[socket] !=3D 0; i++) { > + strncpy(hp_used[i].hugedir, hp_info[i].hugedir, > + sizeof(hp_used[i].hugedir)); > + hp_used[i].num_pages[socket] =3D RTE_MIN( > + memory[socket] / > hp_info[i].hugepage_sz, > + hp_info[i].num_pages[socket]); > + > + cur_mem =3D hp_used[i].num_pages[socket] * > + hp_used[i].hugepage_sz; > + > + memory[socket] -=3D cur_mem; > + total_mem -=3D cur_mem; > + > + total_num_pages +=3D > hp_used[i].num_pages[socket]; > + > + /* check if we have met all memory requests */ > + if (memory[socket] =3D=3D 0) > + break; > + > + /* Check if we have any more pages left at this size, > + * if so, move on to next size. > + */ > + if (hp_used[i].num_pages[socket] =3D=3D > + hp_info[i].num_pages[socket]) > + continue; > + > + /* At this point we know that there are more pages > + * available that are bigger than the memory we > want, > + * so lets see if we can get enough from other page > + * sizes. > + */ > + remaining_mem =3D 0; > + for (j =3D i+1; j < num_hp_info; j++) > + remaining_mem +=3D hp_info[j].hugepage_sz > * > + hp_info[j].num_pages[socket]; > + > + /* Is there enough other memory? > + * If not, allocate another page and quit. > + */ > + if (remaining_mem < memory[socket]) { > + cur_mem =3D RTE_MIN( > + memory[socket], > hp_info[i].hugepage_sz); > + memory[socket] -=3D cur_mem; > + total_mem -=3D cur_mem; > + hp_used[i].num_pages[socket]++; > + total_num_pages++; > + break; /* we are done with this socket*/ > + } > + } > + /* if we didn't satisfy all memory requirements per socket */ > + if (memory[socket] > 0 && > + internal_config.socket_mem[socket] !=3D 0) { > + /* to prevent icc errors */ > + requested =3D (unsigned int)( > + internal_config.socket_mem[socket] / > 0x100000); > + available =3D requested - > + ((unsigned int)(memory[socket] / > 0x100000)); > + RTE_LOG(ERR, EAL, "Not enough memory available > on " > + "socket %u! Requested: %uMB, available: > %uMB\n", > + socket, requested, available); > + return -1; > + } > + } > + > + /* if we didn't satisfy total memory requirements */ > + if (total_mem > 0) { > + requested =3D (unsigned int) (internal_config.memory / > 0x100000); > + available =3D requested - (unsigned int) (total_mem / > 0x100000); > + RTE_LOG(ERR, EAL, "Not enough memory available! " > + "Requested: %uMB, available: %uMB\n", > + requested, available); > + return -1; > + } > + return total_num_pages; > +} > + > +/* Limit is checked by validator itself, nothing left to analyze.*/ > +static int > +limits_callback(int socket_id, size_t cur_limit, size_t new_len) > +{ > + RTE_SET_USED(socket_id); > + RTE_SET_USED(cur_limit); > + RTE_SET_USED(new_len); > + return -1; > +} > + > +static int > +eal_hugepage_init(void) > +{ > + struct hugepage_info used_hp[MAX_HUGEPAGE_SIZES]; > + uint64_t memory[RTE_MAX_NUMA_NODES]; > + int hp_sz_idx, socket_id; > + > + memset(used_hp, 0, sizeof(used_hp)); > + > + for (hp_sz_idx =3D 0; > + hp_sz_idx < (int) > internal_config.num_hugepage_sizes; > + hp_sz_idx++) { > + /* also initialize used_hp hugepage sizes in used_hp */ > + struct hugepage_info *hpi; > + hpi =3D &internal_config.hugepage_info[hp_sz_idx]; > + used_hp[hp_sz_idx].hugepage_sz =3D hpi->hugepage_sz; > + } > + > + /* make a copy of socket_mem, needed for balanced allocation. */ > + for (socket_id =3D 0; socket_id < RTE_MAX_NUMA_NODES; > socket_id++) > + memory[socket_id] =3D > internal_config.socket_mem[socket_id]; > + > + /* calculate final number of pages */ > + if (calc_num_pages_per_socket(memory, > + internal_config.hugepage_info, used_hp, > + internal_config.num_hugepage_sizes) < 0) > + return -1; > + > + for (hp_sz_idx =3D 0; > + hp_sz_idx < > (int)internal_config.num_hugepage_sizes; > + hp_sz_idx++) { > + for (socket_id =3D 0; socket_id < RTE_MAX_NUMA_NODES; > + socket_id++) { > + struct rte_memseg **pages; > + struct hugepage_info *hpi =3D &used_hp[hp_sz_idx]; > + unsigned int num_pages =3D hpi- > >num_pages[socket_id]; > + unsigned int num_pages_alloc; > + > + if (num_pages =3D=3D 0) > + continue; > + > + RTE_LOG(DEBUG, EAL, > + "Allocating %u pages of size %" PRIu64 "M on > socket %i\n", > + num_pages, hpi->hugepage_sz >> 20, > socket_id); > + > + /* we may not be able to allocate all pages in one go, > + * because we break up our memory map into > multiple > + * memseg lists. therefore, try allocating multiple > + * times and see if we can get the desired number of > + * pages from multiple allocations. > + */ > + > + num_pages_alloc =3D 0; > + do { > + int i, cur_pages, needed; > + > + needed =3D num_pages - num_pages_alloc; > + > + pages =3D malloc(sizeof(*pages) * needed); > + > + /* do not request exact number of pages */ > + cur_pages =3D > eal_memalloc_alloc_seg_bulk(pages, > + needed, hpi->hugepage_sz, > + socket_id, false); > + if (cur_pages <=3D 0) { > + free(pages); > + return -1; > + } > + > + /* mark preallocated pages as unfreeable */ > + for (i =3D 0; i < cur_pages; i++) { > + struct rte_memseg *ms =3D pages[i]; > + ms->flags |=3D > + > RTE_MEMSEG_FLAG_DO_NOT_FREE; > + } > + free(pages); > + > + num_pages_alloc +=3D cur_pages; > + } while (num_pages_alloc !=3D num_pages); > + } > + } > + /* if socket limits were specified, set them */ > + if (internal_config.force_socket_limits) { > + unsigned int i; > + for (i =3D 0; i < RTE_MAX_NUMA_NODES; i++) { > + uint64_t limit =3D internal_config.socket_limit[i]; > + if (limit =3D=3D 0) > + continue; > + if (rte_mem_alloc_validator_register("socket-limit", > + limits_callback, i, limit)) > + RTE_LOG(ERR, EAL, "Failed to register socket > " > + "limits validator callback\n"); > + } > + } > + return 0; > +} > + > +static int > +eal_nohuge_init(void) > +{ > + struct rte_mem_config *mcfg; > + struct rte_memseg_list *msl; > + int n_segs, cur_seg; > + uint64_t page_sz; > + void *addr; > + struct rte_fbarray *arr; > + struct rte_memseg *ms; > + > + mcfg =3D rte_eal_get_configuration()->mem_config; > + > + /* nohuge mode is legacy mode */ > + internal_config.legacy_mem =3D 1; > + > + /* create a memseg list */ > + msl =3D &mcfg->memsegs[0]; > + > + page_sz =3D RTE_PGSIZE_4K; > + n_segs =3D internal_config.memory / page_sz; > + > + if (rte_fbarray_init(&msl->memseg_arr, "nohugemem", n_segs, > + sizeof(struct rte_memseg))) { > + RTE_LOG(ERR, EAL, "Cannot allocate memseg list\n"); > + return -1; > + } > + > + addr =3D eal_mem_alloc(internal_config.memory, 0); > + if (addr =3D=3D NULL) { > + RTE_LOG(ERR, EAL, "Cannot allocate %zu bytes", > + internal_config.memory); > + return -1; > + } > + > + msl->base_va =3D addr; > + msl->page_sz =3D page_sz; > + msl->socket_id =3D 0; > + msl->len =3D internal_config.memory; > + msl->heap =3D 1; > + > + /* populate memsegs. each memseg is one page long */ > + for (cur_seg =3D 0; cur_seg < n_segs; cur_seg++) { > + arr =3D &msl->memseg_arr; > + > + ms =3D rte_fbarray_get(arr, cur_seg); > + ms->iova =3D RTE_BAD_IOVA; > + ms->addr =3D addr; > + ms->hugepage_sz =3D page_sz; > + ms->socket_id =3D 0; > + ms->len =3D page_sz; > + > + rte_fbarray_set_used(arr, cur_seg); > + > + addr =3D RTE_PTR_ADD(addr, (size_t)page_sz); > + } > + > + if (mcfg->dma_maskbits && > + rte_mem_check_dma_mask_thread_unsafe(mcfg- > >dma_maskbits)) { > + RTE_LOG(ERR, EAL, > + "%s(): couldn't allocate memory due to IOVA " > + "exceeding limits of current DMA mask.\n", > __func__); > + return -1; > + } > + > + return 0; > +} > + > +int > +rte_eal_hugepage_init(void) > +{ > + return internal_config.no_hugetlbfs ? > + eal_nohuge_init() : eal_hugepage_init(); > +} > + > +int > +rte_eal_hugepage_attach(void) > +{ > + EAL_LOG_NOT_IMPLEMENTED(); > + return -1; > +} > diff --git a/lib/librte_eal/windows/eal_mp.c > b/lib/librte_eal/windows/eal_mp.c > new file mode 100644 > index 000000000..16a5e8ba0 > --- /dev/null > +++ b/lib/librte_eal/windows/eal_mp.c > @@ -0,0 +1,103 @@ > +/* SPDX-License-Identifier: BSD-3-Clause > + * Copyright (c) 2020 Dmitry Kozlyuk > + */ > + > +/** > + * @file Multiprocess support stubs > + * > + * Stubs must log an error until implemented. If success is required > + * for non-multiprocess operation, stub must log a warning and a comment > + * must document what requires success emulation. > + */ > + > +#include > +#include > + > +#include "eal_private.h" > +#include "eal_windows.h" > +#include "malloc_mp.h" > + > +void > +rte_mp_channel_cleanup(void) > +{ > + EAL_LOG_NOT_IMPLEMENTED(); > +} > + > +int > +rte_mp_action_register(const char *name, rte_mp_t action) > +{ > + RTE_SET_USED(name); > + RTE_SET_USED(action); > + EAL_LOG_NOT_IMPLEMENTED(); > + return -1; > +} > + > +void > +rte_mp_action_unregister(const char *name) > +{ > + RTE_SET_USED(name); > + EAL_LOG_NOT_IMPLEMENTED(); > +} > + > +int > +rte_mp_sendmsg(struct rte_mp_msg *msg) > +{ > + RTE_SET_USED(msg); > + EAL_LOG_NOT_IMPLEMENTED(); > + return -1; > +} > + > +int > +rte_mp_request_sync(struct rte_mp_msg *req, struct rte_mp_reply > *reply, > + const struct timespec *ts) > +{ > + RTE_SET_USED(req); > + RTE_SET_USED(reply); > + RTE_SET_USED(ts); > + EAL_LOG_NOT_IMPLEMENTED(); > + return -1; > +} > + > +int > +rte_mp_request_async(struct rte_mp_msg *req, const struct timespec *ts, > + rte_mp_async_reply_t clb) > +{ > + RTE_SET_USED(req); > + RTE_SET_USED(ts); > + RTE_SET_USED(clb); > + EAL_LOG_NOT_IMPLEMENTED(); > + return -1; > +} > + > +int > +rte_mp_reply(struct rte_mp_msg *msg, const char *peer) > +{ > + RTE_SET_USED(msg); > + RTE_SET_USED(peer); > + EAL_LOG_NOT_IMPLEMENTED(); > + return -1; > +} > + > +int > +register_mp_requests(void) > +{ > + /* Non-stub function succeeds if multi-process is not supported. */ > + EAL_LOG_STUB(); > + return 0; > +} > + > +int > +request_to_primary(struct malloc_mp_req *req) > +{ > + RTE_SET_USED(req); > + EAL_LOG_NOT_IMPLEMENTED(); > + return -1; > +} > + > +int > +request_sync(void) > +{ > + /* Common memory allocator depends on this function success. */ > + EAL_LOG_STUB(); > + return 0; > +} > diff --git a/lib/librte_eal/windows/eal_windows.h > b/lib/librte_eal/windows/eal_windows.h > index 390d2fd66..9735f0293 100644 > --- a/lib/librte_eal/windows/eal_windows.h > +++ b/lib/librte_eal/windows/eal_windows.h > @@ -9,8 +9,24 @@ > * @file Facilities private to Windows EAL > */ >=20 > +#include > #include >=20 > +/** > + * Log current function as not implemented and set rte_errno. > + */ > +#define EAL_LOG_NOT_IMPLEMENTED() \ > + do { \ > + RTE_LOG(DEBUG, EAL, "%s() is not implemented\n", > __func__); \ > + rte_errno =3D ENOTSUP; \ > + } while (0) > + > +/** > + * Log current function as a stub. > + */ > +#define EAL_LOG_STUB() \ > + RTE_LOG(DEBUG, EAL, "Windows: %s() is a stub\n", __func__) > + > /** > * Create a map of processors and cores on the system. > */ > @@ -36,4 +52,78 @@ int eal_thread_create(pthread_t *thread); > */ > unsigned int eal_socket_numa_node(unsigned int socket_id); >=20 > +/** > + * Open virt2phys driver interface device. > + * > + * @return 0 on success, (-1) on failure. > + */ > +int eal_mem_virt2iova_init(void); > + > +/** > + * Locate Win32 memory management routines in system libraries. > + * > + * @return 0 on success, (-1) on failure. > + */ > +int eal_mem_win32api_init(void); > + > +/** > + * Allocate a contiguous chunk of virtual memory. > + * > + * Use eal_mem_free() to free allocated memory. > + * > + * @param size > + * Number of bytes to allocate. > + * @param page_size > + * If non-zero, means memory must be allocated in hugepages > + * of the specified size. The *size* parameter must then be > + * a multiple of the largest hugepage size requested. > + * @return > + * Address of allocated memory, NULL on failure and rte_errno is set. > + */ > +void *eal_mem_alloc(size_t size, size_t page_size); > + > +/** > + * Allocate new memory in hugepages on the specified NUMA node. > + * > + * @param size > + * Number of bytes to allocate. Must be a multiple of huge page size. > + * @param socket_id > + * Socket ID. > + * @return > + * Address of the memory allocated on success or NULL on failure. > + */ > +void *eal_mem_alloc_socket(size_t size, int socket_id); > + > +/** > + * Commit memory previously reserved with eal_mem_reserve() > + * or decommitted from hugepages by eal_mem_decommit(). > + * > + * @param requested_addr > + * Address within a reserved region. Must not be NULL. > + * @param size > + * Number of bytes to commit. Must be a multiple of page size. > + * @param socket_id > + * Socket ID to allocate on. Can be SOCKET_ID_ANY. > + * @return > + * On success, address of the committed memory, that is, requested_addr= . > + * On failure, NULL and rte_errno is set. > + */ > +void *eal_mem_commit(void *requested_addr, size_t size, int socket_id); > + > +/** > + * Put allocated or committed memory back into reserved state. > + * > + * @param addr > + * Address of the region to decommit. > + * @param size > + * Number of bytes to decommit. > + * > + * The *addr* and *size* must match location and size > + * of a previously allocated or committed region. > + * > + * @return > + * 0 on success, (-1) on failure. > + */ > +int eal_mem_decommit(void *addr, size_t size); > + > #endif /* _EAL_WINDOWS_H_ */ > diff --git a/lib/librte_eal/windows/include/meson.build > b/lib/librte_eal/windows/include/meson.build > index 5fb1962ac..b3534b025 100644 > --- a/lib/librte_eal/windows/include/meson.build > +++ b/lib/librte_eal/windows/include/meson.build > @@ -5,5 +5,6 @@ includes +=3D include_directories('.') >=20 > headers +=3D files( > 'rte_os.h', > + 'rte_virt2phys.h', > 'rte_windows.h', > ) > diff --git a/lib/librte_eal/windows/include/rte_os.h > b/lib/librte_eal/windows/include/rte_os.h > index 510e39e03..62805a307 100644 > --- a/lib/librte_eal/windows/include/rte_os.h > +++ b/lib/librte_eal/windows/include/rte_os.h > @@ -36,6 +36,10 @@ extern "C" { >=20 > #define strncasecmp(s1, s2, count) _strnicmp(s1, s2, count) >=20 > +#define open _open > +#define close _close > +#define unlink _unlink > + > /* cpu_set macros implementation */ > #define RTE_CPU_AND(dst, src1, src2) CPU_AND(dst, src1, src2) > #define RTE_CPU_OR(dst, src1, src2) CPU_OR(dst, src1, src2) > diff --git a/lib/librte_eal/windows/include/rte_virt2phys.h > b/lib/librte_eal/windows/include/rte_virt2phys.h > new file mode 100644 > index 000000000..4bb2b4aaf > --- /dev/null > +++ b/lib/librte_eal/windows/include/rte_virt2phys.h > @@ -0,0 +1,34 @@ > +/* SPDX-License-Identifier: BSD-3-Clause > + * Copyright (c) 2020 Dmitry Kozlyuk > + */ > + > +/** > + * @file virt2phys driver interface > + */ > + > +/** > + * Driver device interface GUID {539c2135-793a-4926-afec-d3a1b61bbc8a}. > + */ > +DEFINE_GUID(GUID_DEVINTERFACE_VIRT2PHYS, > + 0x539c2135, 0x793a, 0x4926, > + 0xaf, 0xec, 0xd3, 0xa1, 0xb6, 0x1b, 0xbc, 0x8a); > + > +/** > + * Driver device type for IO control codes. > + */ > +#define VIRT2PHYS_DEVTYPE 0x8000 > + > +/** > + * Translate a valid non-paged virtual address to a physical address. > + * > + * Note: A physical address zero (0) is reported if input address > + * is paged out or not mapped. However, if input is a valid mapping > + * of I/O port 0x0000, output is also zero. There is no way > + * to distinguish between these cases by return value only. > + * > + * Input: a non-paged virtual address (PVOID). > + * > + * Output: the corresponding physical address (LARGE_INTEGER). > + */ > +#define IOCTL_VIRT2PHYS_TRANSLATE CTL_CODE( \ > + VIRT2PHYS_DEVTYPE, 0x800, METHOD_BUFFERED, > FILE_ANY_ACCESS) > diff --git a/lib/librte_eal/windows/include/rte_windows.h > b/lib/librte_eal/windows/include/rte_windows.h > index ed6e4c148..899ed7d87 100644 > --- a/lib/librte_eal/windows/include/rte_windows.h > +++ b/lib/librte_eal/windows/include/rte_windows.h > @@ -23,6 +23,8 @@ >=20 > #include > #include > +#include > +#include >=20 > /* Have GUIDs defined. */ > #ifndef INITGUID > diff --git a/lib/librte_eal/windows/include/unistd.h > b/lib/librte_eal/windows/include/unistd.h > index 757b7f3c5..6b33005b2 100644 > --- a/lib/librte_eal/windows/include/unistd.h > +++ b/lib/librte_eal/windows/include/unistd.h > @@ -9,4 +9,7 @@ > * as Microsoft libc does not contain unistd.h. This may be removed > * in future releases. > */ > + > +#include > + > #endif /* _UNISTD_H_ */ > diff --git a/lib/librte_eal/windows/meson.build > b/lib/librte_eal/windows/meson.build > index 5f118bfe2..0bd56cd8f 100644 > --- a/lib/librte_eal/windows/meson.build > +++ b/lib/librte_eal/windows/meson.build > @@ -8,6 +8,11 @@ sources +=3D files( > 'eal_debug.c', > 'eal_hugepages.c', > 'eal_lcore.c', > + 'eal_memalloc.c', > + 'eal_memory.c', > + 'eal_mp.c', > 'eal_thread.c', > 'getopt.c', > ) > + > +dpdk_conf.set10('RTE_EAL_NUMA_AWARE_HUGEPAGES', true) > -- > 2.25.1