diff mbox

[v2,7/7] target-arm: Call the pmccntr_sync function when swapping ELs

Message ID 299bd2202b8bda7c319cfd172eb1a7ca5a175d47.1403757527.git.alistair.francis@xilinx.com
State New
Headers show

Commit Message

Alistair Francis June 26, 2014, 5:02 a.m. UTC
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.francis@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(-)

Comments

Peter Maydell Aug. 1, 2014, 3:35 p.m. UTC | #1
On 26 June 2014 06:02, Alistair Francis <alistair.francis@xilinx.com> wrote:
> 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.francis@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 e78c5a7..f05d912 100644
> --- a/target-arm/helper.c
> +++ b/target-arm/helper.c
> @@ -3457,6 +3457,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.  */
> @@ -3487,6 +3489,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;
>              }
>          }
> @@ -3505,6 +3508,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;
>              }
>          }
> @@ -3548,6 +3552,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.  */
>      }
> @@ -3580,6 +3585,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);
>  }

This feels way too fragile to me to be scattering these sync
calls all over the place like this. We need to find a better
approach than this.

thanks
-- PMM
Peter Crosthwaite Aug. 1, 2014, 11:27 p.m. UTC | #2
On Sat, Aug 2, 2014 at 1:35 AM, Peter Maydell <peter.maydell@linaro.org> wrote:
> On 26 June 2014 06:02, Alistair Francis <alistair.francis@xilinx.com> wrote:
>> 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.francis@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 e78c5a7..f05d912 100644
>> --- a/target-arm/helper.c
>> +++ b/target-arm/helper.c
>> @@ -3457,6 +3457,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.  */
>> @@ -3487,6 +3489,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;
>>              }
>>          }
>> @@ -3505,6 +3508,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;
>>              }
>>          }
>> @@ -3548,6 +3552,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.  */
>>      }
>> @@ -3580,6 +3585,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);
>>  }
>
> This feels way too fragile to me to be scattering these sync
> calls all over the place like this. We need to find a better
> approach than this.
>

If we could consolidate all the code paths that actually switch el
(both ways) into a helper fn we could then add the pmccntr
el-switching side effects (i.e. the sync) to that helper once. Would
you accept such an approach?

Regards,
Peter

> thanks
> -- PMM
>
diff mbox

Patch

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 e78c5a7..f05d912 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -3457,6 +3457,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.  */
@@ -3487,6 +3489,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;
             }
         }
@@ -3505,6 +3508,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;
             }
         }
@@ -3548,6 +3552,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.  */
     }
@@ -3580,6 +3585,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.