On Thu, Jan 14, 2016 at 06:34:08PM +0000, Peter Maydell wrote: > The entry offset when taking an exception to AArch64 from a lower > exception level may be 0x400 or 0x600. 0x400 is used if the > implemented exception level immediately lower than the target level > is using AArch64, and 0x600 if it is using AArch32. We were > incorrectly implementing this as checking the exception level > that the exception was taken from. (The two can be different if > for example we take an exception from EL0 to AArch64 EL3; we should > in this case be checking EL2 if EL2 is implemented, and EL1 if > EL2 is not implemented.) > > Signed-off-by: Peter Maydell <peter.mayd...@linaro.org>
Reviewed-by: Edgar E. Iglesias <edgar.igles...@xilinx.com> > --- > target-arm/helper.c | 21 ++++++++++++++++++++- > 1 file changed, 20 insertions(+), 1 deletion(-) > > diff --git a/target-arm/helper.c b/target-arm/helper.c > index d37c82c..196c111 100644 > --- a/target-arm/helper.c > +++ b/target-arm/helper.c > @@ -5866,7 +5866,26 @@ static void arm_cpu_do_interrupt_aarch64(CPUState *cs) > unsigned int new_mode = aarch64_pstate_mode(new_el, true); > > if (arm_current_el(env) < new_el) { > - if (env->aarch64) { > + /* Entry vector offset depends on whether the implemented EL > + * immediately lower than the target level is using AArch32 or > AArch64 > + */ > + bool is_aa64; > + > + switch (new_el) { > + case 3: > + is_aa64 = (env->cp15.scr_el3 & SCR_RW) != 0; > + break; > + case 2: > + is_aa64 = (env->cp15.hcr_el2 & HCR_RW) != 0; > + break; > + case 1: > + is_aa64 = is_a64(env); > + break; > + default: > + g_assert_not_reached(); > + } > + > + if (is_aa64) { > addr += 0x400; > } else { > addr += 0x600; > -- > 1.9.1 >