From patchwork Thu Jan 21 14:56:24 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Peter Maydell X-Patchwork-Id: 8082011 Return-Path: X-Original-To: patchwork-qemu-devel@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 6473CBEEE5 for ; Thu, 21 Jan 2016 15:00:32 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id CC51420303 for ; Thu, 21 Jan 2016 15:00:27 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id AB384204F6 for ; Thu, 21 Jan 2016 15:00:25 +0000 (UTC) Received: from localhost ([::1]:48061 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1aMGin-0000wZ-5S for patchwork-qemu-devel@patchwork.kernel.org; Thu, 21 Jan 2016 10:00:25 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:45413) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1aMGfB-0002QS-FI for qemu-devel@nongnu.org; Thu, 21 Jan 2016 09:56:42 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1aMGfA-0002jY-A5 for qemu-devel@nongnu.org; Thu, 21 Jan 2016 09:56:41 -0500 Received: from mnementh.archaic.org.uk ([2001:8b0:1d0::1]:59496) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1aMGfA-0002g6-2E for qemu-devel@nongnu.org; Thu, 21 Jan 2016 09:56:40 -0500 Received: from pm215 by mnementh.archaic.org.uk with local (Exim 4.80) (envelope-from ) id 1aMGf0-0003Rd-7C for qemu-devel@nongnu.org; Thu, 21 Jan 2016 14:56:30 +0000 From: Peter Maydell To: qemu-devel@nongnu.org Date: Thu, 21 Jan 2016 14:56:24 +0000 Message-Id: <1453388189-13092-32-git-send-email-peter.maydell@linaro.org> X-Mailer: git-send-email 1.7.10.4 In-Reply-To: <1453388189-13092-1-git-send-email-peter.maydell@linaro.org> References: <1453388189-13092-1-git-send-email-peter.maydell@linaro.org> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x X-Received-From: 2001:8b0:1d0::1 Subject: [Qemu-devel] [PULL 31/36] target-arm: Pull semihosting handling out to arm_cpu_do_interrupt() X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org X-Spam-Status: No, score=-6.9 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Handling of semihosting calls should depend on the register width of the calling code, not on that of any higher exception level, so we need to identify and handle semihosting calls before we decide whether to deliver the exception as an entry to AArch32 or AArch64. (EXCP_SEMIHOST is also an "internal exception" so it has no target exception level in the first place.) This will allow AArch32 EL1 code to use semihosting calls when running under an AArch64 EL3. Signed-off-by: Peter Maydell --- target-arm/helper.c | 120 +++++++++++++++++++++++++++++++++++----------------- 1 file changed, 81 insertions(+), 39 deletions(-) diff --git a/target-arm/helper.c b/target-arm/helper.c index 8f3a457..90c985a 100644 --- a/target-arm/helper.c +++ b/target-arm/helper.c @@ -5755,27 +5755,6 @@ static void arm_cpu_do_interrupt_aarch32(CPUState *cs) offset = 4; break; case EXCP_SWI: - if (semihosting_enabled()) { - /* Check for semihosting interrupt. */ - if (env->thumb) { - mask = arm_lduw_code(env, env->regs[15] - 2, env->bswap_code) - & 0xff; - } else { - mask = arm_ldl_code(env, env->regs[15] - 4, env->bswap_code) - & 0xffffff; - } - /* Only intercept calls from privileged modes, to provide some - semblance of security. */ - if (((mask == 0x123456 && !env->thumb) - || (mask == 0xab && env->thumb)) - && (env->uncached_cpsr & CPSR_M) != ARM_CPU_MODE_USR) { - qemu_log_mask(CPU_LOG_INT, - "...handling as semihosting call 0x%x\n", - env->regs[0]); - env->regs[0] = do_arm_semihosting(env); - return; - } - } new_mode = ARM_CPU_MODE_SVC; addr = 0x08; mask = CPSR_I; @@ -5783,19 +5762,6 @@ static void arm_cpu_do_interrupt_aarch32(CPUState *cs) offset = 0; break; case EXCP_BKPT: - /* See if this is a semihosting syscall. */ - if (env->thumb && semihosting_enabled()) { - mask = arm_lduw_code(env, env->regs[15], env->bswap_code) & 0xff; - if (mask == 0xab - && (env->uncached_cpsr & CPSR_M) != ARM_CPU_MODE_USR) { - env->regs[15] += 2; - qemu_log_mask(CPU_LOG_INT, - "...handling as semihosting call 0x%x\n", - env->regs[0]); - env->regs[0] = do_arm_semihosting(env); - return; - } - } env->exception.fsr = 2; /* Fall through to prefetch abort. */ case EXCP_PREFETCH_ABORT: @@ -5971,6 +5937,78 @@ static void arm_cpu_do_interrupt_aarch64(CPUState *cs) new_el, env->pc, pstate_read(env)); } +static inline bool check_for_semihosting(CPUState *cs) +{ + /* Check whether this exception is a semihosting call; if so + * then handle it and return true; otherwise return false. + */ + 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 (!semihosting_enabled() || + ((env->uncached_cpsr & CPSR_M) == ARM_CPU_MODE_USR)) { + return false; + } + + switch (cs->exception_index) { + case EXCP_SWI: + /* Check for semihosting interrupt. */ + if (env->thumb) { + imm = arm_lduw_code(env, env->regs[15] - 2, env->bswap_code) + & 0xff; + if (imm == 0xab) { + break; + } + } else { + imm = arm_ldl_code(env, env->regs[15] - 4, env->bswap_code) + & 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], env->bswap_code) + & 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; + } +} + /* Handle a CPU exception for A and R profile CPUs. * Do any appropriate logging, handle PSCI calls, and then hand off * to the AArch64-entry or AArch32-entry function depending on the @@ -6000,12 +6038,16 @@ void arm_cpu_do_interrupt(CPUState *cs) return; } - /* Temporary special case for EXCP_SEMIHOST, which is used only - * for 64-bit semihosting calls -- as this is an internal exception - * it has no specified target level and arm_el_is_aa64() would - * assert because new_el could be 0. + /* 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 (cs->exception_index == EXCP_SEMIHOST || arm_el_is_aa64(env, new_el)) { + if (check_for_semihosting(cs)) { + return; + } + + assert(!excp_is_internal(cs->exception_index)); + if (arm_el_is_aa64(env, new_el)) { arm_cpu_do_interrupt_aarch64(cs); } else { arm_cpu_do_interrupt_aarch32(cs);