Commit 47994e16 authored by Peter Maydell's avatar Peter Maydell
Browse files

Merge remote-tracking branch 'remotes/pmaydell/tags/pull-target-arm-20190205' into staging



target-arm queue:
 * Implement Armv8.5-BTI extension for system emulation mode
 * Implement the PR_PAC_RESET_KEYS prctl() for linux-user mode's Armv8.3-PAuth support
 * Support TBI (top-byte-ignore) properly for linux-user mode
 * gdbstub: allow killing QEMU via vKill command
 * hw/arm/boot: Support DTB autoload for firmware-only boots
 * target/arm: Make FPSCR/FPCR trapped-exception bits RAZ/WI

# gpg: Signature made Tue 05 Feb 2019 17:04:22 GMT
# gpg:                using RSA key E1A5C593CD419DE28E8315CF3C2525ED14360CDE
# gpg:                issuer "peter.maydell@linaro.org"
# gpg: Good signature from "Peter Maydell <peter.maydell@linaro.org>" [ultimate]
# gpg:                 aka "Peter Maydell <pmaydell@gmail.com>" [ultimate]
# gpg:                 aka "Peter Maydell <pmaydell@chiark.greenend.org.uk>" [ultimate]
# Primary key fingerprint: E1A5 C593 CD41 9DE2 8E83  15CF 3C25 25ED 1436 0CDE

* remotes/pmaydell/tags/pull-target-arm-20190205: (22 commits)
  target/arm: Make FPSCR/FPCR trapped-exception bits RAZ/WI
  hw/arm/boot: Support DTB autoload for firmware-only boots
  hw/arm/boot: Clarify why arm_setup_firmware_boot() doesn't set env->boot_info
  hw/arm/boot: Factor out "set up firmware boot" code
  hw/arm/boot: Factor out "direct kernel boot" code into its own function
  hw/arm/boot: Fix block comment style in arm_load_kernel()
  gdbstub: allow killing QEMU via vKill command
  target/arm: Enable TBI for user-only
  target/arm: Compute TB_FLAGS for TBI for user-only
  target/arm: Clean TBI for data operations in the translator
  target/arm: Add TBFLAG_A64_TBID, split out gen_top_byte_ignore
  tests/tcg/aarch64: Add pauth smoke test
  linux-user: Implement PR_PAC_RESET_KEYS
  target/arm: Enable BTI for -cpu max
  target/arm: Set btype for indirect branches
  target/arm: Reset btype for direct branches
  target/arm: Default handling of BTYPE during translation
  target/arm: Cache the GP bit for a page in MemTxAttrs
  exec: Add target-specific tlb bits to MemTxAttrs
  target/arm: Add BT and BTYPE to tb->flags
  ...

Signed-off-by: default avatarPeter Maydell <peter.maydell@linaro.org>
parents 9669c975 a15945d9
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -1359,6 +1359,10 @@ static int gdb_handle_packet(GDBState *s, const char *line_buf)

            put_packet(s, buf);
            break;
        } else if (strncmp(p, "Kill;", 5) == 0) {
            /* Kill the target */
            error_report("QEMU: Terminated via GDBstub");
            exit(0);
        } else {
            goto unknown_command;
        }
+96 −70
Original line number Diff line number Diff line
@@ -949,9 +949,12 @@ static uint64_t load_aarch64_image(const char *filename, hwaddr mem_base,
    return size;
}

void arm_load_kernel(ARMCPU *cpu, struct arm_boot_info *info)
static void arm_setup_direct_kernel_boot(ARMCPU *cpu,
                                         struct arm_boot_info *info)
{
    /* Set up for a direct boot of a kernel image file. */
    CPUState *cs;
    AddressSpace *as = arm_boot_address_space(cpu, info);
    int kernel_size;
    int initrd_size;
    int is_linux = 0;
@@ -959,70 +962,6 @@ void arm_load_kernel(ARMCPU *cpu, struct arm_boot_info *info)
    int elf_machine;
    hwaddr entry;
    static const ARMInsnFixup *primary_loader;
    AddressSpace *as = arm_boot_address_space(cpu, info);

