From: Peter Maydell <peter.maydell@linaro.org>
To: qemu-devel@nongnu.org
Cc: "Peter Crosthwaite" <peter.crosthwaite@xilinx.com>,
patches@linaro.org, "Michael Matz" <matz@suse.de>,
"Alexander Graf" <agraf@suse.de>,
"Will Newton" <will.newton@linaro.org>,
"Dirk Mueller" <dmueller@suse.de>,
"Laurent Desnogues" <laurent.desnogues@gmail.com>,
"Alex Bennée" <alex.bennee@linaro.org>,
kvmarm@lists.cs.columbia.edu,
"Christoffer Dall" <christoffer.dall@linaro.org>,
"Richard Henderson" <rth@twiddle.net>
Subject: [Qemu-devel] [PATCH v5 19/37] target-arm: Implement AArch64 EL1 exception handling
Date: Fri, 28 Mar 2014 16:10:06 +0000 [thread overview]
Message-ID: <1396023024-2262-20-git-send-email-peter.maydell@linaro.org> (raw)
In-Reply-To: <1396023024-2262-1-git-send-email-peter.maydell@linaro.org>
From: Rob Herring <rob.herring@linaro.org>
Implement exception handling for AArch64 EL1. Exceptions from AArch64 or
AArch32 EL0 are supported.
Signed-off-by: Rob Herring <rob.herring@linaro.org>
[PMM: fixed minor style nits; updated to match changes in
previous patches; added some of the simpler cases of
illegal-exception-return support]
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
target-arm/cpu-qom.h | 2 ++
target-arm/cpu64.c | 1 +
target-arm/helper-a64.c | 75 ++++++++++++++++++++++++++++++++++++++++++++++
target-arm/helper.h | 1 +
target-arm/op_helper.c | 60 +++++++++++++++++++++++++++++++++++++
target-arm/translate-a64.c | 3 ++
6 files changed, 142 insertions(+)
diff --git a/target-arm/cpu-qom.h b/target-arm/cpu-qom.h
index 41caa6c..afdee9d 100644
--- a/target-arm/cpu-qom.h
+++ b/target-arm/cpu-qom.h
@@ -202,6 +202,8 @@ void aarch64_cpu_dump_state(CPUState *cs, FILE *f,
fprintf_function cpu_fprintf, int flags);
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);
+
+void aarch64_cpu_do_interrupt(CPUState *cs);
#endif
#endif
diff --git a/target-arm/cpu64.c b/target-arm/cpu64.c
index fccecc2..d4fb1de 100644
--- a/target-arm/cpu64.c
+++ b/target-arm/cpu64.c
@@ -85,6 +85,7 @@ static void aarch64_cpu_class_init(ObjectClass *oc, void *data)
{
CPUClass *cc = CPU_CLASS(oc);
+ cc->do_interrupt = aarch64_cpu_do_interrupt;
cc->dump_state = aarch64_cpu_dump_state;
cc->set_pc = aarch64_cpu_set_pc;
cc->gdb_read_register = aarch64_cpu_gdb_read_register;
diff --git a/target-arm/helper-a64.c b/target-arm/helper-a64.c
index ec02582..1a82056 100644
--- a/target-arm/helper-a64.c
+++ b/target-arm/helper-a64.c
@@ -23,6 +23,7 @@
#include "qemu/host-utils.h"
#include "sysemu/sysemu.h"
#include "qemu/bitops.h"
+#include "internals.h"
/* C2.4.7 Multiply and divide */
/* special cases for 0 and LLONG_MIN are mandated by the standard */
@@ -436,3 +437,77 @@ float32 HELPER(fcvtx_f64_to_f32)(float64 a, CPUARMState *env)
set_float_exception_flags(exflags, fpst);
return r;
}
+
+/* Handle a CPU exception. */
+void aarch64_cpu_do_interrupt(CPUState *cs)
+{
+ ARMCPU *cpu = ARM_CPU(cs);
+ CPUARMState *env = &cpu->env;
+ target_ulong addr = env->cp15.c12_vbar;
+ int i;
+
+ if (arm_current_pl(env) == 0) {
+ if (env->aarch64) {
+ addr += 0x400;
+ } else {
+ addr += 0x600;
+ }
+ } else if (pstate_read(env) & PSTATE_SP) {
+ addr += 0x200;
+ }
+
+ arm_log_exception(cs->exception_index);
+ qemu_log_mask(CPU_LOG_INT, "...from EL%d\n", arm_current_pl(env));
+ if (qemu_loglevel_mask(CPU_LOG_INT)
+ && !excp_is_internal(cs->exception_index)) {
+ qemu_log_mask(CPU_LOG_INT, "...with ESR 0x%" PRIx32 "\n",
+ env->exception.syndrome);
+ }
+
+ env->cp15.esr_el1 = env->exception.syndrome;
+ env->cp15.far_el1 = env->exception.vaddress;
+
+ switch (cs->exception_index) {
+ case EXCP_PREFETCH_ABORT:
+ case EXCP_DATA_ABORT:
+ qemu_log_mask(CPU_LOG_INT, "...with FAR 0x%" PRIx64 "\n",
+ env->cp15.far_el1);
+ case EXCP_BKPT:
+ case EXCP_UDEF:
+ case EXCP_SWI:
+ break;
+ case EXCP_IRQ:
+ addr += 0x80;
+ break;
+ case EXCP_FIQ:
+ addr += 0x100;
+ break;
+ default:
+ cpu_abort(cs, "Unhandled exception 0x%x\n", cs->exception_index);
+ }
+
+ if (is_a64(env)) {
+ env->banked_spsr[0] = pstate_read(env);
+ env->sp_el[arm_current_pl(env)] = env->xregs[31];
+ env->xregs[31] = env->sp_el[1];
+ env->elr_el1 = env->pc;
+ } else {
+ env->banked_spsr[0] = cpsr_read(env);
+ if (!env->thumb) {
+ env->cp15.esr_el1 |= 1 << 25;
+ }
+ env->elr_el1 = env->regs[15];
+
+ for (i = 0; i < 15; i++) {
+ env->xregs[i] = env->regs[i];
+ }
+
+ env->condexec_bits = 0;
+ }
+
+ pstate_write(env, PSTATE_DAIF | PSTATE_MODE_EL1h);
+ env->aarch64 = 1;
+
+ env->pc = addr;
+ cs->interrupt_request |= CPU_INTERRUPT_EXITTB;
+}
diff --git a/target-arm/helper.h b/target-arm/helper.h
index 5977169..a5449e7 100644
--- a/target-arm/helper.h
+++ b/target-arm/helper.h
@@ -66,6 +66,7 @@ DEF_HELPER_3(set_cp_reg64, void, env, ptr, i64)
DEF_HELPER_2(get_cp_reg64, i64, env, ptr)
DEF_HELPER_3(msr_i_pstate, void, env, i32, i32)
+DEF_HELPER_1(exception_return, void, env)
DEF_HELPER_2(get_r13_banked, i32, env, i32)
DEF_HELPER_3(set_r13_banked, void, env, i32, i32)
diff --git a/target-arm/op_helper.c b/target-arm/op_helper.c
index 64a33dd..57e7d9c 100644
--- a/target-arm/op_helper.c
+++ b/target-arm/op_helper.c
@@ -384,6 +384,66 @@ void HELPER(msr_i_pstate)(CPUARMState *env, uint32_t op, uint32_t imm)
}
}
+void HELPER(exception_return)(CPUARMState *env)
+{
+ uint32_t spsr = env->banked_spsr[0];
+ int new_el, i;
+
+ if (env->pstate & PSTATE_SP) {
+ env->sp_el[1] = env->xregs[31];
+ } else {
+ env->sp_el[0] = env->xregs[31];
+ }
+
+ env->exclusive_addr = -1;
+
+ if (spsr & PSTATE_nRW) {
+ env->aarch64 = 0;
+ new_el = 0;
+ env->uncached_cpsr = 0x10;
+ cpsr_write(env, spsr, ~0);
+ for (i = 0; i < 15; i++) {
+ env->regs[i] = env->xregs[i];
+ }
+
+ env->regs[15] = env->elr_el1 & ~0x1;
+ } else {
+ new_el = extract32(spsr, 2, 2);
+ if (new_el > 1) {
+ /* Return to unimplemented EL */
+ goto illegal_return;
+ }
+ if (extract32(spsr, 1, 1)) {
+ /* Return with reserved M[1] bit set */
+ goto illegal_return;
+ }
+ if (new_el == 0 && (spsr & PSTATE_SP)) {
+ /* Return to EL1 with M[0] bit set */
+ goto illegal_return;
+ }
+ env->aarch64 = 1;
+ pstate_write(env, spsr);
+ env->xregs[31] = env->sp_el[new_el];
+ env->pc = env->elr_el1;
+ }
+
+ return;
+
+illegal_return:
+ /* Illegal return events of various kinds have architecturally
+ * mandated behaviour:
+ * restore NZCV and DAIF from SPSR_ELx
+ * set PSTATE.IL
+ * restore PC from ELR_ELx
+ * no change to exception level, execution state or stack pointer
+ */
+ env->pstate |= PSTATE_IL;
+ env->pc = env->elr_el1;
+ spsr &= PSTATE_NZCV | PSTATE_DAIF;
+ spsr |= pstate_read(env) & ~(PSTATE_NZCV | PSTATE_DAIF);
+ pstate_write(env, spsr);
+}
+
/* ??? Flag setting arithmetic is awkward because we need to do comparisons.
The only way to do that in TCG is a conditional branch, which clobbers
all our temporaries. For now implement these as helper functions. */
diff --git a/target-arm/translate-a64.c b/target-arm/translate-a64.c
index 863a6db..29997cb 100644
--- a/target-arm/translate-a64.c
+++ b/target-arm/translate-a64.c
@@ -1511,6 +1511,9 @@ static void disas_uncond_b_reg(DisasContext *s, uint32_t insn)
tcg_gen_movi_i64(cpu_reg(s, 30), s->pc);
break;
case 4: /* ERET */
+ gen_helper_exception_return(cpu_env);
+ s->is_jmp = DISAS_JUMP;
+ return;
case 5: /* DRPS */
if (rn != 0x1f) {
unallocated_encoding(s);
--
1.9.0
next prev parent reply other threads:[~2014-03-28 16:27 UTC|newest]
Thread overview: 53+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-03-28 16:09 [Qemu-devel] [PATCH v5 00/37] AArch64 system emulation Peter Maydell
2014-03-28 16:09 ` [Qemu-devel] [PATCH v5 01/37] target-arm: Split out private-to-target functions into internals.h Peter Maydell
2014-03-28 16:09 ` [Qemu-devel] [PATCH v5 02/37] target-arm: Implement AArch64 DAIF system register Peter Maydell
2014-03-28 16:09 ` [Qemu-devel] [PATCH v5 03/37] target-arm: Define exception record for AArch64 exceptions Peter Maydell
2014-03-28 16:09 ` [Qemu-devel] [PATCH v5 04/37] target-arm: Provide correct syndrome information for cpreg access traps Peter Maydell
2014-03-28 16:09 ` [Qemu-devel] [PATCH v5 05/37] target-arm: Add support for generating exceptions with syndrome information Peter Maydell
2014-03-28 16:09 ` [Qemu-devel] [PATCH v5 06/37] target-arm: Provide syndrome information for MMU faults Peter Maydell
2014-04-01 3:10 ` Peter Crosthwaite
2014-04-04 13:25 ` Peter Maydell
2014-03-28 16:09 ` [Qemu-devel] [PATCH v5 07/37] target-arm: A64: Correctly fault FP/Neon if CPACR.FPEN set Peter Maydell
2014-03-28 16:09 ` [Qemu-devel] [PATCH v5 08/37] target-arm: A64: Add assertion that FP access was checked Peter Maydell
2014-04-01 3:24 ` Peter Crosthwaite
2014-03-28 16:09 ` [Qemu-devel] [PATCH v5 09/37] target-arm: Fix VFP enables for AArch32 EL0 under AArch64 EL1 Peter Maydell
2014-04-01 3:30 ` Peter Crosthwaite
2014-03-28 16:09 ` [Qemu-devel] [PATCH v5 10/37] target-arm: Add v8 mmu translation support Peter Maydell
2014-03-28 16:09 ` [Qemu-devel] [PATCH v5 11/37] target-arm: Don't mention PMU in debug feature register Peter Maydell
2014-04-01 13:19 ` Christopher Covington
2014-04-01 13:43 ` Peter Maydell
2014-03-28 16:09 ` [Qemu-devel] [PATCH v5 12/37] target-arm: A64: Implement DC ZVA Peter Maydell
2014-03-28 18:42 ` Richard Henderson
2014-04-04 14:12 ` Peter Maydell
2014-03-28 16:10 ` [Qemu-devel] [PATCH v5 13/37] target-arm: Use dedicated CPU state fields for ARM946 access bit registers Peter Maydell
2014-03-28 16:10 ` [Qemu-devel] [PATCH v5 14/37] target-arm: Implement AArch64 views of fault status and data registers Peter Maydell
2014-03-28 16:10 ` [Qemu-devel] [PATCH v5 15/37] target-arm: Add AArch64 ELR_EL1 register Peter Maydell
2014-03-28 16:10 ` [Qemu-devel] [PATCH v5 16/37] target-arm: Implement SP_EL0, SP_EL1 Peter Maydell
2014-03-28 16:10 ` [Qemu-devel] [PATCH v5 17/37] target-arm: Implement AArch64 SPSR_EL1 Peter Maydell
2014-03-28 16:10 ` [Qemu-devel] [PATCH v5 18/37] target-arm: Move arm_log_exception() into internals.h Peter Maydell
2014-03-28 16:10 ` Peter Maydell [this message]
2014-03-28 16:10 ` [Qemu-devel] [PATCH v5 20/37] target-arm: Implement ARMv8 MVFR registers Peter Maydell
2014-03-28 16:10 ` [Qemu-devel] [PATCH v5 21/37] target-arm: Add Cortex-A57 processor Peter Maydell
2014-03-28 16:10 ` [Qemu-devel] [PATCH v5 22/37] hw/arm/virt: Add support for Cortex-A57 Peter Maydell
2014-03-28 16:10 ` [Qemu-devel] [PATCH v5 23/37] target-arm: Implement AArch64 views of AArch32 ID registers Peter Maydell
2014-03-28 16:10 ` [Qemu-devel] [PATCH v5 24/37] target-arm: Implement AArch64 view of CONTEXTIDR Peter Maydell
2014-03-28 16:10 ` [Qemu-devel] [PATCH v5 25/37] target-arm: Implement AArch64 view of ACTLR Peter Maydell
2014-03-28 16:10 ` [Qemu-devel] [PATCH v5 26/37] target-arm: Implement ISR_EL1 register Peter Maydell
2014-03-28 16:10 ` [Qemu-devel] [PATCH v5 27/37] target-arm: Remove THUMB2EE feature from AArch64 'any' CPU Peter Maydell
2014-04-02 12:20 ` Peter Crosthwaite
2014-03-28 16:10 ` [Qemu-devel] [PATCH v5 28/37] target-arm: Don't expose wildcard ID register definitions for ARMv8 Peter Maydell
2014-03-28 16:10 ` [Qemu-devel] [PATCH v5 29/37] target-arm: Replace wildcarded cpreg definitions with precise ones " Peter Maydell
2014-03-28 16:10 ` [Qemu-devel] [PATCH v5 30/37] target-arm: Implement auxiliary fault status registers Peter Maydell
2014-03-28 16:10 ` [Qemu-devel] [PATCH v5 31/37] target-arm: Implement AArch64 address translation operations Peter Maydell
2014-03-28 16:10 ` [Qemu-devel] [PATCH v5 32/37] target-arm: Implement RVBAR register Peter Maydell
2014-04-04 5:17 ` Peter Crosthwaite
2014-03-28 16:10 ` [Qemu-devel] [PATCH v5 33/37] target-arm: Implement Cortex-A57 implementation-defined system registers Peter Maydell
2014-03-28 16:10 ` [Qemu-devel] [PATCH v5 34/37] target-arm: Implement CBAR for Cortex-A57 Peter Maydell
2014-04-04 5:32 ` Peter Crosthwaite
2014-04-04 8:25 ` Peter Maydell
2014-04-04 12:32 ` Peter Crosthwaite
2014-04-04 13:05 ` Peter Maydell
2014-03-28 16:10 ` [Qemu-devel] [PATCH v5 35/37] target-arm: Make Cortex-A15 CBAR read-only Peter Maydell
2014-04-04 5:33 ` Peter Crosthwaite
2014-03-28 16:10 ` [Qemu-devel] [PATCH v5 36/37] target-arm: Handle the CPU being in AArch32 mode in the AArch64 set_pc Peter Maydell
2014-03-28 16:10 ` [Qemu-devel] [PATCH v5 37/37] target-arm: Dump 32-bit CPU state if 64 bit CPU is in AArch32 Peter Maydell
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1396023024-2262-20-git-send-email-peter.maydell@linaro.org \
--to=peter.maydell@linaro.org \
--cc=agraf@suse.de \
--cc=alex.bennee@linaro.org \
--cc=christoffer.dall@linaro.org \
--cc=dmueller@suse.de \
--cc=kvmarm@lists.cs.columbia.edu \
--cc=laurent.desnogues@gmail.com \
--cc=matz@suse.de \
--cc=patches@linaro.org \
--cc=peter.crosthwaite@xilinx.com \
--cc=qemu-devel@nongnu.org \
--cc=rth@twiddle.net \
--cc=will.newton@linaro.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).