From patchwork Fri Jun 4 15:52:27 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Alex_Benn=C3=A9e?= X-Patchwork-Id: 454137 Delivered-To: patch@linaro.org Received: by 2002:a02:735a:0:0:0:0:0 with SMTP id a26csp619063jae; Fri, 4 Jun 2021 10:36:57 -0700 (PDT) X-Google-Smtp-Source: ABdhPJxoLfBtHgMPath0vbZVzvnQIZJUjlWv8MZY6UTZj8rMIVP3mLfqxskZq24xBuquI8K/vsEF X-Received: by 2002:a05:6102:32d1:: with SMTP id o17mr3643146vss.38.1622828217059; Fri, 04 Jun 2021 10:36:57 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1622828217; cv=none; d=google.com; s=arc-20160816; b=AnC7u6ghPGw9ve2t5LEaB469+s4ayFqmvpshiFTuKackn03ZlZDGu8sr1yek9DxN2B UaaErMV4+C6jOxfksFl+9sQoRD0hNMDY9bEuUCyg4yOsAHhMStF+iEHbNXGJjRfQnkuC sFVjYJOUj6iT61EFfSl3x//GiSUs0W8cXvXRvs5JkPPIFgHzeG4U8Mc6X2f8y5PvT/Du 3dK1N2gQ8650sVKEF0TTc0XZemKB3Uu+BmEyhSzdyvk8p2YcRjuU4ykHetrygXcTqnUj ADO+gDbZSvfONKlZruEmUl0Y3Wawukcvem17NboJEYPfc0SrRLWIprPRqk2qeXihT1bc 765Q== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:cc:list-subscribe:list-help:list-post:list-archive :list-unsubscribe:list-id:precedence:content-transfer-encoding :mime-version:references:in-reply-to:message-id:date:subject:to:from :dkim-signature; bh=lmCIQoI/Hkin0XFZ5JHEI3PAYwX9z71nEbOHIAi16Pg=; b=Ap8Z+ROwbLnWcyJgmuVA/DfvHHDgAku4mfe+2H2Fw19zsKvbI0v4Hc3bDYg9Fa8xkW hmRSs456wYYPrUsBvg6bDL0uus5Bt6Jzido0hIfBy3zRgiDbQHz7FQUoByy5PO7YpwgA dwK7wBAuHaIK4Fh1rdpRrzWBxeotYy3TLRCzyneEJliWf7BF00mEqGDXTk482U8RSq45 pFU/IN3MVI0MULYlcE7CBYbVojBRZJfJHMB8On5vgGHCTOqmRp3ZcpV5EdQg6yn9+f30 WBzkBb3kyaGAi67dvUwAJwtd91sk7Fx3EU/3c/2sxjlRgYjiL3teV5NU5xkVS+kAv33m /aTA== ARC-Authentication-Results: i=1; mx.google.com; dkim=fail header.i=@linaro.org header.s=google header.b="x0K7/fo1"; spf=pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom="qemu-devel-bounces+patch=linaro.org@nongnu.org"; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from lists.gnu.org (lists.gnu.org. [209.51.188.17]) by mx.google.com with ESMTPS id f7si3203308uav.6.2021.06.04.10.36.56 for (version=TLS1_2 cipher=ECDHE-ECDSA-CHACHA20-POLY1305 bits=256/256); Fri, 04 Jun 2021 10:36:57 -0700 (PDT) Received-SPF: pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; Authentication-Results: mx.google.com; dkim=fail header.i=@linaro.org header.s=google header.b="x0K7/fo1"; spf=pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom="qemu-devel-bounces+patch=linaro.org@nongnu.org"; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: from localhost ([::1]:47334 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1lpDke-0004F2-Ef for patch@linaro.org; Fri, 04 Jun 2021 13:36:56 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:48892) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1lpDNQ-0000B2-TO for qemu-devel@nongnu.org; Fri, 04 Jun 2021 13:12:56 -0400 Received: from mail-wm1-x331.google.com ([2a00:1450:4864:20::331]:42557) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1lpDNN-00026i-Kb for qemu-devel@nongnu.org; Fri, 04 Jun 2021 13:12:56 -0400 Received: by mail-wm1-x331.google.com with SMTP id o2-20020a05600c4fc2b029019a0a8f959dso6023646wmq.1 for ; Fri, 04 Jun 2021 10:12:53 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=lmCIQoI/Hkin0XFZ5JHEI3PAYwX9z71nEbOHIAi16Pg=; b=x0K7/fo1kZ7VOCuu1I82VF1/QpE4oHyI4nH9FqDjSzQ2GkZFh60QFERWEgRoOdlMae 6LMirwwZU3Lxy5dx/WTMCyM+JK2pvfrfxoHBS8g9uVQcJAZumEN6aO6D41H5gR4UcL9I tf2HSnF68SqBsFzjIVpUNcop0yfDwmGbhbtwsEhCjQxadyCdkexV71AGVEtWY1HSRuZE SMd5wrNVtuWWV+GMZXWBVl2mRtX2nzeJ8UeGisYVufhIr/dblrgrWKdiq91qG3nlQm1z 3pVj80KEU9jGDOIqnzRVO36UeHJBn1z8JPAUSWspXkUa8sIVd2wV3uMlKrF/CehmaZCK 4gAA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=lmCIQoI/Hkin0XFZ5JHEI3PAYwX9z71nEbOHIAi16Pg=; b=tNNKR2qpXGdutqnmawQcBpU5xYF1BsR+StLCPC9/WvRU1b2ADUqUreNUbil175ZXua HweONR1WA8MGU2yHTB5Bd8b5mbV5KOrI0mwZ44i8gOXxkgYYuU5EtMoqNrTKRlkCmVMY SHij2fp6LyFuIxOw+cCE+Md70tzW5TufhDY0JRgDrVoU4Fy+rDpkfcAZU/R5IeqVkqzr RDbPYb1seNbOF9wH64jTnJAelL/SgYuyI9DBSbD1AJJKxDqxMaZwm3N//cmwKykpquUm ILEUeehvsZrLn3DfaM+Lckf49k9MiD40gXMwnodZvI79cjXWIBJIhQTmfabQIOn/mAkP 5fMw== X-Gm-Message-State: AOAM530rTYBZ0/i0IKbV4hFLlxjqNAomMJZyrgApcuGKXgRBDWCMM3jM IL9FicT6KO4HPruyiMycROUu/Q== X-Received: by 2002:a05:600c:4f48:: with SMTP id m8mr4621691wmq.169.1622826772025; Fri, 04 Jun 2021 10:12:52 -0700 (PDT) Received: from zen.linaroharston ([51.148.130.216]) by smtp.gmail.com with ESMTPSA id q5sm6172567wmc.0.2021.06.04.10.12.42 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 04 Jun 2021 10:12:46 -0700 (PDT) Received: from zen.lan (localhost [127.0.0.1]) by zen.linaroharston (Postfix) with ESMTP id 744F01FFCD; Fri, 4 Jun 2021 16:53:19 +0100 (BST) From: =?utf-8?q?Alex_Benn=C3=A9e?= To: qemu-devel@nongnu.org Subject: [PATCH v16 54/99] target/arm: move TCGCPUOps to tcg/tcg-cpu.c Date: Fri, 4 Jun 2021 16:52:27 +0100 Message-Id: <20210604155312.15902-55-alex.bennee@linaro.org> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20210604155312.15902-1-alex.bennee@linaro.org> References: <20210604155312.15902-1-alex.bennee@linaro.org> MIME-Version: 1.0 Received-SPF: pass client-ip=2a00:1450:4864:20::331; envelope-from=alex.bennee@linaro.org; helo=mail-wm1-x331.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Peter Maydell , qemu-arm@nongnu.org, =?utf-8?q?Alex_Benn=C3=A9e?= , Claudio Fontana Errors-To: qemu-devel-bounces+patch=linaro.org@nongnu.org Sender: "Qemu-devel" From: Claudio Fontana move the TCGCPUOps interface to tcg/tcg-cpu.c in preparation for the addition of the TCG accel-cpu class. Signed-off-by: Claudio Fontana Signed-off-by: Alex Bennée --- target/arm/cpu.h | 1 - target/arm/internals.h | 5 - target/arm/tcg/tcg-cpu.h | 6 + target/arm/cpu-sysemu.c | 4 + target/arm/cpu.c | 210 +--------------------------------- target/arm/cpu_tcg.c | 2 +- target/arm/tcg/helper.c | 1 + target/arm/tcg/tcg-cpu.c | 229 +++++++++++++++++++++++++++++++++++++ target/arm/tcg/meson.build | 1 + 9 files changed, 244 insertions(+), 215 deletions(-) create mode 100644 target/arm/tcg/tcg-cpu.c -- 2.20.1 Reviewed-by: Richard Henderson diff --git a/target/arm/cpu.h b/target/arm/cpu.h index c5ead3365f..e528873ed3 100644 --- a/target/arm/cpu.h +++ b/target/arm/cpu.h @@ -1031,7 +1031,6 @@ extern const VMStateDescription vmstate_arm_cpu; void arm_cpu_do_interrupt(CPUState *cpu); void arm_v7m_cpu_do_interrupt(CPUState *cpu); -bool arm_cpu_exec_interrupt(CPUState *cpu, int int_req); int arm_cpu_gdb_read_register(CPUState *cpu, GByteArray *buf, int reg); int arm_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg); diff --git a/target/arm/internals.h b/target/arm/internals.h index c41f91f1c0..227a80ec21 100644 --- a/target/arm/internals.h +++ b/target/arm/internals.h @@ -173,11 +173,6 @@ static inline int r14_bank_number(int mode) void arm_cpu_register_gdb_regs_for_features(ARMCPU *cpu); void arm_translate_init(void); -#ifdef CONFIG_TCG -void arm_cpu_synchronize_from_tb(CPUState *cs, const TranslationBlock *tb); -#endif /* CONFIG_TCG */ - - enum arm_fprounding { FPROUNDING_TIEEVEN, FPROUNDING_POSINF, diff --git a/target/arm/tcg/tcg-cpu.h b/target/arm/tcg/tcg-cpu.h index 7e62f92d16..d93c6a6749 100644 --- a/target/arm/tcg/tcg-cpu.h +++ b/target/arm/tcg/tcg-cpu.h @@ -21,6 +21,12 @@ #define ARM_TCG_CPU_H #include "cpu.h" +#include "hw/core/tcg-cpu-ops.h" + +void arm_cpu_synchronize_from_tb(CPUState *cs, + const TranslationBlock *tb); + +extern struct TCGCPUOps arm_tcg_ops; #ifndef CONFIG_USER_ONLY /* Do semihosting call and set the appropriate return value. */ diff --git a/target/arm/cpu-sysemu.c b/target/arm/cpu-sysemu.c index e83d55b9f7..c09c89eeac 100644 --- a/target/arm/cpu-sysemu.c +++ b/target/arm/cpu-sysemu.c @@ -28,6 +28,10 @@ #include "sysemu/tcg.h" #include "tcg/tcg-cpu.h" +#ifdef CONFIG_TCG +#include "tcg/tcg-cpu.h" +#endif /* CONFIG_TCG */ + void arm_cpu_set_irq(void *opaque, int irq, int level) { ARMCPU *cpu = opaque; diff --git a/target/arm/cpu.c b/target/arm/cpu.c index 97d562bbd5..192700fe8f 100644 --- a/target/arm/cpu.c +++ b/target/arm/cpu.c @@ -27,7 +27,7 @@ #include "cpu.h" #include "cpregs.h" #ifdef CONFIG_TCG -#include "hw/core/tcg-cpu-ops.h" +#include "tcg/tcg-cpu.h" #endif /* CONFIG_TCG */ #include "cpu32.h" #include "internals.h" @@ -58,25 +58,6 @@ static void arm_cpu_set_pc(CPUState *cs, vaddr value) } } -#ifdef CONFIG_TCG -void arm_cpu_synchronize_from_tb(CPUState *cs, - const TranslationBlock *tb) -{ - ARMCPU *cpu = ARM_CPU(cs); - CPUARMState *env = &cpu->env; - - /* - * It's OK to look at env for the current mode here, because it's - * never possible for an AArch64 TB to chain to an AArch32 TB. - */ - if (is_a64(env)) { - env->pc = tb->pc; - } else { - env->regs[15] = tb->pc; - } -} -#endif /* CONFIG_TCG */ - static bool arm_cpu_has_work(CPUState *cs) { ARMCPU *cpu = ARM_CPU(cs); @@ -442,175 +423,6 @@ static void arm_cpu_reset(DeviceState *dev) } } -static inline bool arm_excp_unmasked(CPUState *cs, unsigned int excp_idx, - unsigned int target_el, - unsigned int cur_el, bool secure, - uint64_t hcr_el2) -{ - CPUARMState *env = cs->env_ptr; - bool pstate_unmasked; - bool unmasked = false; - - /* - * Don't take exceptions if they target a lower EL. - * This check should catch any exceptions that would not be taken - * but left pending. - */ - if (cur_el > target_el) { - return false; - } - - switch (excp_idx) { - case EXCP_FIQ: - pstate_unmasked = !(env->daif & PSTATE_F); - break; - - case EXCP_IRQ: - pstate_unmasked = !(env->daif & PSTATE_I); - break; - - case EXCP_VFIQ: - if (!(hcr_el2 & HCR_FMO) || (hcr_el2 & HCR_TGE)) { - /* VFIQs are only taken when hypervized. */ - return false; - } - return !(env->daif & PSTATE_F); - case EXCP_VIRQ: - if (!(hcr_el2 & HCR_IMO) || (hcr_el2 & HCR_TGE)) { - /* VIRQs are only taken when hypervized. */ - return false; - } - return !(env->daif & PSTATE_I); - default: - g_assert_not_reached(); - } - - /* - * Use the target EL, current execution state and SCR/HCR settings to - * determine whether the corresponding CPSR bit is used to mask the - * interrupt. - */ - if ((target_el > cur_el) && (target_el != 1)) { - /* Exceptions targeting a higher EL may not be maskable */ - if (arm_feature(env, ARM_FEATURE_AARCH64)) { - /* - * 64-bit masking rules are simple: exceptions to EL3 - * can't be masked, and exceptions to EL2 can only be - * masked from Secure state. The HCR and SCR settings - * don't affect the masking logic, only the interrupt routing. - */ - if (target_el == 3 || !secure || (env->cp15.scr_el3 & SCR_EEL2)) { - unmasked = true; - } - } else { - /* - * The old 32-bit-only environment has a more complicated - * masking setup. HCR and SCR bits not only affect interrupt - * routing but also change the behaviour of masking. - */ - bool hcr, scr; - - switch (excp_idx) { - case EXCP_FIQ: - /* - * If FIQs are routed to EL3 or EL2 then there are cases where - * we override the CPSR.F in determining if the exception is - * masked or not. If neither of these are set then we fall back - * to the CPSR.F setting otherwise we further assess the state - * below. - */ - hcr = hcr_el2 & HCR_FMO; - scr = (env->cp15.scr_el3 & SCR_FIQ); - - /* - * When EL3 is 32-bit, the SCR.FW bit controls whether the - * CPSR.F bit masks FIQ interrupts when taken in non-secure - * state. If SCR.FW is set then FIQs can be masked by CPSR.F - * when non-secure but only when FIQs are only routed to EL3. - */ - scr = scr && !((env->cp15.scr_el3 & SCR_FW) && !hcr); - break; - case EXCP_IRQ: - /* - * When EL3 execution state is 32-bit, if HCR.IMO is set then - * we may override the CPSR.I masking when in non-secure state. - * The SCR.IRQ setting has already been taken into consideration - * when setting the target EL, so it does not have a further - * affect here. - */ - hcr = hcr_el2 & HCR_IMO; - scr = false; - break; - default: - g_assert_not_reached(); - } - - if ((scr || hcr) && !secure) { - unmasked = true; - } - } - } - - /* - * The PSTATE bits only mask the interrupt if we have not overriden the - * ability above. - */ - return unmasked || pstate_unmasked; -} - -bool arm_cpu_exec_interrupt(CPUState *cs, int interrupt_request) -{ - CPUClass *cc = CPU_GET_CLASS(cs); - CPUARMState *env = cs->env_ptr; - uint32_t cur_el = arm_current_el(env); - bool secure = arm_is_secure(env); - uint64_t hcr_el2 = arm_hcr_el2_eff(env); - uint32_t target_el; - uint32_t excp_idx; - - /* The prioritization of interrupts is IMPLEMENTATION DEFINED. */ - - if (interrupt_request & CPU_INTERRUPT_FIQ) { - excp_idx = EXCP_FIQ; - target_el = arm_phys_excp_target_el(cs, excp_idx, cur_el, secure); - if (arm_excp_unmasked(cs, excp_idx, target_el, - cur_el, secure, hcr_el2)) { - goto found; - } - } - if (interrupt_request & CPU_INTERRUPT_HARD) { - excp_idx = EXCP_IRQ; - target_el = arm_phys_excp_target_el(cs, excp_idx, cur_el, secure); - if (arm_excp_unmasked(cs, excp_idx, target_el, - cur_el, secure, hcr_el2)) { - goto found; - } - } - if (interrupt_request & CPU_INTERRUPT_VIRQ) { - excp_idx = EXCP_VIRQ; - target_el = 1; - if (arm_excp_unmasked(cs, excp_idx, target_el, - cur_el, secure, hcr_el2)) { - goto found; - } - } - if (interrupt_request & CPU_INTERRUPT_VFIQ) { - excp_idx = EXCP_VFIQ; - target_el = 1; - if (arm_excp_unmasked(cs, excp_idx, target_el, - cur_el, secure, hcr_el2)) { - goto found; - } - } - return false; - - found: - cs->exception_index = excp_idx; - env->exception.target_el = target_el; - cc->tcg_ops->do_interrupt(cs); - return true; -} - void arm_cpu_update_virq(ARMCPU *cpu) { /* @@ -1015,6 +827,7 @@ static void arm_cpu_finalizefn(Object *obj) QLIST_REMOVE(hook, node); g_free(hook); } + #ifndef CONFIG_USER_ONLY if (cpu->pmu_timer) { timer_free(cpu->pmu_timer); @@ -1644,25 +1457,6 @@ static const struct SysemuCPUOps arm_sysemu_ops = { .legacy_vmsd = &vmstate_arm_cpu, }; #endif - -#ifdef CONFIG_TCG -static const struct TCGCPUOps arm_tcg_ops = { - .initialize = arm_translate_init, - .synchronize_from_tb = arm_cpu_synchronize_from_tb, - .cpu_exec_interrupt = arm_cpu_exec_interrupt, - .tlb_fill = arm_cpu_tlb_fill, - .debug_excp_handler = arm_debug_excp_handler, - -#if !defined(CONFIG_USER_ONLY) - .do_interrupt = arm_cpu_do_interrupt, - .do_transaction_failed = arm_cpu_do_transaction_failed, - .do_unaligned_access = arm_cpu_do_unaligned_access, - .adjust_watchpoint_address = arm_adjust_watchpoint_address, - .debug_check_watchpoint = arm_debug_check_watchpoint, -#endif /* !CONFIG_USER_ONLY */ -}; -#endif /* CONFIG_TCG */ - static void arm_cpu_class_init(ObjectClass *oc, void *data) { ARMCPUClass *acc = ARM_CPU_CLASS(oc); diff --git a/target/arm/cpu_tcg.c b/target/arm/cpu_tcg.c index fe422498c7..4606ad8436 100644 --- a/target/arm/cpu_tcg.c +++ b/target/arm/cpu_tcg.c @@ -11,7 +11,7 @@ #include "qemu/osdep.h" #include "cpu.h" #ifdef CONFIG_TCG -#include "hw/core/tcg-cpu-ops.h" +#include "tcg/tcg-cpu.h" #endif /* CONFIG_TCG */ #include "internals.h" #include "target/arm/idau.h" diff --git a/target/arm/tcg/helper.c b/target/arm/tcg/helper.c index a8b1efdb36..38cc7c6a3d 100644 --- a/target/arm/tcg/helper.c +++ b/target/arm/tcg/helper.c @@ -16,6 +16,7 @@ #include "arm_ldst.h" #include "cpu-mmu.h" #include "cpregs.h" +#include "tcg-cpu.h" static int vfp_gdb_get_reg(CPUARMState *env, GByteArray *buf, int reg) { diff --git a/target/arm/tcg/tcg-cpu.c b/target/arm/tcg/tcg-cpu.c new file mode 100644 index 0000000000..9fd996d908 --- /dev/null +++ b/target/arm/tcg/tcg-cpu.c @@ -0,0 +1,229 @@ +/* + * QEMU ARM CPU + * + * Copyright (c) 2012 SUSE LINUX Products GmbH + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see + * + */ + +#include "qemu/osdep.h" +#include "cpu.h" +#include "tcg-cpu.h" +#include "hw/core/tcg-cpu-ops.h" +#include "cpregs.h" +#include "internals.h" +#include "exec/exec-all.h" + +void arm_cpu_synchronize_from_tb(CPUState *cs, + const TranslationBlock *tb) +{ + ARMCPU *cpu = ARM_CPU(cs); + CPUARMState *env = &cpu->env; + + /* + * It's OK to look at env for the current mode here, because it's + * never possible for an AArch64 TB to chain to an AArch32 TB. + */ + if (is_a64(env)) { + env->pc = tb->pc; + } else { + env->regs[15] = tb->pc; + } +} + +static inline bool arm_excp_unmasked(CPUState *cs, unsigned int excp_idx, + unsigned int target_el, + unsigned int cur_el, bool secure, + uint64_t hcr_el2) +{ + CPUARMState *env = cs->env_ptr; + bool pstate_unmasked; + bool unmasked = false; + + /* + * Don't take exceptions if they target a lower EL. + * This check should catch any exceptions that would not be taken + * but left pending. + */ + if (cur_el > target_el) { + return false; + } + + switch (excp_idx) { + case EXCP_FIQ: + pstate_unmasked = !(env->daif & PSTATE_F); + break; + + case EXCP_IRQ: + pstate_unmasked = !(env->daif & PSTATE_I); + break; + + case EXCP_VFIQ: + if (!(hcr_el2 & HCR_FMO) || (hcr_el2 & HCR_TGE)) { + /* VFIQs are only taken when hypervized. */ + return false; + } + return !(env->daif & PSTATE_F); + case EXCP_VIRQ: + if (!(hcr_el2 & HCR_IMO) || (hcr_el2 & HCR_TGE)) { + /* VIRQs are only taken when hypervized. */ + return false; + } + return !(env->daif & PSTATE_I); + default: + g_assert_not_reached(); + } + + /* + * Use the target EL, current execution state and SCR/HCR settings to + * determine whether the corresponding CPSR bit is used to mask the + * interrupt. + */ + if ((target_el > cur_el) && (target_el != 1)) { + /* Exceptions targeting a higher EL may not be maskable */ + if (arm_feature(env, ARM_FEATURE_AARCH64)) { + /* + * 64-bit masking rules are simple: exceptions to EL3 + * can't be masked, and exceptions to EL2 can only be + * masked from Secure state. The HCR and SCR settings + * don't affect the masking logic, only the interrupt routing. + */ + if (target_el == 3 || !secure || (env->cp15.scr_el3 & SCR_EEL2)) { + unmasked = true; + } + } else { + /* + * The old 32-bit-only environment has a more complicated + * masking setup. HCR and SCR bits not only affect interrupt + * routing but also change the behaviour of masking. + */ + bool hcr, scr; + + switch (excp_idx) { + case EXCP_FIQ: + /* + * If FIQs are routed to EL3 or EL2 then there are cases where + * we override the CPSR.F in determining if the exception is + * masked or not. If neither of these are set then we fall back + * to the CPSR.F setting otherwise we further assess the state + * below. + */ + hcr = hcr_el2 & HCR_FMO; + scr = (env->cp15.scr_el3 & SCR_FIQ); + + /* + * When EL3 is 32-bit, the SCR.FW bit controls whether the + * CPSR.F bit masks FIQ interrupts when taken in non-secure + * state. If SCR.FW is set then FIQs can be masked by CPSR.F + * when non-secure but only when FIQs are only routed to EL3. + */ + scr = scr && !((env->cp15.scr_el3 & SCR_FW) && !hcr); + break; + case EXCP_IRQ: + /* + * When EL3 execution state is 32-bit, if HCR.IMO is set then + * we may override the CPSR.I masking when in non-secure state. + * The SCR.IRQ setting has already been taken into consideration + * when setting the target EL, so it does not have a further + * affect here. + */ + hcr = hcr_el2 & HCR_IMO; + scr = false; + break; + default: + g_assert_not_reached(); + } + + if ((scr || hcr) && !secure) { + unmasked = true; + } + } + } + + /* + * The PSTATE bits only mask the interrupt if we have not overriden the + * ability above. + */ + return unmasked || pstate_unmasked; +} + +static bool arm_cpu_exec_interrupt(CPUState *cs, int interrupt_request) +{ + CPUClass *cc = CPU_GET_CLASS(cs); + CPUARMState *env = cs->env_ptr; + uint32_t cur_el = arm_current_el(env); + bool secure = arm_is_secure(env); + uint64_t hcr_el2 = arm_hcr_el2_eff(env); + uint32_t target_el; + uint32_t excp_idx; + + /* The prioritization of interrupts is IMPLEMENTATION DEFINED. */ + + if (interrupt_request & CPU_INTERRUPT_FIQ) { + excp_idx = EXCP_FIQ; + target_el = arm_phys_excp_target_el(cs, excp_idx, cur_el, secure); + if (arm_excp_unmasked(cs, excp_idx, target_el, + cur_el, secure, hcr_el2)) { + goto found; + } + } + if (interrupt_request & CPU_INTERRUPT_HARD) { + excp_idx = EXCP_IRQ; + target_el = arm_phys_excp_target_el(cs, excp_idx, cur_el, secure); + if (arm_excp_unmasked(cs, excp_idx, target_el, + cur_el, secure, hcr_el2)) { + goto found; + } + } + if (interrupt_request & CPU_INTERRUPT_VIRQ) { + excp_idx = EXCP_VIRQ; + target_el = 1; + if (arm_excp_unmasked(cs, excp_idx, target_el, + cur_el, secure, hcr_el2)) { + goto found; + } + } + if (interrupt_request & CPU_INTERRUPT_VFIQ) { + excp_idx = EXCP_VFIQ; + target_el = 1; + if (arm_excp_unmasked(cs, excp_idx, target_el, + cur_el, secure, hcr_el2)) { + goto found; + } + } + return false; + + found: + cs->exception_index = excp_idx; + env->exception.target_el = target_el; + cc->tcg_ops->do_interrupt(cs); + return true; +} + +struct TCGCPUOps arm_tcg_ops = { + .initialize = arm_translate_init, + .synchronize_from_tb = arm_cpu_synchronize_from_tb, + .cpu_exec_interrupt = arm_cpu_exec_interrupt, + .tlb_fill = arm_cpu_tlb_fill, + .debug_excp_handler = arm_debug_excp_handler, + +#if !defined(CONFIG_USER_ONLY) + .do_interrupt = arm_cpu_do_interrupt, + .do_transaction_failed = arm_cpu_do_transaction_failed, + .do_unaligned_access = arm_cpu_do_unaligned_access, + .adjust_watchpoint_address = arm_adjust_watchpoint_address, + .debug_check_watchpoint = arm_debug_check_watchpoint, +#endif /* !CONFIG_USER_ONLY */ +}; diff --git a/target/arm/tcg/meson.build b/target/arm/tcg/meson.build index 64a86fd94c..4e690eea6c 100644 --- a/target/arm/tcg/meson.build +++ b/target/arm/tcg/meson.build @@ -31,6 +31,7 @@ arm_ss.add(when: 'CONFIG_TCG', if_true: files( 'vfp_helper.c', 'crypto_helper.c', 'debug_helper.c', + 'tcg-cpu.c', ), if_false: files( 'tcg-stubs.c',