Commit 786d36ad authored by Peter Maydell's avatar Peter Maydell
Browse files

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



target-arm queue:
 * Fix the CBAR register implementation for Cortex-A53,
   Cortex-A57, Cortex-A72
 * Fix direct booting of Linux kernels on emulated CPUs
   which have an AArch32 EL3 (incorrect NSACR settings
   meant they could not access the FPU)
 * semihosting cleanup: do more work at translate time
   and less work at runtime

# gpg: Signature made Fri 27 Sep 2019 15:32:43 BST
# 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-20190927:
  hw/arm/boot: Use the IEC binary prefix definitions
  hw/arm/boot.c: Set NSACR.{CP11,CP10} for NS kernel boots
  tests/tcg: add linux-user semihosting smoke test for ARM
  target/arm: remove run-time semihosting checks for linux-user
  target/arm: remove run time semihosting checks
  target/arm: handle A-profile semihosting at translate time
  target/arm: handle M-profile semihosting at translate time
  tests/tcg: clean-up some comments after the de-tangling
  target/arm: fix CBAR register for AArch64 CPUs

Signed-off-by: default avatarPeter Maydell <peter.maydell@linaro.org>

# Conflicts:
#	tests/tcg/arm/Makefile.target
parents 1e396381 e4e34855
Loading
Loading
Loading
Loading
+7 −5
Original line number Diff line number Diff line
@@ -575,7 +575,7 @@ int arm_load_dtb(hwaddr addr, const struct arm_boot_info *binfo,
        goto fail;
    }

    if (scells < 2 && binfo->ram_size >= (1ULL << 32)) {
    if (scells < 2 && binfo->ram_size >= 4 * GiB) {
        /* This is user error so deserves a friendlier error message
         * than the failure of setprop_sized_cells would provide
         */
@@ -754,6 +754,8 @@ static void do_cpu_reset(void *opaque)
                    (cs != first_cpu || !info->secure_board_setup)) {
                    /* Linux expects non-secure state */
                    env->cp15.scr_el3 |= SCR_NS;
                    /* Set NSACR.{CP11,CP10} so NS can access the FPU */
                    env->cp15.nsacr |= 3 << 10;
                }
            }

