Commit 03834e22 authored by Anthony Liguori's avatar Anthony Liguori
Browse files

Merge remote-tracking branch 'origin/master' into staging

* origin/master:
  linux-user: ARM: Ignore immediate value for svc in thumb mode
  linux-user: Use init_guest_space when -R and -B are specified
  linux-user: Factor out guest space probing into a function
  flatload: fix bss clearing
  linux-user: make host_to_target_cmsg support SO_TIMESTAMP cmsg_type
  linux-user: make do_setsockopt support SOL_RAW ICMP_FILTER socket option
  linux-user: pass sockaddr from host to target
  x86: switch to AREG0 free mode
  x86: avoid AREG0 in segmentation helpers
  x86: avoid AREG0 for misc helpers
  x86: use wrappers for memory access helpers
  x86: avoid AREG0 for SMM helpers
  x86: avoid AREG0 for SVM helpers
  x86: avoid AREG0 for integer helpers
  x86: avoid AREG0 for condition code helpers
  x86: avoid AREG0 for FPU helpers
  linux-user: Move target_to_host_errno_table[] setup out of ioctl loop
  linux-user: Fix SNDCTL_DSP_MAP{IN, OUT}BUF ioctl definitions
  linux-user: Fix incorrect TARGET_BLKBSZGET, TARGET_BLKBSZSET
parents 28a9a00e 873359d4
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -3778,7 +3778,7 @@ symlink "$source_path/Makefile.target" "$target_dir/Makefile"


case "$target_arch2" in
  alpha | or32 | sparc* | xtensa* | ppc*)
  alpha | i386 | or32 | sparc* | x86_64 | xtensa* | ppc*)
    echo "CONFIG_TCG_PASS_AREG0=y" >> $config_target_mak
  ;;
esac
+22 −0
Original line number Diff line number Diff line
@@ -274,6 +274,28 @@ extern unsigned long reserved_va;
#define cpu_ldsw_code(env1, p) ldsw_raw(p)
#define cpu_ldl_code(env1, p) ldl_raw(p)
#define cpu_ldq_code(env1, p) ldq_raw(p)

#define cpu_ldub_data(env, addr) ldub_raw(addr)
#define cpu_lduw_data(env, addr) lduw_raw(addr)
#define cpu_ldsw_data(env, addr) ldsw_raw(addr)
#define cpu_ldl_data(env, addr) ldl_raw(addr)
#define cpu_ldq_data(env, addr) ldq_raw(addr)

#define cpu_stb_data(env, addr, data) stb_raw(addr, data)
#define cpu_stw_data(env, addr, data) stw_raw(addr, data)
#define cpu_stl_data(env, addr, data) stl_raw(addr, data)
#define cpu_stq_data(env, addr, data) stq_raw(addr, data)

#define cpu_ldub_kernel(env, addr) ldub_raw(addr)
#define cpu_lduw_kernel(env, addr) lduw_raw(addr)
#define cpu_ldsw_kernel(env, addr) ldsw_raw(addr)
#define cpu_ldl_kernel(env, addr) ldl_raw(addr)
#define cpu_ldq_kernel(env, addr) ldq_raw(addr)

#define cpu_stb_kernel(env, addr, data) stb_raw(addr, data)
#define cpu_stw_kernel(env, addr, data) stw_raw(addr, data)
#define cpu_stl_kernel(env, addr, data) stl_raw(addr, data)
#define cpu_stq_kernel(env, addr, data) stq_raw(addr, data)
#endif

#define ldub_kernel(p) ldub_raw(p)
+123 −38
Original line number Diff line number Diff line
@@ -332,9 +332,17 @@ enum
    ARM_HWCAP_ARM_VFPv3D16  = 1 << 13,
};

#define TARGET_HAS_GUEST_VALIDATE_BASE
/* We want the opportunity to check the suggested base */
bool guest_validate_base(unsigned long guest_base)
#define TARGET_HAS_VALIDATE_GUEST_SPACE
/* Return 1 if the proposed guest space is suitable for the guest.
 * Return 0 if the proposed guest space isn't suitable, but another
 * address space should be tried.
 * Return -1 if there is no way the proposed guest space can be
 * valid regardless of the base.
 * The guest code may leave a page mapped and populate it if the
 * address is suitable.
 */
