From patchwork Thu Jan 21 14:56:23 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Peter Maydell X-Patchwork-Id: 8082001 Return-Path: X-Original-To: patchwork-qemu-devel@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork1.web.kernel.org (Postfix) with ESMTP id 506389F1CC for ; Thu, 21 Jan 2016 14:58:57 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 7C50A20511 for ; Thu, 21 Jan 2016 14:58:52 +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 8091B204E3 for ; Thu, 21 Jan 2016 14:58:51 +0000 (UTC) Received: from localhost ([::1]:48048 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1aMGhG-0006CM-SH for patchwork-qemu-devel@patchwork.kernel.org; Thu, 21 Jan 2016 09:58:50 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:45436) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1aMGfC-0002QU-4W for qemu-devel@nongnu.org; Thu, 21 Jan 2016 09:56:43 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1aMGfA-0002jf-JV for qemu-devel@nongnu.org; Thu, 21 Jan 2016 09:56:42 -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-CH 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-0003RZ-5y 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:23 +0000 Message-Id: <1453388189-13092-31-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 30/36] target-arm: Use a single entry point for AArch64 and AArch32 exceptions 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 If EL2 or EL3 is present on an AArch64 CPU, then exceptions can be taken to an exception level which is running AArch32 (if only EL0 and EL1 are present then EL1 must be AArch64 and all exceptions are taken to AArch64). To support this we need to have a single implementation of the CPU do_interrupt() method which can handle both 32 and 64 bit exception entry. Pull the common parts of aarch64_cpu_do_interrupt() and arm_cpu_do_interrupt() out into a new function which calls either the AArch32 or AArch64 specific entry code once it has worked out which one is needed. We temporarily special-case the handling of EXCP_SEMIHOST to avoid an assertion in arm_el_is_aa64(); the next patch will pull all the semihosting handling out to the arm_cpu_do_interrupt() level (since semihosting semantics depend on the register width of the calling code, not on that of any higher EL). Signed-off-by: Peter Maydell Reviewed-by: Edgar E. Iglesias --- target-arm/cpu-qom.h | 2 -- target-arm/cpu64.c | 3 --- target-arm/helper.c | 75 ++++++++++++++++++++++++++++++---------------------- 3 files changed, 44 insertions(+), 36 deletions(-) diff --git a/target-arm/cpu-qom.h b/target-arm/cpu-qom.h index 979e1ee..07c0a71 100644 --- a/target-arm/cpu-qom.h +++ b/target-arm/cpu-qom.h @@ -254,6 +254,4 @@ int aarch64_cpu_gdb_read_register(CPUState *cpu, uint8_t *buf, int reg); int aarch64_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg); #endif -void aarch64_cpu_do_interrupt(CPUState *cs); - #endif diff --git a/target-arm/cpu64.c b/target-arm/cpu64.c index 5f8a177..cc177bb 100644 --- a/target-arm/cpu64.c +++ b/target-arm/cpu64.c @@ -291,9 +291,6 @@ static void aarch64_cpu_class_init(ObjectClass *oc, void *data) { CPUClass *cc = CPU_CLASS(oc); -#if !defined(CONFIG_USER_ONLY) - cc->do_interrupt = aarch64_cpu_do_interrupt; -#endif cc->cpu_exec_interrupt = arm_cpu_exec_interrupt; cc->set_pc = aarch64_cpu_set_pc; cc->gdb_read_register = aarch64_cpu_gdb_read_register; diff --git a/target-arm/helper.c b/target-arm/helper.c index 573e155..8f3a457 100644 --- a/target-arm/helper.c +++ b/target-arm/helper.c @@ -5708,8 +5708,7 @@ void aarch64_sync_64_to_32(CPUARMState *env) env->regs[15] = env->pc; } -/* Handle a CPU exception. */ -void arm_cpu_do_interrupt(CPUState *cs) +static void arm_cpu_do_interrupt_aarch32(CPUState *cs) { ARMCPU *cpu = ARM_CPU(cs); CPUARMState *env = &cpu->env; @@ -5719,16 +5718,6 @@ void arm_cpu_do_interrupt(CPUState *cs) uint32_t offset; uint32_t moe; - assert(!IS_M(env)); - - arm_log_exception(cs->exception_index); - - if (arm_is_psci_call(cpu, cs->exception_index)) { - arm_handle_psci_call(cpu); - qemu_log_mask(CPU_LOG_INT, "...handled as PSCI call\n"); - return; - } - /* If this is a debug exception we must update the DBGDSCR.MOE bits */ switch (env->exception.syndrome >> ARM_EL_EC_SHIFT) { case EC_BREAKPOINT: @@ -5900,11 +5889,10 @@ void arm_cpu_do_interrupt(CPUState *cs) } env->regs[14] = env->regs[15] + offset; env->regs[15] = addr; - cs->interrupt_request |= CPU_INTERRUPT_EXITTB; } -/* Handle a CPU exception. */ -void aarch64_cpu_do_interrupt(CPUState *cs) +/* Handle exception entry to a target EL which is using AArch64 */ +static void arm_cpu_do_interrupt_aarch64(CPUState *cs) { ARMCPU *cpu = ARM_CPU(cs); CPUARMState *env = &cpu->env; @@ -5922,22 +5910,6 @@ void aarch64_cpu_do_interrupt(CPUState *cs) addr += 0x200; } - arm_log_exception(cs->exception_index); - qemu_log_mask(CPU_LOG_INT, "...from EL%d to EL%d\n", arm_current_el(env), - new_el); - if (qemu_loglevel_mask(CPU_LOG_INT) - && !excp_is_internal(cs->exception_index)) { - qemu_log_mask(CPU_LOG_INT, "...with ESR %x/0x%" PRIx32 "\n", - env->exception.syndrome >> ARM_EL_EC_SHIFT, - env->exception.syndrome); - } - - if (arm_is_psci_call(cpu, cs->exception_index)) { - arm_handle_psci_call(cpu); - qemu_log_mask(CPU_LOG_INT, "...handled as PSCI call\n"); - return; - } - switch (cs->exception_index) { case EXCP_PREFETCH_ABORT: case EXCP_DATA_ABORT: @@ -5997,6 +5969,47 @@ void aarch64_cpu_do_interrupt(CPUState *cs) qemu_log_mask(CPU_LOG_INT, "...to EL%d PC 0x%" PRIx64 " PSTATE 0x%x\n", new_el, env->pc, pstate_read(env)); +} + +/* 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 + * target exception level's register width. + */ +void arm_cpu_do_interrupt(CPUState *cs) +{ + ARMCPU *cpu = ARM_CPU(cs); + CPUARMState *env = &cpu->env; + unsigned int new_el = env->exception.target_el; + + assert(!IS_M(env)); + + arm_log_exception(cs->exception_index); + qemu_log_mask(CPU_LOG_INT, "...from EL%d to EL%d\n", arm_current_el(env), + new_el); + if (qemu_loglevel_mask(CPU_LOG_INT) + && !excp_is_internal(cs->exception_index)) { + qemu_log_mask(CPU_LOG_INT, "...with ESR %x/0x%" PRIx32 "\n", + env->exception.syndrome >> ARM_EL_EC_SHIFT, + env->exception.syndrome); + } + + if (arm_is_psci_call(cpu, cs->exception_index)) { + arm_handle_psci_call(cpu); + qemu_log_mask(CPU_LOG_INT, "...handled as PSCI call\n"); + 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. + */ + if (cs->exception_index == EXCP_SEMIHOST || arm_el_is_aa64(env, new_el)) { + arm_cpu_do_interrupt_aarch64(cs); + } else { + arm_cpu_do_interrupt_aarch32(cs); + } if (!kvm_enabled()) { cs->interrupt_request |= CPU_INTERRUPT_EXITTB;