From e68cc1bf6f8c9022a96dc1c67694dd0524539bd4 Mon Sep 17 00:00:00 2001 From: Seg Date: Mon, 30 Nov 2020 20:52:34 -0800 Subject: [PATCH 1/3] Fix direct addressing on aarch64 linux and others --- BasiliskII/src/CrossPlatform/vm_alloc.cpp | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) mode change 100755 => 100644 BasiliskII/src/CrossPlatform/vm_alloc.cpp diff --git a/BasiliskII/src/CrossPlatform/vm_alloc.cpp b/BasiliskII/src/CrossPlatform/vm_alloc.cpp old mode 100755 new mode 100644 index 005cb727..32e36236 --- a/BasiliskII/src/CrossPlatform/vm_alloc.cpp +++ b/BasiliskII/src/CrossPlatform/vm_alloc.cpp @@ -83,6 +83,10 @@ typedef unsigned long vm_uintptr_t; #define MAP_ANONYMOUS 0 #endif +/* NOTE: on linux MAP_32BIT is only implemented on AMD64 + it is a null op on all other architectures + thus the MAP_BASE setting below is the only thing + ensuring low addresses on aarch64 for example */ #define MAP_EXTRA_FLAGS (MAP_32BIT) #ifdef HAVE_MMAP_VM @@ -91,7 +95,18 @@ typedef unsigned long vm_uintptr_t; don't get addresses above when the program is run on AMD64. NOTE: this is empirically determined on Linux/x86. */ #define MAP_BASE 0x10000000 -#else +#elif !REAL_ADDRESSING +/* linux does not implement any useful fallback behavior + such as allocating the next available address + and the first 4k-64k of address space is marked unavailable + for security reasons (see https://wiki.debian.org/mmap_min_addr) + so we must start requesting after the first page + (or we get a high 64bit address and break on aarch64) + + leaving NULL unmapped is a good idea anyway for debugging reasons + so we do this unconditionally on all platforms */ +#define MAP_BASE 0x00010000 +#else /* must be 0x0 when REAL_ADDRESSING=1 */ #define MAP_BASE 0x00000000 #endif static char * next_address = (char *)MAP_BASE; From 8f4d65186c01d3bb1f2ba73ef3545b01a37a8950 Mon Sep 17 00:00:00 2001 From: Seg Date: Mon, 30 Nov 2020 21:54:53 -0800 Subject: [PATCH 2/3] Fix banked addressing on aarch64 linux and others --- BasiliskII/src/CrossPlatform/vm_alloc.cpp | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/BasiliskII/src/CrossPlatform/vm_alloc.cpp b/BasiliskII/src/CrossPlatform/vm_alloc.cpp index 32e36236..50636029 100644 --- a/BasiliskII/src/CrossPlatform/vm_alloc.cpp +++ b/BasiliskII/src/CrossPlatform/vm_alloc.cpp @@ -95,18 +95,17 @@ typedef unsigned long vm_uintptr_t; don't get addresses above when the program is run on AMD64. NOTE: this is empirically determined on Linux/x86. */ #define MAP_BASE 0x10000000 -#elif !REAL_ADDRESSING +#elif DIRECT_ADDRESSING /* linux does not implement any useful fallback behavior such as allocating the next available address and the first 4k-64k of address space is marked unavailable for security reasons (see https://wiki.debian.org/mmap_min_addr) so we must start requesting after the first page - (or we get a high 64bit address and break on aarch64) + or we get a high 64bit address that will crash direct addressing - leaving NULL unmapped is a good idea anyway for debugging reasons - so we do this unconditionally on all platforms */ + leaving NULL unmapped is a good idea anyway for debugging reasons */ #define MAP_BASE 0x00010000 -#else /* must be 0x0 when REAL_ADDRESSING=1 */ +#else #define MAP_BASE 0x00000000 #endif static char * next_address = (char *)MAP_BASE; @@ -270,9 +269,12 @@ void * vm_acquire(size_t size, int options) if ((addr = mmap((caddr_t)next_address, size, VM_PAGE_DEFAULT, the_map_flags, fd, 0)) == (void *)MAP_FAILED) return VM_MAP_FAILED; - // Sanity checks for 64-bit platforms +#if DIRECT_ADDRESSING + // Sanity check to prevent crash on 64-bit when direct addressing + // FIXME: this results in a misleading "out of memory" error to the user when it fails if (sizeof(void *) == 8 && (options & VM_MAP_32BIT) && !((char *)addr <= (char *)0xffffffff)) return VM_MAP_FAILED; +#endif next_address = (char *)addr + size; #elif defined(HAVE_WIN32_VM) From 17ed9f99ed0c7a06edeb6ea9bed3411ff84c7db0 Mon Sep 17 00:00:00 2001 From: Seg Date: Mon, 7 Dec 2020 16:04:39 -0800 Subject: [PATCH 3/3] Improve error reporting --- BasiliskII/src/CrossPlatform/vm_alloc.cpp | 9 +++++---- BasiliskII/src/CrossPlatform/vm_alloc.h | 2 ++ 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/BasiliskII/src/CrossPlatform/vm_alloc.cpp b/BasiliskII/src/CrossPlatform/vm_alloc.cpp index 50636029..30a156aa 100644 --- a/BasiliskII/src/CrossPlatform/vm_alloc.cpp +++ b/BasiliskII/src/CrossPlatform/vm_alloc.cpp @@ -270,10 +270,11 @@ void * vm_acquire(size_t size, int options) return VM_MAP_FAILED; #if DIRECT_ADDRESSING - // Sanity check to prevent crash on 64-bit when direct addressing - // FIXME: this results in a misleading "out of memory" error to the user when it fails - if (sizeof(void *) == 8 && (options & VM_MAP_32BIT) && !((char *)addr <= (char *)0xffffffff)) - return VM_MAP_FAILED; + // If VM_MAP_32BIT and MAP_BASE fail to ensure + // a 32-bit address crash now instead of later. + // FIXME: make everything 64-bit clean and tear this all out. + if(sizeof(void *) > 4 && (options & VM_MAP_32BIT)) + assert((size_t)addr<0xffffffffL); #endif next_address = (char *)addr + size; diff --git a/BasiliskII/src/CrossPlatform/vm_alloc.h b/BasiliskII/src/CrossPlatform/vm_alloc.h index c44e853b..c5d4f99a 100644 --- a/BasiliskII/src/CrossPlatform/vm_alloc.h +++ b/BasiliskII/src/CrossPlatform/vm_alloc.h @@ -36,6 +36,8 @@ extern "C" { } #endif +#include + /* Return value of `vm_acquire' in case of an error. */ #ifdef HAVE_MACH_VM #define VM_MAP_FAILED ((void *)-1)