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

Merge remote-tracking branch 'remotes/vivier2/tags/linux-user-for-4.2-pull-request' into staging



Add several floppy drive ioctl,
xtensa call0 ABI support, arm MAX_RESERVED_VA for M-profile,
aarch64 AT_HWCAP2, qOffsets' query for ELF, memfd_create,
and some code cleanup

# gpg: Signature made Wed 11 Sep 2019 07:48:45 BST
# gpg:                using RSA key CD2F75DDC8E3A4DC2E4F5173F30C38BD3F2FBE3C
# gpg:                issuer "laurent@vivier.eu"
# gpg: Good signature from "Laurent Vivier <lvivier@redhat.com>" [full]
# gpg:                 aka "Laurent Vivier <laurent@vivier.eu>" [full]
# gpg:                 aka "Laurent Vivier (Red Hat) <lvivier@redhat.com>" [full]
# Primary key fingerprint: CD2F 75DD C8E3 A4DC 2E4F  5173 F30C 38BD 3F2F BE3C

* remotes/vivier2/tags/linux-user-for-4.2-pull-request:
  linux-user: Add support for FDRESET, FDRAWCMD, FDTWADDLE, and FDEJECT ioctls
  linux-user: Add support for FDMSGON and FDMSGOFF ioctls
  linux-user: Add support for FDFLUSH ioctl
  linux-user: Add support for FIOGETOWN and FIOSETOWN ioctls
  linux-user: Add support for RNDRESEEDCRNG ioctl
  linux-user: drop redundant handling of environment variables
  target/xtensa: linux-user: add call0 ABI support
  linux-user: Support gdb 'qOffsets' query for ELF
  linux-user/arm: Adjust MAX_RESERVED_VA for M-profile
  linux-user: Pass CPUState to MAX_RESERVED_VA
  linux-user: add memfd_create
  linux-user: fail and report on bad dfilter specs
  linux-user: erroneous fd_trans_unregister call
  linux-user: Add AT_HWCAP2 for aarch64-linux-user
  linux-user: remove useless variable

Signed-off-by: default avatarPeter Maydell <peter.maydell@linaro.org>
parents 6d2fdde4 5eea9429
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -32,6 +32,10 @@
#define MFD_HUGE_SHIFT 26
#endif

#if defined CONFIG_LINUX && !defined CONFIG_MEMFD
int memfd_create(const char *name, unsigned int flags);
#endif

int qemu_memfd_create(const char *name, size_t size, bool hugetlb,
                      uint64_t hugetlbsize, unsigned int seals, Error **errp);
bool qemu_memfd_alloc_check(void);
+21 −3
Original line number Diff line number Diff line
@@ -19,9 +19,27 @@
#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 unsigned long arm_max_reserved_va(CPUState *cs)
{
    ARMCPU *cpu = ARM_CPU(cs);

    if (arm_feature(&cpu->env, ARM_FEATURE_M)) {
        /*
         * There are magic return addresses above 0xfe000000,
         * and in general a lot of M-profile system stuff in
         * the high addresses.  Restrict linux-user to the
         * cached write-back RAM in the system map.
         */
        return 0x80000000ul;
    } else {
        /*
         * We need to be able to map the commpage.
         * See validate_guest_space in linux-user/elfload.c.
         */
        return 0xffff0000ul;
    }
}
#define MAX_RESERVED_VA  arm_max_reserved_va

