diff --git a/configure.ac b/configure.ac index 10b9b528f8..55666fc6e2 100644 --- a/configure.ac +++ b/configure.ac @@ -140,7 +140,6 @@ AC_MSG_RESULT([$ABI]) AC_SUBST([ABI]) - dnl dnl Miscellaneous tools dnl @@ -195,6 +194,44 @@ AC_CHECK_SIZEOF([long]) AC_CHECK_SIZEOF([long long]) +dnl Despite being 64-bit, the RISC-V architecture supports hardware +dnl MMUs and virtual memory layouts with fewer than the traditional +dnl 48 addressable bits: +dnl +dnl https://www.kernel.org/doc/html/next/riscv/vm-layout.html +dnl +dnl Here we detect only the most limited (SV39) of these, as GASMAN +dnl must be made aware of the limitation. +AS_CASE([$host], [riscv64*], [ + AC_MSG_CHECKING([[for SV39 MMU (RISC-V)]]) + AC_RUN_IFELSE( + [AC_LANG_SOURCE([[ +#define _BSD_SOURCE +#include +#include +#include + +int main(void) { + struct riscv_hwprobe p = { + .key = RISCV_HWPROBE_KEY_HIGHEST_VIRT_ADDRESS, + }; + if ((syscall(__NR_riscv_hwprobe, &p, 1, 0, NULL, 0) == 0) + && (p.key != -1) + && ((void*)p.value == (void*)0x4000000000)) { + return 0; + } + return 1; +} + ]])], [ + AC_MSG_RESULT([yes]) + GAP_DEFINE([HAVE_SV39_MMU=1]) + ], [ + AC_MSG_RESULT([no]) + ], [ + AC_MSG_RESULT([no (cross-compiling)]) + ]) +]) + dnl dnl User settings diff --git a/src/sysmem.c b/src/sysmem.c index 039272385b..5afd8133ad 100644 --- a/src/sysmem.c +++ b/src/sysmem.c @@ -359,9 +359,18 @@ static void * SyAnonMMap(size_t size) void *result; size = SyRoundUpToPagesize(size); #ifdef SYS_IS_64_BIT +#ifdef HAVE_SV39_MMU + /* On Linux (the only place we check for it), this MMU can only + * address 38 bits of virtual memory. The hint supplied to mmap() + * therefore needs to be much smaller than the default 16TB. Trial + * and error shows that 96GB works well enough. */ + result = mmap((void *) (96L*1024*1024*1024), size, + PROT_READ|PROT_WRITE, GAP_MMAP_FLAGS, -1, 0); +#else // The following is at 16 Terabyte: result = mmap((void *) (16L*1024*1024*1024*1024), size, PROT_READ|PROT_WRITE, GAP_MMAP_FLAGS, -1, 0); +#endif if (result == MAP_FAILED) { result = mmap(NULL, size, PROT_READ|PROT_WRITE, GAP_MMAP_FLAGS, -1, 0);