aboutsummaryrefslogtreecommitdiff
path: root/linux-user/main.c
diff options
context:
space:
mode:
Diffstat (limited to 'linux-user/main.c')
-rw-r--r--linux-user/main.c45
1 files changed, 32 insertions, 13 deletions
diff --git a/linux-user/main.c b/linux-user/main.c
index 829f974662..dde04c769a 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -60,23 +60,38 @@ do { \
} \
} while (0)
-#if (TARGET_LONG_BITS == 32) && (HOST_LONG_BITS == 64)
/*
* 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.
*/
-# if defined(TARGET_MIPS) || defined(TARGET_NIOS2)
-/*
- * MIPS only supports 31 bits of virtual address space for user space.
- * Nios2 also only supports 31 bits.
- */
-unsigned long reserved_va = 0x77000000;
+#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
-unsigned long reserved_va = 0xf7000000;
+# 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
@@ -3854,6 +3869,11 @@ static void handle_arg_log(const char *arg)
qemu_set_log(mask);
}
+static void handle_arg_dfilter(const char *arg)
+{
+ qemu_set_dfilter_ranges(arg, NULL);
+}
+
static void handle_arg_log_filename(const char *arg)
{
qemu_set_log_filename(arg, &error_fatal);
@@ -3978,11 +3998,8 @@ static void handle_arg_reserved_va(const char *arg)
unsigned long unshifted = reserved_va;
p++;
reserved_va <<= shift;
- if (((reserved_va >> shift) != unshifted)
-#if HOST_LONG_BITS > TARGET_VIRT_ADDR_SPACE_BITS
- || (reserved_va > (1ul << TARGET_VIRT_ADDR_SPACE_BITS))
-#endif
- ) {
+ if (reserved_va >> shift != unshifted
+ || (MAX_RESERVED_VA && reserved_va > MAX_RESERVED_VA)) {
fprintf(stderr, "Reserved virtual address too big\n");
exit(EXIT_FAILURE);
}
@@ -4054,6 +4071,8 @@ static const struct qemu_argument arg_table[] = {
{"d", "QEMU_LOG", true, handle_arg_log,
"item[,...]", "enable logging of specified items "
"(use '-d help' for a list of items)"},
+ {"dfilter", "QEMU_DFILTER", true, handle_arg_dfilter,
+ "range[,...]","filter logging based on address range"},
{"D", "QEMU_LOG_FILENAME", true, handle_arg_log_filename,
"logfile", "write logs to 'logfile' (default stderr)"},
{"p", "QEMU_PAGESIZE", true, handle_arg_pagesize,