    /* CPU objects (unlike devices) are not automatically reset on system
     * reset, so we must always register a handler to do so. If we're
     * actually loading a kernel, the handler is also responsible for
     * arranging that we start it correctly.
     */
    for (cs = first_cpu; cs; cs = CPU_NEXT(cs)) {
        qemu_register_reset(do_cpu_reset, ARM_CPU(cs));
    }

    /* The board code is not supposed to set secure_board_setup unless
     * running its code in secure mode is actually possible, and KVM
     * doesn't support secure.
     */
    assert(!(info->secure_board_setup && kvm_enabled()));

    info->dtb_filename = qemu_opt_get(qemu_get_machine_opts(), "dtb");
    info->dtb_limit = 0;

    /* Load the kernel.  */
    if (!info->kernel_filename || info->firmware_loaded) {

        if (have_dtb(info)) {
            /* If we have a device tree blob, but no kernel to supply it to (or
             * the kernel is supposed to be loaded by the bootloader), copy the
             * DTB to the base of RAM for the bootloader to pick up.
             */
            info->dtb_start = info->loader_start;
        }

        if (info->kernel_filename) {
            FWCfgState *fw_cfg;
            bool try_decompressing_kernel;

            fw_cfg = fw_cfg_find();
            try_decompressing_kernel = arm_feature(&cpu->env,
                                                   ARM_FEATURE_AARCH64);

            /* Expose the kernel, the command line, and the initrd in fw_cfg.
             * We don't process them here at all, it's all left to the
             * firmware.
             */
            load_image_to_fw_cfg(fw_cfg,
                                 FW_CFG_KERNEL_SIZE, FW_CFG_KERNEL_DATA,
                                 info->kernel_filename,
                                 try_decompressing_kernel);
            load_image_to_fw_cfg(fw_cfg,
                                 FW_CFG_INITRD_SIZE, FW_CFG_INITRD_DATA,
                                 info->initrd_filename, false);

            if (info->kernel_cmdline) {
                fw_cfg_add_i32(fw_cfg, FW_CFG_CMDLINE_SIZE,
                               strlen(info->kernel_cmdline) + 1);
                fw_cfg_add_string(fw_cfg, FW_CFG_CMDLINE_DATA,
                                  info->kernel_cmdline);
            }
        }

        /* We will start from address 0 (typically a boot ROM image) in the
         * same way as hardware.
         */
        return;
    }

