diff mbox

[1/6] target-arm: correct CNTFRQ access rights

Message ID 1454690704-16233-2-git-send-email-peter.maydell@linaro.org
State New
Headers show

Commit Message

Peter Maydell Feb. 5, 2016, 4:44 p.m. UTC
Correct some corner cases we were getting wrong for
CNTFRQ access rights:
 * should UNDEF from 32-bit Secure EL1
 * only writable from the highest implemented exception level,
   which might not be EL1 now

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 target-arm/helper.c | 31 ++++++++++++++++++++++++++++---
 1 file changed, 28 insertions(+), 3 deletions(-)

Comments

Sergey Fedorov Feb. 8, 2016, 3:25 p.m. UTC | #1
On 05.02.2016 19:44, Peter Maydell wrote:
> Correct some corner cases we were getting wrong for
> CNTFRQ access rights:
>  * should UNDEF from 32-bit Secure EL1
>  * only writable from the highest implemented exception level,
>    which might not be EL1 now
>
> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
> ---
>  target-arm/helper.c | 31 ++++++++++++++++++++++++++++---
>  1 file changed, 28 insertions(+), 3 deletions(-)
>
> diff --git a/target-arm/helper.c b/target-arm/helper.c
> index 7a8881a..082701a 100644
> --- a/target-arm/helper.c
> +++ b/target-arm/helper.c
> @@ -1217,9 +1217,34 @@ static const ARMCPRegInfo v6k_cp_reginfo[] = {
>  static CPAccessResult gt_cntfrq_access(CPUARMState *env, const ARMCPRegInfo *ri,
>                                         bool isread)
>  {
> -    /* CNTFRQ: not visible from PL0 if both PL0PCTEN and PL0VCTEN are zero */
> -    if (arm_current_el(env) == 0 && !extract32(env->cp15.c14_cntkctl, 0, 2)) {
> -        return CP_ACCESS_TRAP;
> +    /* CNTFRQ: not visible from PL0 if both PL0PCTEN and PL0VCTEN are zero.
> +     * Writable only at the highest implemented exception level.
> +     */
> +    switch (arm_current_el(env)) {
> +    case 0:
> +        if (!extract32(env->cp15.c14_cntkctl, 0, 2)) {
> +            return CP_ACCESS_TRAP;
> +        }
> +        /* EL0 reads are forbidden by the .access fields */

s/reads/writes/ ?

> +        break;
> +    case 1:
> +        if (!isread && (arm_feature(env, ARM_FEATURE_EL2)
> +                        || arm_feature(env, ARM_FEATURE_EL3))) {
> +            return CP_ACCESS_TRAP_UNCATEGORIZED;
> +        }
> +        if (!isread && ri->state == ARM_CP_STATE_AA32 &&
> +            arm_is_secure_below_el3(env)) {
> +            /* Accesses from 32-bit Secure EL1 UNDEF (*not* trap to EL3!) */
> +            return CP_ACCESS_TRAP_UNCATEGORIZED;
> +        }
> +        break;
> +    case 2:
> +        if (!isread && arm_feature(env, ARM_FEATURE_EL3)) {
> +            return CP_ACCESS_TRAP_UNCATEGORIZED;
> +        }
> +        break;
> +    case 3:
> +        break;
>      }
>      return CP_ACCESS_OK;
>  }

Maybe calculating "the highest implemented exception level" could
simplify reading of the code a bit? E.g.:

    int highest_el = arm_feature(env, ARM_FEATURE_EL3) ? 3 :
                     arm_feature(env, ARM_FEATURE_EL2) ? 2 : 1;

We would probably want to have a dedicated static inline function for
this similar to HighestEL() from ARMv8 ARM pseudocode.

Kind regards,
Sergey
Peter Maydell Feb. 8, 2016, 3:30 p.m. UTC | #2
On 8 February 2016 at 15:25, Sergey Fedorov <serge.fdrv@gmail.com> wrote:
> On 05.02.2016 19:44, Peter Maydell wrote:
>> Correct some corner cases we were getting wrong for
>> CNTFRQ access rights:
>>  * should UNDEF from 32-bit Secure EL1
>>  * only writable from the highest implemented exception level,
>>    which might not be EL1 now

>> +    switch (arm_current_el(env)) {
>> +    case 0:
>> +        if (!extract32(env->cp15.c14_cntkctl, 0, 2)) {
>> +            return CP_ACCESS_TRAP;
>> +        }
>> +        /* EL0 reads are forbidden by the .access fields */
>
> s/reads/writes/ ?

Yes.

>> +        break;
>> +    case 1:
>> +        if (!isread && (arm_feature(env, ARM_FEATURE_EL2)
>> +                        || arm_feature(env, ARM_FEATURE_EL3))) {
>> +            return CP_ACCESS_TRAP_UNCATEGORIZED;
>> +        }
>> +        if (!isread && ri->state == ARM_CP_STATE_AA32 &&
>> +            arm_is_secure_below_el3(env)) {
>> +            /* Accesses from 32-bit Secure EL1 UNDEF (*not* trap to EL3!) */
>> +            return CP_ACCESS_TRAP_UNCATEGORIZED;
>> +        }
>> +        break;
>> +    case 2:
>> +        if (!isread && arm_feature(env, ARM_FEATURE_EL3)) {
>> +            return CP_ACCESS_TRAP_UNCATEGORIZED;
>> +        }
>> +        break;
>> +    case 3:
>> +        break;
>>      }
>>      return CP_ACCESS_OK;
>>  }
>
> Maybe calculating "the highest implemented exception level" could
> simplify reading of the code a bit? E.g.:
>
>     int highest_el = arm_feature(env, ARM_FEATURE_EL3) ? 3 :
>                      arm_feature(env, ARM_FEATURE_EL2) ? 2 : 1;
>
> We would probably want to have a dedicated static inline function for
> this similar to HighestEL() from ARMv8 ARM pseudocode.

Mmm, that might look neater. I'll have a play with the code.

thanks
-- PMM
diff mbox

Patch

diff --git a/target-arm/helper.c b/target-arm/helper.c
index 7a8881a..082701a 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -1217,9 +1217,34 @@  static const ARMCPRegInfo v6k_cp_reginfo[] = {
 static CPAccessResult gt_cntfrq_access(CPUARMState *env, const ARMCPRegInfo *ri,
                                        bool isread)
 {
-    /* CNTFRQ: not visible from PL0 if both PL0PCTEN and PL0VCTEN are zero */
-    if (arm_current_el(env) == 0 && !extract32(env->cp15.c14_cntkctl, 0, 2)) {
-        return CP_ACCESS_TRAP;
+    /* CNTFRQ: not visible from PL0 if both PL0PCTEN and PL0VCTEN are zero.
+     * Writable only at the highest implemented exception level.
+     */
+    switch (arm_current_el(env)) {
+    case 0:
+        if (!extract32(env->cp15.c14_cntkctl, 0, 2)) {
+            return CP_ACCESS_TRAP;
+        }
+        /* EL0 reads are forbidden by the .access fields */
+        break;
+    case 1:
+        if (!isread && (arm_feature(env, ARM_FEATURE_EL2)
+                        || arm_feature(env, ARM_FEATURE_EL3))) {
+            return CP_ACCESS_TRAP_UNCATEGORIZED;
+        }
+        if (!isread && ri->state == ARM_CP_STATE_AA32 &&
+            arm_is_secure_below_el3(env)) {
+            /* Accesses from 32-bit Secure EL1 UNDEF (*not* trap to EL3!) */
+            return CP_ACCESS_TRAP_UNCATEGORIZED;
+        }
+        break;
+    case 2:
+        if (!isread && arm_feature(env, ARM_FEATURE_EL3)) {
+            return CP_ACCESS_TRAP_UNCATEGORIZED;
+        }
+        break;
+    case 3:
+        break;
     }
     return CP_ACCESS_OK;
 }