Commit f2a48d69 authored by Peter Maydell's avatar Peter Maydell
Browse files

Merge remote-tracking branch 'remotes/riku/tags/pull-linux-user-20171018' into staging



Linux-user updates for Qemu 2.11

# gpg: Signature made Wed 18 Oct 2017 13:20:14 BST
# gpg:                using RSA key 0xB44890DEDE3C9BC0
# gpg: Good signature from "Riku Voipio <riku.voipio@iki.fi>"
# gpg:                 aka "Riku Voipio <riku.voipio@linaro.org>"
# Primary key fingerprint: FF82 03C8 C391 98AE 0581  41EF B448 90DE DE3C 9BC0

* remotes/riku/tags/pull-linux-user-20171018:
  linux-user: Fix TARGET_MTIOCTOP/MTIOCGET/MTIOCPOS values
  linux-user/main: support dfilter
  linux-user: Fix target FS_IOC_GETFLAGS and FS_IOC_SETFLAGS numbers
  linux-user/sh4: Reduce TARGET_VIRT_ADDR_SPACE_BITS to 31
  linux-user: Tidy and enforce reserved_va initialization
  tcg: Fix off-by-one in assert in page_set_flags
  linux-user: Allow -R values up to 0xffff0000 for 32-bit ARM guests
  linux-user: remove duplicate break in syscall
  target/m68k,linux-user: manage FP registers in ucontext
  linux-user: fix O_TMPFILE handling

Signed-off-by: default avatarPeter Maydell <peter.maydell@linaro.org>
parents ba6f0fc2 f443e396
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -2114,7 +2114,7 @@ void page_set_flags(target_ulong start, target_ulong end, int flags)
       guest address space.  If this assert fires, it probably indicates
       a missing call to h2g_valid.  */
#if TARGET_ABI_BITS > L1_MAP_ADDR_SPACE_BITS
    assert(end < ((target_ulong)1 << L1_MAP_ADDR_SPACE_BITS));
    assert(end <= ((target_ulong)1 << L1_MAP_ADDR_SPACE_BITS));
#endif
    assert(start < end);
    assert_memory_lock();
+4 −0
Original line number Diff line number Diff line
@@ -19,6 +19,10 @@
#ifndef 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)
{
    if (newsp) {
+1 −1
Original line number Diff line number Diff line
@@ -377,7 +377,7 @@ static int validate_guest_space(unsigned long guest_base,
     * then there is no way we can allocate it.
     */
    if (test_page_addr >= guest_base
        && test_page_addr <= (guest_base + guest_size)) {
        && test_page_addr < (guest_base + guest_size)) {
        return -1;
    }

+32 −13
Original line number Diff line number Diff line
@@ -60,24 +60,39 @@ 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
unsigned long reserved_va = 0xf7000000;
#   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

@@ -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,
+43 −0
Original line number Diff line number Diff line
@@ -5704,6 +5704,24 @@ give_sigsegv:
    force_sigsegv(sig);
}

static inline void target_rt_save_fpu_state(struct target_ucontext *uc,
                                           CPUM68KState *env)
{
    int i;
    target_fpregset_t *fpregs = &uc->tuc_mcontext.fpregs;

    __put_user(env->fpcr, &fpregs->f_fpcntl[0]);
    __put_user(env->fpsr, &fpregs->f_fpcntl[1]);
    /* fpiar is not emulated */

    for (i = 0; i < 8; i++) {
        uint32_t high = env->fregs[i].d.high << 16;
        __put_user(high, &fpregs->f_fpregs[i * 3]);
        __put_user(env->fregs[i].d.low,
                   (uint64_t *)&fpregs->f_fpregs[i * 3 + 1]);
    }
}

static inline int target_rt_setup_ucontext(struct target_ucontext *uc,
                                           CPUM68KState *env)
{
@@ -5730,9 +5748,32 @@ static inline int target_rt_setup_ucontext(struct target_ucontext *uc,
    __put_user(env->pc, &gregs[16]);
    __put_user(sr, &gregs[17]);

    target_rt_save_fpu_state(uc, env);

    return 0;
}

static inline void target_rt_restore_fpu_state(CPUM68KState *env,
                                               struct target_ucontext *uc)
{
    int i;
    target_fpregset_t *fpregs = &uc->tuc_mcontext.fpregs;
    uint32_t fpcr;

    __get_user(fpcr, &fpregs->f_fpcntl[0]);
    cpu_m68k_set_fpcr(env, fpcr);
    __get_user(env->fpsr, &fpregs->f_fpcntl[1]);
    /* fpiar is not emulated */

    for (i = 0; i < 8; i++) {
        uint32_t high;
        __get_user(high, &fpregs->f_fpregs[i * 3]);
        env->fregs[i].d.high = high >> 16;
        __get_user(env->fregs[i].d.low,
                   (uint64_t *)&fpregs->f_fpregs[i * 3 + 1]);
    }
}

static inline int target_rt_restore_ucontext(CPUM68KState *env,
                                             struct target_ucontext *uc)
{
@@ -5764,6 +5805,8 @@ static inline int target_rt_restore_ucontext(CPUM68KState *env,
    __get_user(temp, &gregs[17]);
    cpu_m68k_set_ccr(env, temp);

    target_rt_restore_fpu_state(env, uc);

    return 0;

badframe:
Loading