static inline void cpu_clone_regs(CPUARMState *env, target_ulong newsp)
{
+29 −4
Original line number Diff line number Diff line
@@ -607,9 +607,23 @@ enum {
    ARM_HWCAP_A64_SB            = 1 << 29,
    ARM_HWCAP_A64_PACA          = 1 << 30,
    ARM_HWCAP_A64_PACG          = 1UL << 31,

    ARM_HWCAP2_A64_DCPODP       = 1 << 0,
    ARM_HWCAP2_A64_SVE2         = 1 << 1,
    ARM_HWCAP2_A64_SVEAES       = 1 << 2,
    ARM_HWCAP2_A64_SVEPMULL     = 1 << 3,
    ARM_HWCAP2_A64_SVEBITPERM   = 1 << 4,
    ARM_HWCAP2_A64_SVESHA3      = 1 << 5,
    ARM_HWCAP2_A64_SVESM4       = 1 << 6,
    ARM_HWCAP2_A64_FLAGM2       = 1 << 7,
    ARM_HWCAP2_A64_FRINT        = 1 << 8,
};

#define ELF_HWCAP   get_elf_hwcap()
#define ELF_HWCAP2  get_elf_hwcap2()

#define GET_FEATURE_ID(feat, hwcap) \
    do { if (cpu_isar_feature(feat, cpu)) { hwcaps |= hwcap; } } while (0)

static uint32_t get_elf_hwcap(void)
{
@@ -621,8 +635,6 @@ static uint32_t get_elf_hwcap(void)
    hwcaps |= ARM_HWCAP_A64_CPUID;

    /* probe for the extra features */
#define GET_FEATURE_ID(feat, hwcap) \
    do { if (cpu_isar_feature(feat, cpu)) { hwcaps |= hwcap; } } while (0)

    GET_FEATURE_ID(aa64_aes, ARM_HWCAP_A64_AES);
    GET_FEATURE_ID(aa64_pmull, ARM_HWCAP_A64_PMULL);
@@ -645,11 +657,22 @@ static uint32_t get_elf_hwcap(void)
    GET_FEATURE_ID(aa64_sb, ARM_HWCAP_A64_SB);
    GET_FEATURE_ID(aa64_condm_4, ARM_HWCAP_A64_FLAGM);

#undef GET_FEATURE_ID
    return hwcaps;
}

static uint32_t get_elf_hwcap2(void)
{
    ARMCPU *cpu = ARM_CPU(thread_cpu);
    uint32_t hwcaps = 0;

    GET_FEATURE_ID(aa64_condm_5, ARM_HWCAP2_A64_FLAGM2);
    GET_FEATURE_ID(aa64_frint, ARM_HWCAP2_A64_FRINT);

    return hwcaps;
}

#undef GET_FEATURE_ID

#endif /* not TARGET_AARCH64 */
#endif /* TARGET_ARM */

@@ -2380,6 +2403,8 @@ static void load_elf_image(const char *image_name, int image_fd,
    }

    info->load_bias = load_bias;
    info->code_offset = load_bias;
    info->data_offset = load_bias;
    info->load_addr = load_addr;
    info->entry = ehdr->e_entry + load_bias;
    info->start_code = -1;
+13 −0
Original line number Diff line number Diff line
@@ -112,6 +112,14 @@
     IOCTL(BLKZEROOUT, IOC_W, MK_PTR(MK_ARRAY(TYPE_ULONGLONG, 2)))
#endif

     IOCTL(FDMSGON, 0, TYPE_NULL)
     IOCTL(FDMSGOFF, 0, TYPE_NULL)
     IOCTL(FDFLUSH, 0, TYPE_NULL)
     IOCTL(FDRESET, 0, TYPE_NULL)
     IOCTL(FDRAWCMD, 0, TYPE_NULL)
     IOCTL(FDTWADDLE, 0, TYPE_NULL)
     IOCTL(FDEJECT, 0, TYPE_NULL)

#ifdef FIBMAP
     IOCTL(FIBMAP, IOC_W | IOC_R, MK_PTR(TYPE_LONG))
#endif
@@ -177,6 +185,8 @@
#endif
#endif /* CONFIG_USBFS */

  IOCTL(FIOGETOWN, IOC_R, MK_PTR(TYPE_INT))
  IOCTL(FIOSETOWN, IOC_W, MK_PTR(TYPE_INT))
  IOCTL(SIOCATMARK, IOC_R, MK_PTR(TYPE_INT))
  IOCTL(SIOCGIFNAME, IOC_RW, MK_PTR(MK_STRUCT(STRUCT_int_ifreq)))
  IOCTL(SIOCGIFFLAGS, IOC_W | IOC_R, MK_PTR(MK_STRUCT(STRUCT_short_ifreq)))
@@ -246,6 +256,9 @@
  IOCTL(RNDADDTOENTCNT, IOC_W, MK_PTR(TYPE_INT))
  IOCTL(RNDZAPENTCNT, 0, TYPE_NULL)
  IOCTL(RNDCLEARPOOL, 0, TYPE_NULL)
#ifdef RNDRESEEDCRNG
  IOCTL(RNDRESEEDCRNG, 0, TYPE_NULL)
#endif

  IOCTL(CDROMPAUSE, 0, TYPE_NULL)
  IOCTL(CDROMSTART, 0, TYPE_NULL)
+39 −30
Original line number Diff line number Diff line
@@ -49,7 +49,6 @@
char *exec_path;

int singlestep;
static const char *filename;
static const char *argv0;
static int gdbstub_port;
static envlist_t *envlist;
@@ -78,12 +77,12 @@ int have_guest_base;
      (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)
#   define MAX_RESERVED_VA(CPU)  (0xfffffffful & TARGET_PAGE_MASK)
#  else
#   define MAX_RESERVED_VA  (1ul << TARGET_VIRT_ADDR_SPACE_BITS)
#   define MAX_RESERVED_VA(CPU)  (1ul << TARGET_VIRT_ADDR_SPACE_BITS)
#  endif
# else
#  define MAX_RESERVED_VA  0
#  define MAX_RESERVED_VA(CPU)  0
# endif
#endif

@@ -236,7 +235,7 @@ static void handle_arg_log(const char *arg)

static void handle_arg_dfilter(const char *arg)
{
    qemu_set_dfilter_ranges(arg, NULL);
    qemu_set_dfilter_ranges(arg, &error_fatal);
}

static void handle_arg_log_filename(const char *arg)
@@ -357,8 +356,7 @@ static void handle_arg_reserved_va(const char *arg)
        unsigned long unshifted = reserved_va;
        p++;
        reserved_va <<= shift;
        if (reserved_va >> shift != unshifted
            || (MAX_RESERVED_VA && reserved_va > MAX_RESERVED_VA)) {
        if (reserved_va >> shift != unshifted) {
            fprintf(stderr, "Reserved virtual address too big\n");
            exit(EXIT_FAILURE);
        }
@@ -393,6 +391,13 @@ static void handle_arg_trace(const char *arg)
    trace_file = trace_opt_parse(arg);
}

#if defined(TARGET_XTENSA)
static void handle_arg_abi_call0(const char *arg)
{
    xtensa_set_abi_call0();
}
#endif

struct qemu_argument {
    const char *argv;
    const char *env;
@@ -446,6 +451,10 @@ static const struct qemu_argument arg_table[] = {
     "",           "[[enable=]<pattern>][,events=<file>][,file=<file>]"},
    {"version",    "QEMU_VERSION",     false, handle_arg_version,
     "",           "display version information and exit"},
#if defined(TARGET_XTENSA)
    {"xtensa-abi-call0", "QEMU_XTENSA_ABI_CALL0", false, handle_arg_abi_call0,
     "",           "assume CALL0 Xtensa ABI"},
#endif
    {NULL, NULL, false, NULL, NULL, NULL}
};

@@ -586,7 +595,6 @@ static int parse_args(int argc, char **argv)
        exit(EXIT_FAILURE);
    }

    filename = argv[optind];
    exec_path = argv[optind];

    return optind;
