From d1826aafda646361fa0214d8e122dd545391db1e Mon Sep 17 00:00:00 2001 From: Joyee Cheung Date: Tue, 18 Aug 2026 18:28:43 +0200 Subject: [PATCH] build,src: make --use-largepages a no-op This feature has not been actively used in the wild and has always only been best-effort on systems that support it. The build changes it needs breaks WSL1 compatibility and the relocation mechanism won't work with newer V8 that remaps builtins using mremap(MREMAP_DONTUNMAP). This patch effectively removes this feature by turning the flags into no-ops. A warning will be printed if `--use-largepages=on` is used. Signed-off-by: Joyee Cheung --- LICENSE | 23 -- configure.py | 10 +- doc/api/cli.md | 18 +- doc/node-config-schema.json | 2 +- doc/node.1 | 17 +- node.gyp | 33 -- src/debug_utils.h | 1 - src/large_pages/node_large_page.cc | 464 ---------------------- src/large_pages/node_large_page.h | 34 -- src/large_pages/node_text_start.S | 29 -- src/node.cc | 10 +- src/node.h | 3 +- src/node_options.cc | 7 +- test/parallel/test-startup-large-pages.js | 45 ++- tools/license-builder.sh | 4 - 15 files changed, 48 insertions(+), 652 deletions(-) delete mode 100644 src/large_pages/node_large_page.cc delete mode 100644 src/large_pages/node_large_page.h delete mode 100644 src/large_pages/node_text_start.S diff --git a/LICENSE b/LICENSE index 9cc3315dd388..67cd2feb69a9 100644 --- a/LICENSE +++ b/LICENSE @@ -2600,29 +2600,6 @@ The externally maintained libraries used by Node.js are: WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. """ -- large_pages, located at src/large_pages, is licensed as follows: - """ - Copyright (C) 2018 Intel Corporation - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom - the Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included - in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL - THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES - OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE - OR OTHER DEALINGS IN THE SOFTWARE. - """ - - caja, located at lib/internal/freeze_intrinsics.js, is licensed as follows: """ Adapted from SES/Caja - Copyright (C) 2011 Google Inc. diff --git a/configure.py b/configure.py index 3f4f9984d5a8..33074585c09c 100755 --- a/configure.py +++ b/configure.py @@ -884,13 +884,13 @@ action='store_true', dest='node_use_large_pages', default=None, - help='This option has no effect. --use-largepages is now a runtime option.') + help='This option is no longer supported and a no-op.') parser.add_argument('--use-largepages-script-lld', action='store_true', dest='node_use_large_pages_script_lld', default=None, - help='This option has no effect. --use-largepages is now a runtime option.') + help='This option is no longer supported and a no-op.') parser.add_argument('--use-section-ordering-file', action='store', @@ -2047,10 +2047,8 @@ def configure_node(o): if options.node_use_large_pages or options.node_use_large_pages_script_lld: warn('''The `--use-largepages` and `--use-largepages-script-lld` options - have no effect during build time. Support for mapping to large pages is - now a runtime option of Node.js. Run `node --use-largepages` or add - `--use-largepages` to the `NODE_OPTIONS` environment variable once - Node.js is built to enable mapping to large pages.''') + have no effect. Mapping the Node.js static code to large pages is + no longer supported.''') if options.no_ifaddrs: o['defines'] += ['SUNOS_NO_IFADDRS'] diff --git a/doc/api/cli.md b/doc/api/cli.md index 514af04c02cd..7b5825ff1332 100644 --- a/doc/api/cli.md +++ b/doc/api/cli.md @@ -3486,19 +3486,21 @@ When both are set, `--use-env-proxy` takes precedence. added: - v13.6.0 - v12.17.0 +changes: + - version: REPLACEME + pr-url: https://github.com/nodejs/node/pull/65389 + description: This option is now a no-op. --> -Re-map the Node.js static code to large memory pages at startup. If supported on -the target system, this will cause the Node.js static code to be moved onto 2 -MiB pages instead of 4 KiB pages. +This option is no longer supported and a no-op. It used to re-map the Node.js +static code to large memory pages at startup. -The following values are valid for `mode`: +It still accepts the following values for compatibility: * `off`: No mapping will be attempted. This is the default. -* `on`: If supported by the OS, mapping will be attempted. Failure to map will - be ignored and a message will be printed to standard error. -* `silent`: If supported by the OS, mapping will be attempted. Failure to map - will be ignored and will not be reported. +* `on`: No mapping will be attempted and a message will be printed to + standard error stating it's no longer supported. +* `silent`: Same as `off`. ### `--use-system-ca` diff --git a/doc/node-config-schema.json b/doc/node-config-schema.json index df75fc3cf37a..4618a5f17df1 100644 --- a/doc/node-config-schema.json +++ b/doc/node-config-schema.json @@ -754,7 +754,7 @@ }, "use-largepages": { "type": "string", - "description": "Map the Node.js static code to large pages. Options are 'off' (the default value, meaning do not map), 'on' (map and ignore failure, reporting it to stderr), or 'silent' (map and silently ignore failure)" + "description": "This option is no longer supported and a no-op. Options are 'off' (default), 'on' (report a warning to stderr), or 'silent' (same as 'off')." }, "use-openssl-ca": { "type": "boolean", diff --git a/doc/node.1 b/doc/node.1 index dd541051de28..29e18663d52d 100644 --- a/doc/node.1 +++ b/doc/node.1 @@ -1691,20 +1691,9 @@ This is equivalent to setting the \fBNODE_USE_ENV_PROXY=1\fR environment variabl When both are set, \fB--use-env-proxy\fR takes precedence. . .It Fl -use-largepages Ns = Ns Ar mode -Re-map the Node.js static code to large memory pages at startup. If supported on -the target system, this will cause the Node.js static code to be moved onto 2 -MiB pages instead of 4 KiB pages. -The following values are valid for \fBmode\fR: -.Bl -bullet -.It -\fBoff\fR: No mapping will be attempted. This is the default. -.It -\fBon\fR: If supported by the OS, mapping will be attempted. Failure to map will -be ignored and a message will be printed to standard error. -.It -\fBsilent\fR: If supported by the OS, mapping will be attempted. Failure to map -will be ignored and will not be reported. -.El +This option is no longer supported and a no-op. It still accepts +\fBoff\fR (the default), \fBon\fR and \fBsilent\fR as values for compatibility. +Passing \fBon\fR as the value prints a warning to standard error. . .It Fl -use-system-ca Node.js uses the trusted CA certificates present in the system store along with diff --git a/node.gyp b/node.gyp index 4f7a3d1ff634..b99755575020 100644 --- a/node.gyp +++ b/node.gyp @@ -235,8 +235,6 @@ 'src/histogram-inl.h', 'src/js_stream.h', 'src/json_utils.h', - 'src/large_pages/node_large_page.cc', - 'src/large_pages/node_large_page.h', 'src/memory_tracker.h', 'src/memory_tracker-inl.h', 'src/module_wrap.h', @@ -503,11 +501,6 @@ 'node_mksnapshot_exec': '<(PRODUCT_DIR)/<(EXECUTABLE_PREFIX)node_mksnapshot<(EXECUTABLE_SUFFIX)', 'node_js2c_exec': '<(PRODUCT_DIR)/<(EXECUTABLE_PREFIX)node_js2c<(EXECUTABLE_SUFFIX)', 'conditions': [ - ['GENERATOR == "ninja"', { - 'node_text_start_object_path': 'src/large_pages/node_text_start.node_text_start.o' - }, { - 'node_text_start_object_path': 'node_text_start/src/large_pages/node_text_start.o' - }], [ 'node_shared=="true"', { 'node_target_type%': 'shared_library', 'node_lib_type': 'shared_library', @@ -585,19 +578,6 @@ }, 'targets': [ - { - 'target_name': 'node_text_start', - 'type': 'none', - 'conditions': [ - [ 'OS in "linux freebsd solaris openharmony" and ' - 'target_arch=="x64"', { - 'type': 'static_library', - 'sources': [ - 'src/large_pages/node_text_start.S' - ] - }], - ] - }, { 'target_name': '<(node_core_target_name)', 'type': 'executable', @@ -769,14 +749,6 @@ }, }, }], - [ 'OS in "linux freebsd openharmony" and ' - 'target_arch=="x64"', { - 'dependencies': [ 'node_text_start' ], - 'ldflags+': [ - '<(obj_dir)/<(node_text_start_object_path)' - ] - }], - ['node_fipsinstall=="true"', { 'variables': { 'openssl-cli': '<(PRODUCT_DIR)/<(EXECUTABLE_PREFIX)openssl-cli<(EXECUTABLE_SUFFIX)', @@ -1013,11 +985,6 @@ 'HAVE_DTLS=1', ], }], - [ 'OS in "linux freebsd mac solaris openharmony" and ' - 'target_arch=="x64" and ' - 'node_target_type=="executable"', { - 'defines': [ 'NODE_ENABLE_LARGE_CODE_PAGES=1' ], - }], [ 'use_openssl_def==1', { # TODO(bnoordhuis) Make all platforms export the same list of symbols. # Teach mkssldef.py to generate linker maps that UNIX linkers understand. diff --git a/src/debug_utils.h b/src/debug_utils.h index 616f6c03e49a..f381e48547c1 100644 --- a/src/debug_utils.h +++ b/src/debug_utils.h @@ -49,7 +49,6 @@ void NODE_EXTERN_PRIVATE FWrite(FILE* file, const std::string& str); V(COMPILE_CACHE) \ V(CONTEXTIFY) \ V(DIAGNOSTICS) \ - V(HUGEPAGES) \ V(INSPECTOR_SERVER) \ V(INSPECTOR_CLIENT) \ V(INSPECTOR_PROFILER) \ diff --git a/src/large_pages/node_large_page.cc b/src/large_pages/node_large_page.cc deleted file mode 100644 index 43ebb7641a62..000000000000 --- a/src/large_pages/node_large_page.cc +++ /dev/null @@ -1,464 +0,0 @@ -// Copyright (C) 2018 Intel Corporation -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), -// to deal in the Software without restriction, including without limitation -// the rights to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons to whom -// the Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included -// in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL -// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES -// OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE -// OR OTHER DEALINGS IN THE SOFTWARE. -// -// SPDX-License-Identifier: MIT - -// The functions in this file map the .text section of Node.js into 2MB pages. -// They perform the following steps: -// -// 1: Find the Node.js binary's `.text` section in memory. This is done below in -// `FindNodeTextRegion`. It is accomplished in a platform-specific way. On -// Linux and FreeBSD, `dl_iterate_phdr(3)` is used. When the region is found, -// it is "trimmed" as follows: -// * Modify the start to point to the very beginning of the Node.js `.text` -// section (from symbol `__node_text_start` declared in node_text_start.S). -// * Possibly modify the end to account for the `lpstub` section which -// contains `MoveTextRegionToLargePages`, the function we do not wish to -// move (see below). -// * Align the address of the start to its nearest higher large page -// boundary. -// * Align the address of the end to its nearest lower large page boundary. -// -// 2: Move the text region to large pages. This is done below in -// `MoveTextRegionToLargePages`. We need to be very careful: -// a) `MoveTextRegionToLargePages` itself should not be moved. -// We use gcc attributes -// (__section__) to put it outside the `.text` section, -// (__aligned__) to align it at the 2M boundary, and -// (__noline__) to not inline this function. -// b) `MoveTextRegionToLargePages` should not call any function(s) that might -// be moved. -// To move the .text section, perform the following steps: -// * Map a new, temporary area and copy the original code there. -// * Use mmap using the start address with MAP_FIXED so we get exactly the -// same virtual address (except on macOS). On platforms other than Linux, -// use mmap flags to request hugepages. -// * On Linux use madvise with MADV_HUGEPAGE to use anonymous 2MB pages. -// * If successful copy the code to the newly mapped area and protect it to -// be readable and executable. -// * Unmap the temporary area. - -#include "node_large_page.h" - -#include // NOLINT(build/include) - -// Besides returning ENOTSUP at runtime we do nothing if this define is missing. -#if defined(NODE_ENABLE_LARGE_CODE_PAGES) && NODE_ENABLE_LARGE_CODE_PAGES -#include "debug_utils-inl.h" - -#if defined(__linux__) || defined(__FreeBSD__) -#if defined(__linux__) -#ifndef _GNU_SOURCE -#define _GNU_SOURCE -#endif // ifndef _GNU_SOURCE -#include -#if !defined(PR_SET_VMA) -#define PR_SET_VMA 0x53564d41 -#define PR_SET_VMA_ANON_NAME 0 -#endif -#elif defined(__FreeBSD__) -#include "uv.h" // uv_exepath -#endif // defined(__linux__) -#include -#endif // defined(__linux__) || defined(__FreeBSD__) - -#include -#include -#if defined(__FreeBSD__) -#include -#elif defined(__APPLE__) -#include -#endif - -#include // PATH_MAX -#include -#include -#include -#include -#include - -#if defined(__linux__) || defined(__FreeBSD__) -extern "C" { -// This symbol must be declared weak because this file becomes part of all -// Node.js targets (like node_mksnapshot, node_mkcodecache, and cctest) and -// those files do not supply the symbol. -extern char __attribute__((weak)) __node_text_start; -extern char __start_lpstub; -} // extern "C" -#endif // defined(__linux__) || defined(__FreeBSD__) - -#endif // defined(NODE_ENABLE_LARGE_CODE_PAGES) && NODE_ENABLE_LARGE_CODE_PAGES -namespace node { -#if defined(NODE_ENABLE_LARGE_CODE_PAGES) && NODE_ENABLE_LARGE_CODE_PAGES - -namespace { - -struct text_region { - char* from = nullptr; - char* to = nullptr; - bool found_text_region = false; -}; - -static const size_t hps = 2L * 1024 * 1024; - -template -inline void Debug(std::string fmt, Args&&... args) { - node::Debug(&per_process::enabled_debug_list, - DebugCategory::HUGEPAGES, - (std::string("Hugepages info: ") + fmt).c_str(), - std::forward(args)...); -} - -inline void PrintWarning(const char* warn) { - fprintf(stderr, "Hugepages WARNING: %s\n", warn); -} - -inline void PrintSystemError(int error) { - PrintWarning(strerror(error)); -} - -inline uintptr_t hugepage_align_up(uintptr_t addr) { - return (((addr) + (hps) - 1) & ~((hps) - 1)); -} - -inline uintptr_t hugepage_align_down(uintptr_t addr) { - return ((addr) & ~((hps) - 1)); -} - -#if defined(__linux__) || defined(__FreeBSD__) -#if defined(__FreeBSD__) -#ifndef ElfW -#define ElfW(name) Elf_##name -#endif // ifndef ElfW -#endif // defined(__FreeBSD__) - -struct dl_iterate_params { - uintptr_t start = 0; - uintptr_t end = 0; - uintptr_t reference_sym = reinterpret_cast(&__node_text_start); - std::string exename; -}; - -int FindMapping(struct dl_phdr_info* info, size_t, void* data) { - auto dl_params = static_cast(data); - if (dl_params->exename == std::string(info->dlpi_name)) { - for (int idx = 0; idx < info->dlpi_phnum; idx++) { - const ElfW(Phdr)* phdr = &info->dlpi_phdr[idx]; - if (phdr->p_type == PT_LOAD && (phdr->p_flags & PF_X)) { - uintptr_t start = info->dlpi_addr + phdr->p_vaddr; - uintptr_t end = start + phdr->p_memsz; - - if (dl_params->reference_sym >= start && - dl_params->reference_sym <= end) { - dl_params->start = start; - dl_params->end = end; - return 1; - } - } - } - } - return 0; -} -#endif // defined(__linux__) || defined(__FreeBSD__) - -struct text_region FindNodeTextRegion() { - struct text_region nregion; -#if defined(__linux__) || defined(__FreeBSD__) - dl_iterate_params dl_params; - uintptr_t lpstub_start = reinterpret_cast(&__start_lpstub); - -#if defined(__FreeBSD__) - // On FreeBSD we need the name of the binary, because `dl_iterate_phdr` does - // not pass in an empty string as the `dlpi_name` of the binary but rather its - // absolute path. - { - char selfexe[PATH_MAX]; - size_t count = sizeof(selfexe); - if (uv_exepath(selfexe, &count)) - return nregion; - dl_params.exename = std::string(selfexe, count); - } -#endif // defined(__FreeBSD__) - - if (dl_iterate_phdr(FindMapping, &dl_params) == 1) { - Debug("start: %p - sym: %p - end: %p\n", - reinterpret_cast(dl_params.start), - reinterpret_cast(dl_params.reference_sym), - reinterpret_cast(dl_params.end)); - - dl_params.start = dl_params.reference_sym; - if (lpstub_start > dl_params.start && lpstub_start <= dl_params.end) { - Debug("Trimming end for lpstub: %p\n", - reinterpret_cast(lpstub_start)); - dl_params.end = lpstub_start; - } - - if (dl_params.start < dl_params.end) { - char* from = reinterpret_cast(hugepage_align_up(dl_params.start)); - char* to = reinterpret_cast(hugepage_align_down(dl_params.end)); - Debug("Aligned range is %p - %p\n", from, to); - if (from < to) { - size_t pagecount = (to - from) / hps; - if (pagecount > 0) { - nregion.found_text_region = true; - nregion.from = from; - nregion.to = to; - } - } - } - } -#elif defined(__APPLE__) - struct vm_region_submap_info_64 map; - mach_msg_type_number_t count = VM_REGION_SUBMAP_INFO_COUNT_64; - vm_address_t addr = 0UL; - vm_size_t size = 0; - natural_t depth = 1; - - while (true) { - if (vm_region_recurse_64(mach_task_self(), &addr, &size, &depth, - reinterpret_cast(&map), - &count) != KERN_SUCCESS) { - break; - } - - if (map.is_submap) { - depth++; - } else { - char* start = reinterpret_cast(hugepage_align_up(addr)); - char* end = reinterpret_cast(hugepage_align_down(addr+size)); - - if (end > start && (map.protection & VM_PROT_READ) != 0 && - (map.protection & VM_PROT_EXECUTE) != 0) { - nregion.found_text_region = true; - nregion.from = start; - nregion.to = end; - break; - } - - addr += size; - size = 0; - } - } -#endif - Debug("Found %d huge pages\n", (nregion.to - nregion.from) / hps); - return nregion; -} - -#if defined(__linux__) -bool IsTransparentHugePagesEnabled() { - // File format reference: - // https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/mm/huge_memory.c?id=13391c60da3308ed9980de0168f74cce6c62ac1d#n163 - const char* filename = "/sys/kernel/mm/transparent_hugepage/enabled"; - std::ifstream config_stream(filename, std::ios::in); - if (!config_stream.good()) { - PrintWarning("could not open /sys/kernel/mm/transparent_hugepage/enabled"); - return false; - } - - std::string token; - config_stream >> token; - if ("[always]" == token) return true; - config_stream >> token; - if ("[madvise]" == token) return true; - return false; -} -#elif defined(__FreeBSD__) -bool IsSuperPagesEnabled() { - // It is enabled by default on amd64. - unsigned int super_pages = 0; - size_t super_pages_length = sizeof(super_pages); - return sysctlbyname("vm.pmap.pg_ps_enabled", - &super_pages, - &super_pages_length, - nullptr, - 0) != -1 && - super_pages >= 1; -} -#endif - -// Functions in this class must always be inlined because they must end up in -// the `lpstub` section rather than the `.text` section. -class MemoryMapPointer { - public: - FORCE_INLINE explicit MemoryMapPointer() {} - FORCE_INLINE bool operator==(void* rhs) const { return mem_ == rhs; } - FORCE_INLINE void* mem() const { return mem_; } - MemoryMapPointer(const MemoryMapPointer&) = delete; - MemoryMapPointer(MemoryMapPointer&&) = delete; - void operator= (const MemoryMapPointer&) = delete; - void operator= (const MemoryMapPointer&&) = delete; - FORCE_INLINE void Reset(void* start, - size_t size, - int prot, - int flags, - int fd = -1, - size_t offset = 0) { - mem_ = mmap(start, size, prot, flags, fd, offset); - size_ = size; - } - FORCE_INLINE void Reset() { - mem_ = nullptr; - size_ = 0; - } - static void SetName(void* mem, size_t size, const char* name) { -#if defined(__linux__) - // Available since the 5.17 kernel release and if the - // CONFIG_ANON_VMA_NAME option, we can set an identifier - // to an anonymous mapped region. However if the kernel - // option is not present or it s an older kernel, it is a no-op. - if (mem != MAP_FAILED && mem != nullptr) - prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, - reinterpret_cast(mem), - size, - reinterpret_cast(name)); -#else - (void)name; -#endif - } - FORCE_INLINE ~MemoryMapPointer() { - if (mem_ == nullptr) return; - if (mem_ == MAP_FAILED) return; - if (munmap(mem_, size_) == 0) return; - PrintSystemError(errno); - } - - private: - size_t size_ = 0; - void* mem_ = nullptr; -}; - -} // End of anonymous namespace - -int -#if !defined(__APPLE__) -__attribute__((__section__("lpstub"))) -#else -__attribute__((__section__("__TEXT,__lpstub"))) -#endif -__attribute__((__aligned__(hps))) -__attribute__((__noinline__)) -MoveTextRegionToLargePages(const text_region& r) { - MemoryMapPointer nmem; - MemoryMapPointer tmem; - void* start = r.from; - size_t size = r.to - r.from; - - // Allocate a temporary region and back up the code we will re-map. - nmem.Reset(nullptr, size, - PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS); - if (nmem.mem() == MAP_FAILED) goto fail; - memcpy(nmem.mem(), r.from, size); - -#if defined(__linux__) -// We already know the original page is r-xp -// (PROT_READ, PROT_EXEC, MAP_PRIVATE) -// We want PROT_WRITE because we are writing into it. -// We want it at the fixed address and we use MAP_FIXED. - tmem.Reset(start, size, - PROT_READ | PROT_WRITE | PROT_EXEC, - MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED); - if (tmem.mem() == MAP_FAILED) goto fail; - if (madvise(tmem.mem(), size, 14 /* MADV_HUGEPAGE */) == -1) goto fail; - memcpy(start, nmem.mem(), size); -#elif defined(__FreeBSD__) - tmem.Reset(start, size, - PROT_READ | PROT_WRITE | PROT_EXEC, - MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED | - MAP_ALIGNED_SUPER); - if (tmem.mem() == MAP_FAILED) goto fail; - memcpy(start, nmem.mem(), size); -#elif defined(__APPLE__) - // There is not enough room to reserve the mapping close - // to the region address so we content to give a hint - // without forcing the new address being closed to. - // We explicitally gives all permission since we plan - // to write into it. - tmem.Reset(start, size, - PROT_READ | PROT_WRITE | PROT_EXEC, - MAP_PRIVATE | MAP_ANONYMOUS, - VM_FLAGS_SUPERPAGE_SIZE_2MB); - if (tmem.mem() == MAP_FAILED) goto fail; - memcpy(tmem.mem(), nmem.mem(), size); - if (mprotect(start, size, PROT_READ | PROT_WRITE | PROT_EXEC) == -1) - goto fail; - memcpy(start, tmem.mem(), size); -#endif - - if (mprotect(start, size, PROT_READ | PROT_EXEC) == -1) goto fail; - MemoryMapPointer::SetName(start, size, "nodejs Large Page"); - - // We need not `munmap(tmem, size)` on success. - tmem.Reset(); - return 0; -fail: - PrintSystemError(errno); - return -1; -} -#endif // defined(NODE_ENABLE_LARGE_CODE_PAGES) && NODE_ENABLE_LARGE_CODE_PAGES - -// This is the primary API called from main. -int MapStaticCodeToLargePages() { -#if defined(NODE_ENABLE_LARGE_CODE_PAGES) && NODE_ENABLE_LARGE_CODE_PAGES - bool have_thp = false; -#if defined(__linux__) - have_thp = IsTransparentHugePagesEnabled(); -#elif defined(__FreeBSD__) - have_thp = IsSuperPagesEnabled(); -#elif defined(__APPLE__) - // pse-36 flag is present in recent mac x64 products. - have_thp = true; -#endif - if (!have_thp) - return EACCES; - - struct text_region r = FindNodeTextRegion(); - if (r.found_text_region == false) - return ENOENT; - - return MoveTextRegionToLargePages(r); -#else - return ENOTSUP; -#endif -} - -const char* LargePagesError(int status) { - switch (status) { - case ENOTSUP: - return "Mapping to large pages is not supported."; - - case EACCES: - return "Large pages are not enabled."; - - case ENOENT: - return "failed to find text region"; - - case -1: - return "Mapping code to large pages failed. Reverting to default page " - "size."; - - case 0: - return "OK"; - - default: - return "Unknown error"; - } -} - -} // namespace node diff --git a/src/large_pages/node_large_page.h b/src/large_pages/node_large_page.h deleted file mode 100644 index 622cf09ede4e..000000000000 --- a/src/large_pages/node_large_page.h +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright (C) 2018 Intel Corporation -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), -// to deal in the Software without restriction, including without limitation -// the rights to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons to whom -// the Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included -// in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL -// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES -// OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE -// OR OTHER DEALINGS IN THE SOFTWARE. -// -// SPDX-License-Identifier: MIT - -#ifndef SRC_LARGE_PAGES_NODE_LARGE_PAGE_H_ -#define SRC_LARGE_PAGES_NODE_LARGE_PAGE_H_ - -#if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS - -namespace node { -int MapStaticCodeToLargePages(); -const char* LargePagesError(int status); -} // namespace node - -#endif // NODE_WANT_INTERNALS -#endif // SRC_LARGE_PAGES_NODE_LARGE_PAGE_H_ diff --git a/src/large_pages/node_text_start.S b/src/large_pages/node_text_start.S deleted file mode 100644 index 2a643457b572..000000000000 --- a/src/large_pages/node_text_start.S +++ /dev/null @@ -1,29 +0,0 @@ -#if defined(__ELF__) -.section .note.GNU-stack,"",%progbits -#endif -// Add .note.gnu.property note for x86_64 to enable Intel CET -// Based on: https://sourceware.org/annobin/annobin.html/Test-cf-protection.html -// Refs: https://github.com/nodejs/node/issues/59084 -#if defined(__x86_64__) || defined(_M_X64) -.section .note.gnu.property,"a" -.align 8 -.long 1f - 0f -.long 4f - 1f -.long 5 -0: -.string "GNU" -1: -.align 8 -.long 0xc0000002 -.long 3f - 2f -2: -.long 0x3 -3: -.align 8 -4: -#endif -.text -.align 0x2000 -.global __node_text_start -.hidden __node_text_start -__node_text_start: diff --git a/src/node.cc b/src/node.cc index 00282634419d..e8331150aa2f 100644 --- a/src/node.cc +++ b/src/node.cc @@ -81,8 +81,6 @@ #include "../deps/v8/third_party/vtune/v8-vtune.h" #endif -#include "large_pages/node_large_page.h" - #if defined(__APPLE__) || defined(__linux__) || defined(_WIN32) #define NODE_USE_V8_WASM_TRAP_HANDLER 1 #else @@ -1125,12 +1123,8 @@ InitializeOncePerProcessInternal(const std::vector& args, } if (!(flags & ProcessInitializationFlags::kNoUseLargePages) && - (per_process::cli_options->use_largepages == "on" || - per_process::cli_options->use_largepages == "silent")) { - int lp_result = node::MapStaticCodeToLargePages(); - if (per_process::cli_options->use_largepages == "on" && lp_result != 0) { - result->errors_.emplace_back(node::LargePagesError(lp_result)); - } + (per_process::cli_options->use_largepages == "on")) { + result->errors_.emplace_back("--use-largepages is no longer supported."); } if (!per_process::cli_options->run.empty()) { diff --git a/src/node.h b/src/node.h index bf6537e3bfe6..02a4a4246c1b 100644 --- a/src/node.h +++ b/src/node.h @@ -223,7 +223,8 @@ enum Flags : uint32_t { kNoParseGlobalDebugVariables = 1 << 9, // Do not adjust OS resource limits for this process. kNoAdjustResourceLimits = 1 << 10, - // Do not map code segments into large pages for this process. + // Legacy flag for not mapping code segments into large pages for this + // process. The feature is no longer supported so this is just a no-op. kNoUseLargePages = 1 << 11, // Skip printing output for --help, --version, --v8-options. kNoPrintHelpOrVersionOutput = 1 << 12, diff --git a/src/node_options.cc b/src/node_options.cc index c743a20c31bf..d3c7bccedfe8 100644 --- a/src/node_options.cc +++ b/src/node_options.cc @@ -1513,10 +1513,9 @@ PerProcessOptionsParser::PerProcessOptionsParser( #endif // OPENSSL_VERSION_MAJOR AddOption("--use-largepages", - "Map the Node.js static code to large pages. Options are " - "'off' (the default value, meaning do not map), " - "'on' (map and ignore failure, reporting it to stderr), " - "or 'silent' (map and silently ignore failure)", + "This option is no longer supported and a no-op. It still accepts" + " these values for compatibility: 'off' (default), 'on' (report a " + "warning to stderr), or 'silent' (same as 'off').", &PerProcessOptions::use_largepages, kAllowedInEnvvar); diff --git a/test/parallel/test-startup-large-pages.js b/test/parallel/test-startup-large-pages.js index 9ebe9fa7b668..f84aca074fb0 100644 --- a/test/parallel/test-startup-large-pages.js +++ b/test/parallel/test-startup-large-pages.js @@ -1,30 +1,31 @@ 'use strict'; -// Make sure that Node.js runs correctly with the --use-largepages option. +// Tests that the obsolete --use-largepages option is a no-op. It only prints +// a warning when the value is `on`. require('../common'); -const assert = require('assert'); -const { spawnSync } = require('child_process'); +const { spawnSyncAndAssert } = require('../common/child_process'); -{ - const child = spawnSync(process.execPath, - [ '--use-largepages=on', '-p', '42' ], - { stdio: ['inherit', 'pipe', 'inherit'] }); - const stdout = child.stdout.toString().match(/\S+/g); - assert.strictEqual(child.status, 0); - assert.strictEqual(child.signal, null); - assert.strictEqual(stdout.length, 1); - assert.strictEqual(stdout[0], '42'); -} +spawnSyncAndAssert(process.execPath, ['--use-largepages=on', '-p', '42'], { + trim: true, + stdout: '42', + stderr: /--use-largepages is no longer supported/, +}); -{ - const child = spawnSync(process.execPath, - [ '--use-largepages=xyzzy', '-p', '42' ]); - assert.strictEqual(child.status, 9); - assert.strictEqual(child.signal, null); - assert.match(child.stderr.toString().trim(), - /invalid value for --use-largepages$/); +for (const mode of ['off', 'silent']) { + spawnSyncAndAssert( + process.execPath, + [`--use-largepages=${mode}`, '-p', '42'], + { + trim: true, + stdout: '42', + stderr: '', + }); } -// TODO(gabrielschulhof): Make assertions about the stderr, which may or may not -// contain a message indicating that mapping to large pages has failed. +spawnSyncAndAssert(process.execPath, ['--use-largepages=xyzzy', '-p', '42'], { + trim: true, + status: 9, + stdout: '', + stderr: /invalid value for --use-largepages/, +}); diff --git a/tools/license-builder.sh b/tools/license-builder.sh index d4f4382ca655..e758857390c1 100755 --- a/tools/license-builder.sh +++ b/tools/license-builder.sh @@ -120,10 +120,6 @@ addlicense "gtest" "deps/googletest" "$licenseText" licenseText="$(cat "${rootdir}/deps/nghttp2/COPYING")" addlicense "nghttp2" "deps/nghttp2" "$licenseText" -# large_pages -licenseText="$(sed -e '/SPDX-License-Identifier/,$d' -e 's/^\/\///' "${rootdir}/src/large_pages/node_large_page.h")" -addlicense "large_pages" "src/large_pages" "$licenseText" - # deep_freeze licenseText="$(sed -e '/SPDX-License-Identifier/,$d' -e 's/^\/\///' "${rootdir}/lib/internal/freeze_intrinsics.js")" addlicense "caja" "lib/internal/freeze_intrinsics.js" "$licenseText"