On Tue, Feb 10, 2015 at 10:13 PM, Peter Maydell <peter.mayd...@linaro.org> wrote:
> On 10 February 2015 at 10:50, Greg Bellows <greg.bell...@linaro.org> > wrote: > > Add AArch32 to AArch64 register sychronization functions. > > Replace manual register synchronization with new functions in > > aarch64_cpu_do_interrupt() and HELPER(exception_return)(). > > > > Signed-off-by: Greg Bellows <greg.bell...@linaro.org> > > > > --- > > > > v3 -> v4 > > - Rework sync routines to cover various exception levels > > - Move sync routines to helper.c > > > > v2 -> v3 > > - Conditionalize interrupt handler update of aarch64. > > --- > > target-arm/cpu.h | 2 + > > target-arm/helper-a64.c | 5 +- > > target-arm/helper.c | 181 > ++++++++++++++++++++++++++++++++++++++++++++++++ > > target-arm/op_helper.c | 6 +- > > 4 files changed, 186 insertions(+), 8 deletions(-) > > > > diff --git a/target-arm/cpu.h b/target-arm/cpu.h > > index 1830a12..11845a6 100644 > > --- a/target-arm/cpu.h > > +++ b/target-arm/cpu.h > > @@ -495,6 +495,8 @@ typedef struct CPUARMState { > > ARMCPU *cpu_arm_init(const char *cpu_model); > > int cpu_arm_exec(CPUARMState *s); > > uint32_t do_arm_semihosting(CPUARMState *env); > > +void aarch64_sync_32_to_64(CPUARMState *env); > > +void aarch64_sync_64_to_32(CPUARMState *env); > > > > static inline bool is_a64(CPUARMState *env) > > { > > diff --git a/target-arm/helper-a64.c b/target-arm/helper-a64.c > > index 8aa40e9..7e0d038 100644 > > --- a/target-arm/helper-a64.c > > +++ b/target-arm/helper-a64.c > > @@ -466,7 +466,6 @@ void aarch64_cpu_do_interrupt(CPUState *cs) > > unsigned int new_el = arm_excp_target_el(cs, cs->exception_index); > > target_ulong addr = env->cp15.vbar_el[new_el]; > > unsigned int new_mode = aarch64_pstate_mode(new_el, true); > > - int i; > > > > if (arm_current_el(env) < new_el) { > > if (env->aarch64) { > > @@ -530,9 +529,7 @@ void aarch64_cpu_do_interrupt(CPUState *cs) > > } > > env->elr_el[new_el] = env->regs[15]; > > > > - for (i = 0; i < 15; i++) { > > - env->xregs[i] = env->regs[i]; > > - } > > + aarch64_sync_32_to_64(env); > > > > env->condexec_bits = 0; > > } > > diff --git a/target-arm/helper.c b/target-arm/helper.c > > index 1a1a005..c1d6764 100644 > > --- a/target-arm/helper.c > > +++ b/target-arm/helper.c > > @@ -4096,6 +4096,15 @@ unsigned int arm_excp_target_el(CPUState *cs, > unsigned int excp_idx) > > return 1; > > } > > > > +void aarch64_sync_64_to_32(CPUARMState *env) > > +{ > > + int i; > > + > > + for (i = 0; i < 15; i++) { > > + env->regs[i] = env->xregs[i]; > > + } > > +} > > This is inside CONFIG_USER_ONLY, right? Is it called at all? > If so, when? > The exception_return helper calls the function so I had to either add a USER_CONFIG version of wrap the call in exception return with CONFIG_USER_ONLY. I chose the former, but either would work. As you would already know, the exception_return helper is likely not getting called in a USER_ONLY build. > > > + > > #else > > > > /* Map CPU modes onto saved register banks. */ > > @@ -4425,6 +4434,178 @@ void arm_v7m_cpu_do_interrupt(CPUState *cs) > > env->thumb = addr & 1; > > } > > > > +/* Function used to synchronize QEMU's AArch64 register set with AArch32 > > + * register set. This is necessary when switching between AArch32 and > AArch64 > > + * execution state. > > This is a bit vague... > I'll elaborate. > > > + */ > > +void aarch64_sync_32_to_64(CPUARMState *env) > > +{ > > + int i; > > + uint32_t mode = env->uncached_cpsr & CPSR_M; > > + > > + /* We can blanket copy R[0:7] to X[0:7] */ > > + for (i = 0; i < 8; i++) { > > + env->xregs[i] = env->regs[i]; > > + } > > + > > + /* The latest copy of some registers depend on the current > executing mode. > > "depends" > Fixed in next version. > > > + * The general purpose copy is used when the current mode > corresponds to > > + * the mapping for the given register. Otherwise, the banked copy > > + * corresponding to the register mapping is used. > > + */ > > + if (mode == ARM_CPU_MODE_USR) { > > + for (i = 8; i < 15; i++) { > > + env->xregs[i] = env->regs[i]; > > + } > > + } else { > > + for (i = 8; i < 13; i++) { > > + env->xregs[i] = env->usr_regs[i - 8]; > > + } > > + env->xregs[13] = env->banked_r13[bank_number(ARM_CPU_MODE_USR)]; > > + env->xregs[14] = env->banked_r14[bank_number(ARM_CPU_MODE_USR)]; > > + } > > + > > + if (mode == ARM_CPU_MODE_HYP) { > > + env->xregs[15] = env->regs[13]; > > + } else { > > + env->xregs[15] = env->banked_r13[bank_number(ARM_CPU_MODE_HYP)]; > > + } > > + > > + if (mode == ARM_CPU_MODE_IRQ) { > > + env->xregs[16] = env->regs[13]; > > + env->xregs[17] = env->regs[14]; > > + } else { > > + env->xregs[16] = env->banked_r13[bank_number(ARM_CPU_MODE_IRQ)]; > > + env->xregs[17] = env->banked_r14[bank_number(ARM_CPU_MODE_IRQ)]; > > + } > > + > > + if (mode == ARM_CPU_MODE_SVC) { > > + env->xregs[18] = env->regs[13]; > > + env->xregs[19] = env->regs[14]; > > + } else { > > + env->xregs[18] = env->banked_r13[bank_number(ARM_CPU_MODE_SVC)]; > > + env->xregs[19] = env->banked_r14[bank_number(ARM_CPU_MODE_SVC)]; > > + } > > + > > + if (mode == ARM_CPU_MODE_ABT) { > > + env->xregs[20] = env->regs[13]; > > + env->xregs[21] = env->regs[14]; > > + } else { > > + env->xregs[20] = env->banked_r13[bank_number(ARM_CPU_MODE_ABT)]; > > + env->xregs[21] = env->banked_r14[bank_number(ARM_CPU_MODE_ABT)]; > > + } > > + > > + if (mode == ARM_CPU_MODE_UND) { > > + env->xregs[22] = env->regs[13]; > > + env->xregs[23] = env->regs[14]; > > + } else { > > + env->xregs[22] = env->banked_r13[bank_number(ARM_CPU_MODE_UND)]; > > + env->xregs[23] = env->banked_r14[bank_number(ARM_CPU_MODE_UND)]; > > + } > > + > > + if (mode == ARM_CPU_MODE_FIQ) { > > + for (i = 24; i < 31; i++) { > > + env->xregs[i] = env->regs[i - 16]; /* X[24:30] -> R[8:14] > */ > > + } > > + } else { > > + for (i = 24; i < 29; i++) { > > + env->xregs[i] = env->fiq_regs[i - 24]; > > + } > > + env->xregs[29] = env->banked_r13[bank_number(ARM_CPU_MODE_FIQ)]; > > + env->xregs[30] = env->banked_r14[bank_number(ARM_CPU_MODE_FIQ)]; > > + } > > + > > + env->pc = env->regs[15]; > > +} > > + > > +/* Function used to synchronize QEMU's AArch32 register set with AArch64 > > + * register set. This is necessary when switching between AArch32 and > AArch64 > > + * execution state. > > + */ > > +void aarch64_sync_64_to_32(CPUARMState *env) > > +{ > > + int i; > > + uint32_t mode = env->uncached_cpsr & CPSR_M; > > + > > + /* We can blanket copy X[0:7] to R[0:7] */ > > + for (i = 0; i < 8; i++) { > > + env->regs[i] = env->xregs[i]; > > + } > > + > > + /* The destination of some registers depend on the current > executing mode. > > "depends" > Fixed in next version. > > > + * The AArch32 registers 8-12 are only sync'd when we are in USR or > FIQ > > + * mode as they are the only modes where AArch64 registers map to > these > > + * registers. In all other cases, the respective USR and FIQ banks > are > > + * sync'd. > > + * The AArch32 registers 13 & 14 are sync'd depending on the > execution mode > > + * we are in. If we are not in a given mode, the bank > corresponding to the > > + * AArch64 register is sync'd. > > + */ > > + if (mode == ARM_CPU_MODE_USR) { > > + for (i = 8; i < 15; i++) { > > + env->regs[i] = env->xregs[i]; > > + } > > Something is wrong here, because we don't seem to be writing > anything to env->regs[8..15] if mode is neither USR nor FIQ. > > I wrestled with this myself. As I understand it, nothing maps to regs[8..15] unless we are in USR or FIQ, which I covered. This based on the ARM ARM xregs[8:15] are defined to specifically map to USR, Outside of the these modes, what should be copied to regs[8..15]? > I think you should rearrange this function. The 32->64 sync > needs to write a value to all of xregs[0..30], and it's > ordered such that we basically write them all in that order, > which makes it clear we don't miss any cases. > > This function, on the other hand, needs to write to > regs[0..15] and also to the banked_* registers, so > it should be written to update them in that order, > rather than in xregs order. > > You may also find it easier to always update the banked_* > copies regardless of the current mode -- it's safe to > write the value to them always, it just might be ignored > if we're currently executing for that mode. > > -- PMM >