Module: wine Branch: master Commit: 0900d919e2fd5ce12e02375cfcbfa5ab7c283515 URL: https://gitlab.winehq.org/wine/wine/-/commit/0900d919e2fd5ce12e02375cfcbfa5a...
Author: Alexandre Julliard julliard@winehq.org Date: Fri Jan 5 18:30:58 2024 +0100
ntdll: Determine the available address space dynamically on ARM64.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=56130
---
dlls/ntdll/unix/virtual.c | 57 ++++++++++++++++++++++++++++++++++++----------- 1 file changed, 44 insertions(+), 13 deletions(-)
diff --git a/dlls/ntdll/unix/virtual.c b/dlls/ntdll/unix/virtual.c index e805c349eac..abe1b4dc4ec 100644 --- a/dlls/ntdll/unix/virtual.c +++ b/dlls/ntdll/unix/virtual.c @@ -162,23 +162,18 @@ static void *address_space_start = (void *)0x110000; /* keep DOS area clear */ #else static void *address_space_start = (void *)0x10000; #endif - -#ifdef __aarch64__ -static void *address_space_limit = (void *)0xffffffff0000; /* top of the total available address space */ -#elif defined(_WIN64) -static void *address_space_limit = (void *)0x7fffffff0000; -#else -static void *address_space_limit = (void *)0xc0000000; -#endif - #ifdef _WIN64 +static void *address_space_limit = (void *)0x7fffffff0000; /* top of the total available address space */ static void *user_space_limit = (void *)0x7fffffff0000; /* top of the user address space */ static void *working_set_limit = (void *)0x7fffffff0000; /* top of the current working set */ #else +static void *address_space_limit = (void *)0xc0000000; static void *user_space_limit = (void *)0x7fff0000; static void *working_set_limit = (void *)0x7fff0000; #endif
+static void *host_addr_space_limit; /* top of the host virtual address space */ + static struct file_view *arm64ec_view;
ULONG_PTR user_space_wow_limit = 0; @@ -2009,6 +2004,7 @@ static NTSTATUS map_view( struct file_view **view_ret, void *base, size_t size, if (is_beyond_limit( base, size, address_space_limit )) return STATUS_WORKING_SET_LIMIT_RANGE; if (limit_low && base < (void *)limit_low) return STATUS_CONFLICTING_ADDRESSES; if (limit_high && is_beyond_limit( base, size, (void *)limit_high )) return STATUS_CONFLICTING_ADDRESSES; + if (is_beyond_limit( base, size, host_addr_space_limit )) return STATUS_CONFLICTING_ADDRESSES; if ((status = map_fixed_area( base, size, vprot ))) return status; if (is_beyond_limit( base, size, working_set_limit )) working_set_limit = address_space_limit; ptr = base; @@ -2016,7 +2012,7 @@ static NTSTATUS map_view( struct file_view **view_ret, void *base, size_t size, else { void *start = address_space_start; - void *end = user_space_limit; + void *end = min( user_space_limit, host_addr_space_limit ); size_t view_size, unmap_size;
if (!align_mask) align_mask = granularity_mask; @@ -2031,7 +2027,7 @@ static NTSTATUS map_view( struct file_view **view_ret, void *base, size_t size, goto done; }
- if (start > address_space_start || end < address_space_limit || top_down) + if (start > address_space_start || end < host_addr_space_limit || top_down) { if (!(ptr = map_free_area( start, end, size, top_down, get_unix_prot(vprot), align_mask ))) return STATUS_NO_MEMORY; @@ -2442,6 +2438,33 @@ static NTSTATUS map_pe_header( void *ptr, size_t size, int fd, BOOL *removable )
#ifdef __aarch64__
+/*********************************************************************** + * get_host_addr_space_limit + */ +static void *get_host_addr_space_limit(void) +{ + unsigned int flags = MAP_PRIVATE | MAP_ANON; + UINT_PTR addr = (UINT_PTR)1 << 63; + +#ifdef MAP_FIXED_NOREPLACE + flags |= MAP_FIXED_NOREPLACE; +#endif + + while (addr >> 32) + { + void *ret = mmap( (void *)addr, page_size, PROT_NONE, flags, -1, 0 ); + if (ret != MAP_FAILED) + { + munmap( ret, page_size ); + if (ret >= (void *)addr) break; + } + else if (errno == EEXIST) break; + addr >>= 1; + } + return (void *)((addr << 1) - (granularity_mask + 1)); +} + + /*********************************************************************** * alloc_arm64ec_map */ @@ -3223,7 +3246,8 @@ static void *alloc_virtual_heap( SIZE_T size ) void *base = area->base; void *end = (char *)base + area->size;
- if (is_beyond_limit( base, area->size, address_space_limit )) address_space_limit = end; + if (is_beyond_limit( base, area->size, address_space_limit )) + address_space_limit = host_addr_space_limit = end; if (is_win64 && base < (void *)0x80000000) break; if (preload_reserve_end >= end) { @@ -3261,6 +3285,13 @@ void virtual_init(void) pthread_mutex_init( &virtual_mutex, &attr ); pthread_mutexattr_destroy( &attr );
+#ifdef __aarch64__ + host_addr_space_limit = get_host_addr_space_limit(); + TRACE( "host addr space limit: %p\n", host_addr_space_limit ); +#else + host_addr_space_limit = address_space_limit; +#endif + if (preload_info && *preload_info) for (i = 0; (*preload_info)[i].size; i++) mmap_add_reserved_area( (*preload_info)[i].addr, (*preload_info)[i].size ); @@ -3282,7 +3313,7 @@ void virtual_init(void)
/* try to find space in a reserved area for the views and pages protection table */ #ifdef _WIN64 - pages_vprot_size = ((size_t)address_space_limit >> page_shift >> pages_vprot_shift) + 1; + pages_vprot_size = ((size_t)host_addr_space_limit >> page_shift >> pages_vprot_shift) + 1; size = 2 * view_block_size + pages_vprot_size * sizeof(*pages_vprot); #else size = 2 * view_block_size + (1U << (32 - page_shift));