Call the new pmccntr_sync() function when there is a possibility of swapping ELs (I.E. when there is an exception)
Signed-off-by: Alistair Francis <alistair.fran...@xilinx.com> --- target-arm/helper-a64.c | 5 +++++ target-arm/helper.c | 7 +++++++ target-arm/op_helper.c | 6 ++++++ 3 files changed, 18 insertions(+), 0 deletions(-) diff --git a/target-arm/helper-a64.c b/target-arm/helper-a64.c index 2b4ce6a..b61174f 100644 --- a/target-arm/helper-a64.c +++ b/target-arm/helper-a64.c @@ -446,6 +446,8 @@ void aarch64_cpu_do_interrupt(CPUState *cs) target_ulong addr = env->cp15.vbar_el[1]; int i; + pmccntr_sync(env); + if (arm_current_pl(env) == 0) { if (env->aarch64) { addr += 0x400; @@ -484,6 +486,7 @@ void aarch64_cpu_do_interrupt(CPUState *cs) addr += 0x100; break; default: + pmccntr_sync(env); cpu_abort(cs, "Unhandled exception 0x%x\n", cs->exception_index); } @@ -511,4 +514,6 @@ void aarch64_cpu_do_interrupt(CPUState *cs) env->pc = addr; cs->interrupt_request |= CPU_INTERRUPT_EXITTB; + + pmccntr_sync(env); } diff --git a/target-arm/helper.c b/target-arm/helper.c index 3e0a9a1..7c0a57f 100644 --- a/target-arm/helper.c +++ b/target-arm/helper.c @@ -3417,6 +3417,8 @@ void arm_cpu_do_interrupt(CPUState *cs) assert(!IS_M(env)); + pmccntr_sync(env); + arm_log_exception(cs->exception_index); /* TODO: Vectored interrupt controller. */ @@ -3447,6 +3449,7 @@ void arm_cpu_do_interrupt(CPUState *cs) && (env->uncached_cpsr & CPSR_M) != ARM_CPU_MODE_USR) { env->regs[0] = do_arm_semihosting(env); qemu_log_mask(CPU_LOG_INT, "...handled as semihosting call\n"); + pmccntr_sync(env); return; } } @@ -3465,6 +3468,7 @@ void arm_cpu_do_interrupt(CPUState *cs) env->regs[15] += 2; env->regs[0] = do_arm_semihosting(env); qemu_log_mask(CPU_LOG_INT, "...handled as semihosting call\n"); + pmccntr_sync(env); return; } } @@ -3508,6 +3512,7 @@ void arm_cpu_do_interrupt(CPUState *cs) offset = 4; break; default: + pmccntr_sync(env); cpu_abort(cs, "Unhandled exception 0x%x\n", cs->exception_index); return; /* Never happens. Keep compiler happy. */ } @@ -3540,6 +3545,8 @@ void arm_cpu_do_interrupt(CPUState *cs) env->regs[14] = env->regs[15] + offset; env->regs[15] = addr; cs->interrupt_request |= CPU_INTERRUPT_EXITTB; + + pmccntr_sync(env); } /* Check section/page access permissions. diff --git a/target-arm/op_helper.c b/target-arm/op_helper.c index 9c1ef52..07ab30b 100644 --- a/target-arm/op_helper.c +++ b/target-arm/op_helper.c @@ -376,6 +376,8 @@ void HELPER(exception_return)(CPUARMState *env) uint32_t spsr = env->banked_spsr[spsr_idx]; int new_el, i; + pmccntr_sync(env); + if (env->pstate & PSTATE_SP) { env->sp_el[cur_el] = env->xregs[31]; } else { @@ -418,6 +420,8 @@ void HELPER(exception_return)(CPUARMState *env) env->pc = env->elr_el[cur_el]; } + pmccntr_sync(env); + return; illegal_return: @@ -433,6 +437,8 @@ illegal_return: spsr &= PSTATE_NZCV | PSTATE_DAIF; spsr |= pstate_read(env) & ~(PSTATE_NZCV | PSTATE_DAIF); pstate_write(env, spsr); + + pmccntr_sync(env); } /* ??? Flag setting arithmetic is awkward because we need to do comparisons. -- 1.7.1