提交 18e80c55 编写于 作者: R Richard Henderson 提交者: Riku Voipio

linux-user: Tidy and enforce reserved_va initialization

We had a check using TARGET_VIRT_ADDR_SPACE_BITS to make sure
that the allocation coming in from the command-line option was
not too large, but that didn't include target-specific knowledge
about other restrictions on user-space.

Remove several target-specific hacks in linux-user/main.c.

For MIPS and Nios, we can replace them with proper adjustments
to the respective target's TARGET_VIRT_ADDR_SPACE_BITS definition.

For ARM, we had no existing ifdef but I suspect that the current
default value of 0xf7000000 was chosen with this in mind.  Define
a workable value in linux-user/arm/, and also document why the
special case is required.
Signed-off-by: NRichard Henderson <rth@twiddle.net>
Reviewed-by: NPeter Maydell <peter.maydell@linaro.org>
Message-Id: <20170708025030.15845-3-rth@twiddle.net>
Signed-off-by: NRiku Voipio <riku.voipio@linaro.org>
上级 de258eb0
...@@ -19,6 +19,10 @@ ...@@ -19,6 +19,10 @@
#ifndef ARM_TARGET_CPU_H #ifndef ARM_TARGET_CPU_H
#define ARM_TARGET_CPU_H #define ARM_TARGET_CPU_H
/* We need to be able to map the commpage.
See validate_guest_space in linux-user/elfload.c. */
#define MAX_RESERVED_VA 0xffff0000ul
static inline void cpu_clone_regs(CPUARMState *env, target_ulong newsp) static inline void cpu_clone_regs(CPUARMState *env, target_ulong newsp)
{ {
if (newsp) { if (newsp) {
......
...@@ -60,23 +60,38 @@ do { \ ...@@ -60,23 +60,38 @@ do { \
} \ } \
} while (0) } 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 * 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. * 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 * This way we will never overlap with our own libraries or binaries or stack
* or anything else that QEMU maps. * 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) #ifndef MAX_RESERVED_VA
/* # if HOST_LONG_BITS > TARGET_VIRT_ADDR_SPACE_BITS
* MIPS only supports 31 bits of virtual address space for user space. # if TARGET_VIRT_ADDR_SPACE_BITS == 32 && \
* Nios2 also only supports 31 bits. (TARGET_LONG_BITS == 32 || defined(TARGET_ABI32))
*/ /* There are a number of places where we assign reserved_va to a variable
unsigned long reserved_va = 0x77000000; 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 # else
unsigned long reserved_va = 0xf7000000; # define MAX_RESERVED_VA 0
# endif # 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 #else
unsigned long reserved_va; unsigned long reserved_va;
#endif #endif
...@@ -3978,11 +3993,8 @@ static void handle_arg_reserved_va(const char *arg) ...@@ -3978,11 +3993,8 @@ static void handle_arg_reserved_va(const char *arg)
unsigned long unshifted = reserved_va; unsigned long unshifted = reserved_va;
p++; p++;
reserved_va <<= shift; reserved_va <<= shift;
if (((reserved_va >> shift) != unshifted) if (reserved_va >> shift != unshifted
#if HOST_LONG_BITS > TARGET_VIRT_ADDR_SPACE_BITS || (MAX_RESERVED_VA && reserved_va > MAX_RESERVED_VA)) {
|| (reserved_va > (1ul << TARGET_VIRT_ADDR_SPACE_BITS))
#endif
) {
fprintf(stderr, "Reserved virtual address too big\n"); fprintf(stderr, "Reserved virtual address too big\n");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
......
...@@ -15,7 +15,11 @@ ...@@ -15,7 +15,11 @@
#else #else
#define TARGET_LONG_BITS 32 #define TARGET_LONG_BITS 32
#define TARGET_PHYS_ADDR_SPACE_BITS 40 #define TARGET_PHYS_ADDR_SPACE_BITS 40
#define TARGET_VIRT_ADDR_SPACE_BITS 32 # ifdef CONFIG_USER_ONLY
# define TARGET_VIRT_ADDR_SPACE_BITS 31
# else
# define TARGET_VIRT_ADDR_SPACE_BITS 32
#endif
#endif #endif
/* Masks used to mark instructions to indicate which ISA level they /* Masks used to mark instructions to indicate which ISA level they
......
...@@ -226,7 +226,11 @@ qemu_irq *nios2_cpu_pic_init(Nios2CPU *cpu); ...@@ -226,7 +226,11 @@ qemu_irq *nios2_cpu_pic_init(Nios2CPU *cpu);
void nios2_check_interrupts(CPUNios2State *env); void nios2_check_interrupts(CPUNios2State *env);
#define TARGET_PHYS_ADDR_SPACE_BITS 32 #define TARGET_PHYS_ADDR_SPACE_BITS 32
#define TARGET_VIRT_ADDR_SPACE_BITS 32 #ifdef CONFIG_USER_ONLY
# define TARGET_VIRT_ADDR_SPACE_BITS 31
#else
# define TARGET_VIRT_ADDR_SPACE_BITS 32
#endif
#define cpu_init(cpu_model) cpu_generic_init(TYPE_NIOS2_CPU, cpu_model) #define cpu_init(cpu_model) cpu_generic_init(TYPE_NIOS2_CPU, cpu_model)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册