static int validate_guest_space(unsigned long guest_base,
                                unsigned long guest_size)
{
    unsigned long real_start, test_page_addr;

@@ -342,6 +350,15 @@ bool guest_validate_base(unsigned long guest_base)
     * commpage at 0xffff0fxx
     */
    test_page_addr = guest_base + (0xffff0f00 & qemu_host_page_mask);

    /* If the commpage lies within the already allocated guest space,
     * then there is no way we can allocate it.
     */
    if (test_page_addr >= guest_base
        && test_page_addr <= (guest_base + guest_size)) {
        return -1;
    }

    /* Note it needs to be writeable to let us initialise it */
    real_start = (unsigned long)
                 mmap((void *)test_page_addr, qemu_host_page_size,
@@ -1418,14 +1435,105 @@ static abi_ulong create_elf_tables(abi_ulong p, int argc, int envc,
    return sp;
}

#ifndef TARGET_HAS_GUEST_VALIDATE_BASE
#ifndef TARGET_HAS_VALIDATE_GUEST_SPACE
/* If the guest doesn't have a validation function just agree */
bool guest_validate_base(unsigned long guest_base)
static int validate_guest_space(unsigned long guest_base,
                                unsigned long guest_size)
{
    return 1;
}
#endif

unsigned long init_guest_space(unsigned long host_start,
                               unsigned long host_size,
                               unsigned long guest_start,
                               bool fixed)
{
    unsigned long current_start, real_start;
    int flags;

    assert(host_start || host_size);

    /* If just a starting address is given, then just verify that
     * address.  */
    if (host_start && !host_size) {
        if (validate_guest_space(host_start, host_size) == 1) {
            return host_start;
        } else {
            return (unsigned long)-1;
        }
    }

    /* Setup the initial flags and start address.  */
    current_start = host_start & qemu_host_page_mask;
    flags = MAP_ANONYMOUS | MAP_PRIVATE | MAP_NORESERVE;
    if (fixed) {
        flags |= MAP_FIXED;
    }

    /* Otherwise, a non-zero size region of memory needs to be mapped
     * and validated.  */
    while (1) {
        unsigned long real_size = host_size;

        /* Do not use mmap_find_vma here because that is limited to the
         * guest address space.  We are going to make the
         * guest address space fit whatever we're given.
         */
        real_start = (unsigned long)
            mmap((void *)current_start, host_size, PROT_NONE, flags, -1, 0);
        if (real_start == (unsigned long)-1) {
            return (unsigned long)-1;
        }

        /* Ensure the address is properly aligned.  */
        if (real_start & ~qemu_host_page_mask) {
            munmap((void *)real_start, host_size);
            real_size = host_size + qemu_host_page_size;
            real_start = (unsigned long)
                mmap((void *)real_start, real_size, PROT_NONE, flags, -1, 0);
            if (real_start == (unsigned long)-1) {
                return (unsigned long)-1;
            }
            real_start = HOST_PAGE_ALIGN(real_start);
        }

        /* Check to see if the address is valid.  */
        if (!host_start || real_start == current_start) {
            int valid = validate_guest_space(real_start - guest_start,
                                             real_size);
            if (valid == 1) {
                break;
            } else if (valid == -1) {
                return (unsigned long)-1;
            }
            /* valid == 0, so try again. */
        }

        /* That address didn't work.  Unmap and try a different one.
         * The address the host picked because is typically right at
         * the top of the host address space and leaves the guest with
         * no usable address space.  Resort to a linear search.  We
         * already compensated for mmap_min_addr, so this should not
         * happen often.  Probably means we got unlucky and host
         * address space randomization put a shared library somewhere
         * inconvenient.
         */
        munmap((void *)real_start, host_size);
        current_start += qemu_host_page_size;
        if (host_start == current_start) {
            /* Theoretically possible if host doesn't have any suitably
             * aligned areas.  Normally the first mmap will fail.
             */
            return (unsigned long)-1;
        }
    }

    qemu_log("Reserved 0x%lx bytes of guest address space\n", host_size);

    return real_start;
}

static void probe_guest_base(const char *image_name,
                             abi_ulong loaddr, abi_ulong hiaddr)
{
@@ -1452,46 +1560,23 @@ static void probe_guest_base(const char *image_name,
            }
        }
        host_size = hiaddr - loaddr;
        while (1) {
            /* Do not use mmap_find_vma here because that is limited to the
               guest address space.  We are going to make the
               guest address space fit whatever we're given.  */
            real_start = (unsigned long)
                mmap((void *)host_start, host_size, PROT_NONE,
                     MAP_ANONYMOUS | MAP_PRIVATE | MAP_NORESERVE, -1, 0);

        /* Setup the initial guest memory space with ranges gleaned from
         * the ELF image that is being loaded.
         */
        real_start = init_guest_space(host_start, host_size, loaddr, false);
        if (real_start == (unsigned long)-1) {
                goto exit_perror;
            }
            guest_base = real_start - loaddr;
            if ((real_start == host_start) &&
                guest_validate_base(guest_base)) {
                break;
            }
            /* That address didn't work.  Unmap and try a different one.
               The address the host picked because is typically right at
               the top of the host address space and leaves the guest with
               no usable address space.  Resort to a linear search.  We
               already compensated for mmap_min_addr, so this should not
               happen often.  Probably means we got unlucky and host
               address space randomization put a shared library somewhere
               inconvenient.  */
            munmap((void *)real_start, host_size);
            host_start += qemu_host_page_size;
            if (host_start == loaddr) {
                /* Theoretically possible if host doesn't have any suitably
                   aligned areas.  Normally the first mmap will fail.  */
            errmsg = "Unable to find space for application";
            goto exit_errmsg;
        }
        }
        guest_base = real_start - loaddr;

        qemu_log("Relocating guest address space from 0x"
                 TARGET_ABI_FMT_lx " to 0x%lx\n",
                 loaddr, real_start);
    }
    return;

exit_perror:
    errmsg = strerror(errno);
exit_errmsg:
    fprintf(stderr, "%s: %s\n", image_name, errmsg);
    exit(-1);
+1 −1
Original line number Diff line number Diff line
@@ -660,7 +660,7 @@ static int load_flat_file(struct linux_binprm * bprm,
    }

    /* zero the BSS.  */
    memset((void *)((unsigned long)datapos + data_len), 0, bss_len);
    memset(g2h(datapos + data_len), 0, bss_len);

    return 0;
}
+2 −2
Original line number Diff line number Diff line
@@ -186,8 +186,8 @@
  IOCTL(SNDCTL_DSP_GETISPACE, IOC_R, MK_PTR(MK_STRUCT(STRUCT_audio_buf_info)))
  IOCTL(SNDCTL_DSP_GETOSPACE, IOC_R, MK_PTR(MK_STRUCT(STRUCT_audio_buf_info)))
  IOCTL(SNDCTL_DSP_GETTRIGGER, IOC_R, MK_PTR(TYPE_INT))
  IOCTL(SNDCTL_DSP_MAPINBUF, IOC_R, MK_PTR(TYPE_INT))
  IOCTL(SNDCTL_DSP_MAPOUTBUF, IOC_R, MK_PTR(TYPE_INT))
  IOCTL(SNDCTL_DSP_MAPINBUF, IOC_R, MK_PTR(MK_STRUCT(STRUCT_buffmem_desc)))
  IOCTL(SNDCTL_DSP_MAPOUTBUF, IOC_R, MK_PTR(MK_STRUCT(STRUCT_buffmem_desc)))
  IOCTL(SNDCTL_DSP_NONBLOCK, 0, TYPE_NULL)
  IOCTL(SNDCTL_DSP_POST, 0, TYPE_NULL)
  IOCTL(SNDCTL_DSP_RESET, 0, TYPE_NULL)
Loading