@@ -607,6 +615,7 @@ int main(int argc, char **argv, char **envp)
    int i;
    int ret;
    int execfd;
    unsigned long max_reserved_va;

    error_init(argv[0]);
    module_call_init(MODULE_INIT_TRACE);
@@ -657,9 +666,9 @@ int main(int argc, char **argv, char **envp)

    execfd = qemu_getauxval(AT_EXECFD);
    if (execfd == 0) {
        execfd = open(filename, O_RDONLY);
        execfd = open(exec_path, O_RDONLY);
        if (execfd < 0) {
            printf("Error while loading %s: %s\n", filename, strerror(errno));
            printf("Error while loading %s: %s\n", exec_path, strerror(errno));
            _exit(EXIT_FAILURE);
        }
    }
@@ -672,31 +681,31 @@ int main(int argc, char **argv, char **envp)
    /* init tcg before creating CPUs and to get qemu_host_page_size */
    tcg_exec_init(0);

    /* 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 &&
        reserved_va == 0) {
        /* reserved_va must be aligned with the host page size
         * as it is used with mmap()
         */
        reserved_va = MAX_RESERVED_VA & qemu_host_page_mask;
    }

    cpu = cpu_create(cpu_type);
    env = cpu->env_ptr;
    cpu_reset(cpu);

    thread_cpu = cpu;

    if (getenv("QEMU_STRACE")) {
        do_strace = 1;
    /*
     * 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.
     */
    max_reserved_va = MAX_RESERVED_VA(cpu);
    if (reserved_va != 0) {
        if (max_reserved_va && reserved_va > max_reserved_va) {
            fprintf(stderr, "Reserved virtual address too big\n");
            exit(EXIT_FAILURE);
        }

    if (seed_optarg == NULL) {
        seed_optarg = getenv("QEMU_RAND_SEED");
    } else if (HOST_LONG_BITS == 64 && TARGET_VIRT_ADDR_SPACE_BITS <= 32) {
        /*
         * reserved_va must be aligned with the host page size
         * as it is used with mmap()
         */
        reserved_va = max_reserved_va & qemu_host_page_mask;
    }

    {
        Error *err = NULL;
        if (seed_optarg != NULL) {
@@ -784,10 +793,10 @@ int main(int argc, char **argv, char **envp)
    cpu->opaque = ts;
    task_settid(ts);

    ret = loader_exec(execfd, filename, target_argv, target_environ, regs,
    ret = loader_exec(execfd, exec_path, target_argv, target_environ, regs,
        info, &bprm);
    if (ret != 0) {
        printf("Error while loading %s: %s\n", filename, strerror(-ret));
        printf("Error while loading %s: %s\n", exec_path, strerror(-ret));
        _exit(EXIT_FAILURE);
    }

Loading