diff mbox series

[4/4] target/arm: adjust CPTR_EL2 according to HCR_EL2.E2H

Message ID 20201207044655.2312-5-zhiwei_liu@c-sky.com
State New
Headers show
Series target/arm bug fix | expand

Commit Message

LIU Zhiwei Dec. 7, 2020, 4:46 a.m. UTC
From DDI0487Fc_armv8_arm.pdf, the CPTR_EL2 has two kinds
of layouts according to HCR_EL2.E2H.

When HCR_EL2.E2H is 1, fp_exception_el should refer to
HCR_EL2.FPEN and sve_exception_el should refer to HCR_EL2.ZEN.

Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: LIU Zhiwei <zhiwei_liu@c-sky.com>
---
 target/arm/helper.c | 55 +++++++++++++++++++++++++++++++++++++--------
 1 file changed, 46 insertions(+), 9 deletions(-)

Comments

Richard Henderson Dec. 8, 2020, 8:58 p.m. UTC | #1
On 12/6/20 10:46 PM, LIU Zhiwei wrote:
> From DDI0487Fc_armv8_arm.pdf, the CPTR_EL2 has two kinds
> of layouts according to HCR_EL2.E2H.
> 
> When HCR_EL2.E2H is 1, fp_exception_el should refer to
> HCR_EL2.FPEN and sve_exception_el should refer to HCR_EL2.ZEN.
> 
> Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
> Signed-off-by: LIU Zhiwei <zhiwei_liu@c-sky.com>
> ---
>  target/arm/helper.c | 55 +++++++++++++++++++++++++++++++++++++--------
>  1 file changed, 46 insertions(+), 9 deletions(-)
> 
> diff --git a/target/arm/helper.c b/target/arm/helper.c
> index 38cd35c049..6cc9f2bb50 100644
> --- a/target/arm/helper.c
> +++ b/target/arm/helper.c
> @@ -6147,11 +6147,30 @@ int sve_exception_el(CPUARMState *env, int el)
>       * they will be zero when EL2 is not present.
>       */
>      if (el <= 2 && !arm_is_secure_below_el3(env)) {
> -        if (env->cp15.cptr_el[2] & CPTR_TZ) {
> -            return 2;
> -        }
> -        if (env->cp15.cptr_el[2] & CPTR_TFP) {
> -            return 0;
> +        /* Since we exclude secure first, we may read HCR_EL2 directly. */
> +        if (env->cp15.hcr_el2 & HCR_E2H) {

We have already pulled the correct value into a local variable here: hcr_el2.
No need for the comment.

> +            int zen = extract32(env->cp15.cptr_el[2], 16, 2);
> +            switch (zen) {
> +            case 0:
> +            case 2:
> +                return 2;
> +            case 1:
> +                if (env->cp15.hcr_el2 & HCR_TGE) {

Likewise.

> +                    if (el == 0) {
> +                        return 2;
> +                    }
> +                }
> +                break;
> +            case 3:
> +                break;
> +            }
> +        } else {
> +            if (env->cp15.cptr_el[2] & CPTR_TZ) {
> +                return 2;
> +            }
> +            if (env->cp15.cptr_el[2] & CPTR_TFP) {
> +                return 0;
> +            }
>          }
>      }
>  
> @@ -12635,12 +12654,30 @@ int fp_exception_el(CPUARMState *env, int cur_el)
>       */
>  
>      /* CPTR_EL2 : present in v7VE or v8 */
> -    if (cur_el <= 2 && extract32(env->cp15.cptr_el[2], 10, 1)
> -        && !arm_is_secure_below_el3(env)) {
> +    if ((cur_el <= 2) && !arm_is_secure_below_el3(env)) {
>          /* Trap FP ops at EL2, NS-EL1 or NS-EL0 to EL2 */
> -        return 2;
> +        if ((arm_hcr_el2_eff(env) & HCR_E2H) == HCR_E2H) {

There is a prior use of arm_hcr_el2_eff in this function.  It should be called
once and stored in a local variable, just like in sve_exception_el.

No need for == in testing a single bit.

> +            int fpen = extract32(env->cp15.cptr_el[2], 20, 2);
> +            switch (fpen) {
> +            case 0:
> +            case 2:
> +                return 2;
> +            case 1:
> +                if ((arm_hcr_el2_eff(env) & HCR_TGE) == HCR_TGE) {

Likewise.

> +                    if (cur_el == 0) {
> +                        return 2;
> +                    }
> +                }
> +                break;
> +            case 3:
> +                break;
> +            }
> +        } else {
> +            if (extract32(env->cp15.cptr_el[2], 10, 1)) {

Use CPTR_TFP.

> +                return 2;
> +            }
> +        }
>      }
> -

Whitespace removal.

>      /* CPTR_EL3 : present in v8 */
>      if (extract32(env->cp15.cptr_el[3], 10, 1)) {
>          /* Trap all FP ops to EL3 */
> 

Would you also change this to use CPTR_TFP please?


r~
diff mbox series

Patch

diff --git a/target/arm/helper.c b/target/arm/helper.c
index 38cd35c049..6cc9f2bb50 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -6147,11 +6147,30 @@  int sve_exception_el(CPUARMState *env, int el)
      * they will be zero when EL2 is not present.
      */
     if (el <= 2 && !arm_is_secure_below_el3(env)) {
-        if (env->cp15.cptr_el[2] & CPTR_TZ) {
-            return 2;
-        }
-        if (env->cp15.cptr_el[2] & CPTR_TFP) {
-            return 0;
+        /* Since we exclude secure first, we may read HCR_EL2 directly. */
+        if (env->cp15.hcr_el2 & HCR_E2H) {
+            int zen = extract32(env->cp15.cptr_el[2], 16, 2);
+            switch (zen) {
+            case 0:
+            case 2:
+                return 2;
+            case 1:
+                if (env->cp15.hcr_el2 & HCR_TGE) {
+                    if (el == 0) {
+                        return 2;
+                    }
+                }
+                break;
+            case 3:
+                break;
+            }
+        } else {
+            if (env->cp15.cptr_el[2] & CPTR_TZ) {
+                return 2;
+            }
+            if (env->cp15.cptr_el[2] & CPTR_TFP) {
+                return 0;
+            }
         }
     }
 
@@ -12635,12 +12654,30 @@  int fp_exception_el(CPUARMState *env, int cur_el)
      */
 
     /* CPTR_EL2 : present in v7VE or v8 */
-    if (cur_el <= 2 && extract32(env->cp15.cptr_el[2], 10, 1)
-        && !arm_is_secure_below_el3(env)) {
+    if ((cur_el <= 2) && !arm_is_secure_below_el3(env)) {
         /* Trap FP ops at EL2, NS-EL1 or NS-EL0 to EL2 */
-        return 2;
+        if ((arm_hcr_el2_eff(env) & HCR_E2H) == HCR_E2H) {
+            int fpen = extract32(env->cp15.cptr_el[2], 20, 2);
+            switch (fpen) {
+            case 0:
+            case 2:
+                return 2;
+            case 1:
+                if ((arm_hcr_el2_eff(env) & HCR_TGE) == HCR_TGE) {
+                    if (cur_el == 0) {
+                        return 2;
+                    }
+                }
+                break;
+            case 3:
+                break;
+            }
+        } else {
+            if (extract32(env->cp15.cptr_el[2], 10, 1)) {
+                return 2;
+            }
+        }
     }
-
     /* CPTR_EL3 : present in v8 */
     if (extract32(env->cp15.cptr_el[3], 10, 1)) {
         /* Trap all FP ops to EL3 */