    if (arm_feature(&cpu->env, ARM_FEATURE_AARCH64)) {
        primary_loader = bootloader_aarch64;
@@ -1045,7 +984,8 @@ void arm_load_kernel(ARMCPU *cpu, struct arm_boot_info *info)
    if (info->nb_cpus == 0)
        info->nb_cpus = 1;

    /* We want to put the initrd far enough into RAM that when the
    /*
     * We want to put the initrd far enough into RAM that when the
     * kernel is uncompressed it will not clobber the initrd. However
     * on boards without much RAM we must ensure that we still leave
     * enough room for a decent sized initrd, and on boards with large
@@ -1062,12 +1002,14 @@ void arm_load_kernel(ARMCPU *cpu, struct arm_boot_info *info)
    kernel_size = arm_load_elf(info, &elf_entry, &elf_low_addr,
                               &elf_high_addr, elf_machine, as);
    if (kernel_size > 0 && have_dtb(info)) {
        /* If there is still some room left at the base of RAM, try and put
        /*
         * If there is still some room left at the base of RAM, try and put
         * the DTB there like we do for images loaded with -bios or -pflash.
         */
        if (elf_low_addr > info->loader_start
            || elf_high_addr < info->loader_start) {
            /* Set elf_low_addr as address limit for arm_load_dtb if it may be
            /*
             * Set elf_low_addr as address limit for arm_load_dtb if it may be
             * pointing into RAM, otherwise pass '0' (no limit)
             */
            if (elf_low_addr < info->loader_start) {
@@ -1128,7 +1070,8 @@ void arm_load_kernel(ARMCPU *cpu, struct arm_boot_info *info)
        fixupcontext[FIXUP_BOARDID] = info->board_id;
        fixupcontext[FIXUP_BOARD_SETUP] = info->board_setup_addr;

        /* for device tree boot, we pass the DTB directly in r2. Otherwise
        /*
         * for device tree boot, we pass the DTB directly in r2. Otherwise
         * we point to the kernel args.
         */
        if (have_dtb(info)) {
@@ -1181,7 +1124,8 @@ void arm_load_kernel(ARMCPU *cpu, struct arm_boot_info *info)
            info->write_board_setup(cpu, info);
        }

        /* Notify devices which need to fake up firmware initialization
        /*
         * Notify devices which need to fake up firmware initialization
         * that we're doing a direct kernel boot.
         */
        object_child_foreach_recursive(object_get_root(),
@@ -1192,6 +1136,88 @@ void arm_load_kernel(ARMCPU *cpu, struct arm_boot_info *info)
    for (cs = first_cpu; cs; cs = CPU_NEXT(cs)) {
        ARM_CPU(cs)->env.boot_info = info;
    }
}

static void arm_setup_firmware_boot(ARMCPU *cpu, struct arm_boot_info *info)
{
    /* Set up for booting firmware (which might load a kernel via fw_cfg) */

    if (have_dtb(info)) {
        /*
         * If we have a device tree blob, but no kernel to supply it to (or
         * the kernel is supposed to be loaded by the bootloader), copy the
         * DTB to the base of RAM for the bootloader to pick up.
         */
        info->dtb_start = info->loader_start;
    }

    if (info->kernel_filename) {
        FWCfgState *fw_cfg;
        bool try_decompressing_kernel;

        fw_cfg = fw_cfg_find();
        try_decompressing_kernel = arm_feature(&cpu->env,
                                               ARM_FEATURE_AARCH64);

        /*
         * Expose the kernel, the command line, and the initrd in fw_cfg.
         * We don't process them here at all, it's all left to the
         * firmware.
         */
        load_image_to_fw_cfg(fw_cfg,
                             FW_CFG_KERNEL_SIZE, FW_CFG_KERNEL_DATA,
                             info->kernel_filename,
                             try_decompressing_kernel);
        load_image_to_fw_cfg(fw_cfg,
                             FW_CFG_INITRD_SIZE, FW_CFG_INITRD_DATA,
                             info->initrd_filename, false);

        if (info->kernel_cmdline) {
            fw_cfg_add_i32(fw_cfg, FW_CFG_CMDLINE_SIZE,
                           strlen(info->kernel_cmdline) + 1);
            fw_cfg_add_string(fw_cfg, FW_CFG_CMDLINE_DATA,
                              info->kernel_cmdline);
        }
    }

    /*
     * We will start from address 0 (typically a boot ROM image) in the
     * same way as hardware. Leave env->boot_info NULL, so that
     * do_cpu_reset() knows it does not need to alter the PC on reset.
     */
}

void arm_load_kernel(ARMCPU *cpu, struct arm_boot_info *info)
{
    CPUState *cs;
    AddressSpace *as = arm_boot_address_space(cpu, info);

    /*
     * CPU objects (unlike devices) are not automatically reset on system
     * reset, so we must always register a handler to do so. If we're
     * actually loading a kernel, the handler is also responsible for
     * arranging that we start it correctly.
     */
    for (cs = first_cpu; cs; cs = CPU_NEXT(cs)) {
        qemu_register_reset(do_cpu_reset, ARM_CPU(cs));
    }

    /*
     * The board code is not supposed to set secure_board_setup unless
     * running its code in secure mode is actually possible, and KVM
     * doesn't support secure.
     */
    assert(!(info->secure_board_setup && kvm_enabled()));

    info->dtb_filename = qemu_opt_get(qemu_get_machine_opts(), "dtb");
    info->dtb_limit = 0;

    /* Load the kernel.  */
    if (!info->kernel_filename || info->firmware_loaded) {
        arm_setup_firmware_boot(cpu, info);
    } else {
        arm_setup_direct_kernel_boot(cpu, info);
    }

    if (!info->skip_dtb_autoload && have_dtb(info)) {
        if (arm_load_dtb(info->dtb_start, info, info->dtb_limit, as) < 0) {
+10 −0
Original line number Diff line number Diff line
@@ -37,6 +37,16 @@ typedef struct MemTxAttrs {
    unsigned int user:1;
    /* Requester ID (for MSI for example) */
    unsigned int requester_id:16;
    /*
     * The following are target-specific page-table bits.  These are not
     * related to actual memory transactions at all.  However, this structure
     * is part of the tlb_fill interface, cached in the cputlb structure,
     * and has unused bits.  These fields will be read by target-specific
     * helpers using env->iotlb[mmu_idx][tlb_index()].attrs.target_tlb_bitN.
     */
    unsigned int target_tlb_bit0 : 1;
    unsigned int target_tlb_bit1 : 1;
    unsigned int target_tlb_bit2 : 1;
} MemTxAttrs;

/* Bus masters which don't specify any attributes will get this,
+7 −0
Original line number Diff line number Diff line
@@ -22,6 +22,13 @@ struct target_pt_regs {
#define TARGET_PR_SVE_SET_VL  50
#define TARGET_PR_SVE_GET_VL  51

#define TARGET_PR_PAC_RESET_KEYS 54
# define TARGET_PR_PAC_APIAKEY   (1 << 0)
# define TARGET_PR_PAC_APIBKEY   (1 << 1)
# define TARGET_PR_PAC_APDAKEY   (1 << 2)
# define TARGET_PR_PAC_APDBKEY   (1 << 3)
# define TARGET_PR_PAC_APGAKEY   (1 << 4)

void arm_init_pauth_key(ARMPACKey *key);

#endif /* AARCH64_TARGET_SYSCALL_H */
+36 −0
Original line number Diff line number Diff line
@@ -9691,6 +9691,42 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
                }
            }
            return ret;
        case TARGET_PR_PAC_RESET_KEYS:
            {
                CPUARMState *env = cpu_env;
                ARMCPU *cpu = arm_env_get_cpu(env);

                if (arg3 || arg4 || arg5) {
                    return -TARGET_EINVAL;
                }
                if (cpu_isar_feature(aa64_pauth, cpu)) {
                    int all = (TARGET_PR_PAC_APIAKEY | TARGET_PR_PAC_APIBKEY |
                               TARGET_PR_PAC_APDAKEY | TARGET_PR_PAC_APDBKEY |
                               TARGET_PR_PAC_APGAKEY);
                    if (arg2 == 0) {
                        arg2 = all;
                    } else if (arg2 & ~all) {
                        return -TARGET_EINVAL;
                    }
                    if (arg2 & TARGET_PR_PAC_APIAKEY) {
                        arm_init_pauth_key(&env->apia_key);
                    }
                    if (arg2 & TARGET_PR_PAC_APIBKEY) {
                        arm_init_pauth_key(&env->apib_key);
                    }
                    if (arg2 & TARGET_PR_PAC_APDAKEY) {
                        arm_init_pauth_key(&env->apda_key);
                    }
                    if (arg2 & TARGET_PR_PAC_APDBKEY) {
                        arm_init_pauth_key(&env->apdb_key);
                    }
                    if (arg2 & TARGET_PR_PAC_APGAKEY) {
                        arm_init_pauth_key(&env->apga_key);
                    }
                    return 0;
                }
            }
            return -TARGET_EINVAL;
#endif /* AARCH64 */
        case PR_GET_SECCOMP:
        case PR_SET_SECCOMP:
Loading