@@ -1095,7 +1097,7 @@ static void arm_setup_direct_kernel_boot(ARMCPU *cpu,
     * we might still make a bad choice here.
     */
    info->initrd_start = info->loader_start +
        MIN(info->ram_size / 2, 128 * 1024 * 1024);
        MIN(info->ram_size / 2, 128 * MiB);
    if (image_high_addr) {
        info->initrd_start = MAX(info->initrd_start, image_high_addr);
    }
@@ -1155,13 +1157,13 @@ static void arm_setup_direct_kernel_boot(ARMCPU *cpu,
                 *
                 * Let's play safe and prealign it to 2MB to give us some space.
                 */
                align = 2 * 1024 * 1024;
                align = 2 * MiB;
            } else {
                /*
                 * Some 32bit kernels will trash anything in the 4K page the
                 * initrd ends in, so make sure the DTB isn't caught up in that.
                 */
                align = 4096;
                align = 4 * KiB;
            }

            /* Place the DTB after the initrd in memory with alignment. */
@@ -1178,7 +1180,7 @@ static void arm_setup_direct_kernel_boot(ARMCPU *cpu,
                info->loader_start + KERNEL_ARGS_ADDR;
            fixupcontext[FIXUP_ARGPTR_HI] =
                (info->loader_start + KERNEL_ARGS_ADDR) >> 32;
            if (info->ram_size >= (1ULL << 32)) {
            if (info->ram_size >= 4 * GiB) {
                error_report("RAM size must be less than 4GB to boot"
                             " Linux kernel using ATAGS (try passing a device tree"
                             " using -dtb)");
+0 −3
Original line number Diff line number Diff line
@@ -325,9 +325,6 @@ void cpu_loop(CPUARMState *env)

                if (n == ARM_NR_cacheflush) {
                    /* nop */
                } else if (n == ARM_NR_semihosting
                           || n == ARM_NR_thumb_semihosting) {
                    env->regs[0] = do_arm_semihosting (env);
                } else if (n == 0 || n >= ARM_SYSCALL_BASE || env->thumb) {
                    /* linux syscall */
                    if (env->thumb || n == 0) {
+0 −3
Original line number Diff line number Diff line
@@ -18,9 +18,6 @@ struct target_pt_regs {
#define ARM_NR_set_tls	  (ARM_NR_BASE + 5)
#define ARM_NR_get_tls    (ARM_NR_BASE + 6)

#define ARM_NR_semihosting	  0x123456
#define ARM_NR_thumb_semihosting  0xAB

#if defined(TARGET_WORDS_BIGENDIAN)
#define UNAME_MACHINE "armv5teb"
#else
+38 −77
Original line number Diff line number Diff line
@@ -6733,6 +6733,19 @@ void register_cp_regs_for_features(ARMCPU *cpu)
    }

    if (arm_feature(env, ARM_FEATURE_CBAR)) {
        /*
         * CBAR is IMPDEF, but common on Arm Cortex-A implementations.
         * There are two flavours:
         *  (1) older 32-bit only cores have a simple 32-bit CBAR
         *  (2) 64-bit cores have a 64-bit CBAR visible to AArch64, plus a
         *      32-bit register visible to AArch32 at a different encoding
         *      to the "flavour 1" register and with the bits rearranged to
         *      be able to squash a 64-bit address into the 32-bit view.
         * We distinguish the two via the ARM_FEATURE_AARCH64 flag, but
         * in future if we support AArch32-only configs of some of the
         * AArch64 cores we might need to add a specific feature flag
         * to indicate cores with "flavour 2" CBAR.
         */
        if (arm_feature(env, ARM_FEATURE_AARCH64)) {
            /* 32 bit view is [31:18] 0...0 [43:32]. */
            uint32_t cbar32 = (extract64(cpu->reset_cbar, 18, 14) << 18)
@@ -6740,12 +6753,12 @@ void register_cp_regs_for_features(ARMCPU *cpu)
            ARMCPRegInfo cbar_reginfo[] = {
                { .name = "CBAR",
                  .type = ARM_CP_CONST,
                  .cp = 15, .crn = 15, .crm = 0, .opc1 = 4, .opc2 = 0,
                  .access = PL1_R, .resetvalue = cpu->reset_cbar },
                  .cp = 15, .crn = 15, .crm = 3, .opc1 = 1, .opc2 = 0,
                  .access = PL1_R, .resetvalue = cbar32 },
                { .name = "CBAR_EL1", .state = ARM_CP_STATE_AA64,
                  .type = ARM_CP_CONST,
                  .opc0 = 3, .opc1 = 1, .crn = 15, .crm = 3, .opc2 = 0,
                  .access = PL1_R, .resetvalue = cbar32 },
                  .access = PL1_R, .resetvalue = cpu->reset_cbar },
                REGINFO_SENTINEL
            };
            /* We don't implement a r/w 64 bit CBAR currently */
@@ -8339,88 +8352,32 @@ static void arm_cpu_do_interrupt_aarch64(CPUState *cs)
                  new_el, env->pc, pstate_read(env));
}

static inline bool check_for_semihosting(CPUState *cs)
{
#ifdef CONFIG_TCG
    /* Check whether this exception is a semihosting call; if so
     * then handle it and return true; otherwise return false.
/*
 * Do semihosting call and set the appropriate return value. All the
 * permission and validity checks have been done at translate time.
 *
 * We only see semihosting exceptions in TCG only as they are not
 * trapped to the hypervisor in KVM.
 */
#ifdef CONFIG_TCG
static void handle_semihosting(CPUState *cs)
{
    ARMCPU *cpu = ARM_CPU(cs);
    CPUARMState *env = &cpu->env;

    if (is_a64(env)) {
        if (cs->exception_index == EXCP_SEMIHOST) {
            /* This is always the 64-bit semihosting exception.
             * The "is this usermode" and "is semihosting enabled"
             * checks have been done at translate time.
             */
        qemu_log_mask(CPU_LOG_INT,
                      "...handling as semihosting call 0x%" PRIx64 "\n",
                      env->xregs[0]);
        env->xregs[0] = do_arm_semihosting(env);
            return true;
        }
        return false;
    } else {
        uint32_t imm;

        /* Only intercept calls from privileged modes, to provide some
         * semblance of security.
         */
        if (cs->exception_index != EXCP_SEMIHOST &&
            (!semihosting_enabled() ||
             ((env->uncached_cpsr & CPSR_M) == ARM_CPU_MODE_USR))) {
            return false;
        }

        switch (cs->exception_index) {
        case EXCP_SEMIHOST:
            /* This is always a semihosting call; the "is this usermode"
             * and "is semihosting enabled" checks have been done at
             * translate time.
             */
            break;
        case EXCP_SWI:
            /* Check for semihosting interrupt.  */
            if (env->thumb) {
                imm = arm_lduw_code(env, env->regs[15] - 2, arm_sctlr_b(env))
                    & 0xff;
                if (imm == 0xab) {
                    break;
                }
            } else {
                imm = arm_ldl_code(env, env->regs[15] - 4, arm_sctlr_b(env))
                    & 0xffffff;
                if (imm == 0x123456) {
                    break;
                }
            }
            return false;
        case EXCP_BKPT:
            /* See if this is a semihosting syscall.  */
            if (env->thumb) {
                imm = arm_lduw_code(env, env->regs[15], arm_sctlr_b(env))
                    & 0xff;
                if (imm == 0xab) {
                    env->regs[15] += 2;
                    break;
                }
            }
            return false;
        default:
            return false;
        }

        qemu_log_mask(CPU_LOG_INT,
                      "...handling as semihosting call 0x%x\n",
                      env->regs[0]);
        env->regs[0] = do_arm_semihosting(env);
        return true;
    }
#else
    return false;
#endif
}
#endif

/* Handle a CPU exception for A and R profile CPUs.
 * Do any appropriate logging, handle PSCI calls, and then hand off
@@ -8451,13 +8408,17 @@ void arm_cpu_do_interrupt(CPUState *cs)
        return;
    }

    /* Semihosting semantics depend on the register width of the
     * code that caused the exception, not the target exception level,
     * so must be handled here.
    /*
     * Semihosting semantics depend on the register width of the code
     * that caused the exception, not the target exception level, so
     * must be handled here.
     */
    if (check_for_semihosting(cs)) {
#ifdef CONFIG_TCG
    if (cs->exception_index == EXCP_SEMIHOST) {
        handle_semihosting(cs);
        return;
    }
#endif

    /* Hooks may change global state so BQL should be held, also the
     * BQL needs to be held for any modification of
+6 −12
Original line number Diff line number Diff line
@@ -2114,19 +2114,13 @@ void arm_v7m_cpu_do_interrupt(CPUState *cs)
            break;
        }
        break;
    case EXCP_BKPT:
        if (semihosting_enabled()) {
            int nr;
            nr = arm_lduw_code(env, env->regs[15], arm_sctlr_b(env)) & 0xff;
            if (nr == 0xab) {
                env->regs[15] += 2;
    case EXCP_SEMIHOST:
        qemu_log_mask(CPU_LOG_INT,
                      "...handling as semihosting call 0x%x\n",
                      env->regs[0]);
        env->regs[0] = do_arm_semihosting(env);
        return;
            }
        }
    case EXCP_BKPT:
        armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_DEBUG, false);
        break;
    case EXCP_IRQ:
Loading