aboutsummaryrefslogtreecommitdiff
path: root/bsd-user/main.c
diff options
context:
space:
mode:
authorWarner Losh <imp@FreeBSD.org>2021-08-05 18:15:47 -0600
committerWarner Losh <imp@bsdimp.com>2021-09-10 14:13:06 -0600
commitbe04f210f954bed8663943a94ece50c2ca410231 (patch)
tree66b7ba615be609de81ee13896bf972d825d09d2d /bsd-user/main.c
parentb8012648b38274aa996f1477c422a79e2d44110b (diff)
bsd-user: Update mapping to handle reserved and starting conditions
Update the reserved base based on what platform we're on, as well as the start of the mmap range. Update routines that find va ranges to interact with the reserved ranges as well as properly align the mapping (this is especially important for targets whose page size does not match the host's). Loop where appropriate when the initial address space offered by mmap does not meet the contraints. This has 18e80c55bb6 from linux-user folded in to the upstream bsd-user code as well. Signed-off-by: Mikaƫl Urankar <mikael.urankar@gmail.com> Signed-off-by: Stacey Son <sson@FreeBSD.org> Signed-off-by: Warner Losh <imp@bsdimp.com> Acked-by: Richard Henderson <richard.henderson@linaro.org> Reviewed-by: Kyle Evans <kevans@FreeBSD.org>
Diffstat (limited to 'bsd-user/main.c')
-rw-r--r--bsd-user/main.c43
1 files changed, 42 insertions, 1 deletions
diff --git a/bsd-user/main.c b/bsd-user/main.c
index 6df4f4f011..48643eeabc 100644
--- a/bsd-user/main.c
+++ b/bsd-user/main.c
@@ -52,10 +52,47 @@
#include "target_arch_cpu.h"
int singlestep;
-unsigned long mmap_min_addr;
uintptr_t guest_base;
bool have_guest_base;
+/*
+ * When running 32-on-64 we should make sure we can fit all of the possible
+ * guest address space into a contiguous chunk of virtual host memory.
+ *
+ * This way we will never overlap with our own libraries or binaries or stack
+ * or anything else that QEMU maps.
+ *
+ * Many cpus reserve the high bit (or more than one for some 64-bit cpus)
+ * of the address for the kernel. Some cpus rely on this and user space
+ * uses the high bit(s) for pointer tagging and the like. For them, we
+ * must preserve the expected address space.
+ */
+#ifndef MAX_RESERVED_VA
+# if HOST_LONG_BITS > TARGET_VIRT_ADDR_SPACE_BITS
+# if TARGET_VIRT_ADDR_SPACE_BITS == 32 && \
+ (TARGET_LONG_BITS == 32 || defined(TARGET_ABI32))
+/*
+ * There are a number of places where we assign reserved_va to a variable
+ * of type abi_ulong and expect it to fit. Avoid the last page.
+ */
+# define MAX_RESERVED_VA (0xfffffffful & TARGET_PAGE_MASK)
+# else
+# define MAX_RESERVED_VA (1ul << TARGET_VIRT_ADDR_SPACE_BITS)
+# endif
+# else
+# define MAX_RESERVED_VA 0
+# endif
+#endif
+
+/*
+ * That said, reserving *too* much vm space via mmap can run into problems
+ * with rlimits, oom due to page table creation, etc. We will still try it,
+ * if directed by the command-line option, but not by default.
+ */
+#if HOST_LONG_BITS == 64 && TARGET_VIRT_ADDR_SPACE_BITS <= 32
+unsigned long reserved_va = MAX_RESERVED_VA;
+#else
unsigned long reserved_va;
+#endif
static const char *interp_prefix = CONFIG_QEMU_INTERP_PREFIX;
const char *qemu_uname_release;
@@ -439,6 +476,10 @@ int main(int argc, char **argv)
target_environ = envlist_to_environ(envlist, NULL);
envlist_free(envlist);
+ if (reserved_va) {
+ mmap_next_start = reserved_va;
+ }
+
{
Error *err = NULL;
if (seed_optarg != NULL) {