diff mbox series

[13/13] target/arm: Correct handling of PMCR_EL0.LC bit

Message ID 20200211173726.22541-14-peter.maydell@linaro.org
State Superseded
Headers show
Series arm: Implement ARMv8.1-PMU and ARMv8.4-PMU | expand

Commit Message

Peter Maydell Feb. 11, 2020, 5:37 p.m. UTC
The LC bit in the PMCR_EL0 register is supposed to be:
 * read/write
 * RES1 on an AArch64-only implementation
 * an architecturally UNKNOWN value on reset
(and use of LC==0 by software is deprecated).

We were implementing it incorrectly as read-only always zero,
though we do have all the code needed to test it and behave
accordingly.

Instead make it a read-write bit which resets to 1 always, which
satisfies all the architectural requirements above.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>

---
 target/arm/helper.c | 13 +++++++++----
 1 file changed, 9 insertions(+), 4 deletions(-)

-- 
2.20.1

Comments

Richard Henderson Feb. 11, 2020, 6:55 p.m. UTC | #1
On 2/11/20 9:37 AM, Peter Maydell wrote:
> The LC bit in the PMCR_EL0 register is supposed to be:

>  * read/write

>  * RES1 on an AArch64-only implementation

>  * an architecturally UNKNOWN value on reset

> (and use of LC==0 by software is deprecated).

> 

> We were implementing it incorrectly as read-only always zero,

> though we do have all the code needed to test it and behave

> accordingly.

> 

> Instead make it a read-write bit which resets to 1 always, which

> satisfies all the architectural requirements above.

> 

> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>

> ---

>  target/arm/helper.c | 13 +++++++++----

>  1 file changed, 9 insertions(+), 4 deletions(-)


Reviewed-by: Richard Henderson <richard.henderson@linaro.org>



r~
Philippe Mathieu-Daudé Feb. 12, 2020, 7:14 a.m. UTC | #2
On 2/11/20 6:37 PM, Peter Maydell wrote:
> The LC bit in the PMCR_EL0 register is supposed to be:

>   * read/write

>   * RES1 on an AArch64-only implementation

>   * an architecturally UNKNOWN value on reset

> (and use of LC==0 by software is deprecated).

> 

> We were implementing it incorrectly as read-only always zero,

> though we do have all the code needed to test it and behave

> accordingly.

> 

> Instead make it a read-write bit which resets to 1 always, which

> satisfies all the architectural requirements above.

> 

> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>

> ---

>   target/arm/helper.c | 13 +++++++++----

>   1 file changed, 9 insertions(+), 4 deletions(-)

> 

> diff --git a/target/arm/helper.c b/target/arm/helper.c

> index c6758bfbeb5..1d8eafceda8 100644

> --- a/target/arm/helper.c

> +++ b/target/arm/helper.c

> @@ -1023,6 +1023,11 @@ static const ARMCPRegInfo v6_cp_reginfo[] = {

>   #define PMCRC   0x4

>   #define PMCRP   0x2

>   #define PMCRE   0x1

> +/*

> + * Mask of PMCR bits writeable by guest (not including WO bits like C, P,

> + * which can be written as 1 to trigger behaviour but which stay RAZ).

> + */

> +#define PMCR_WRITEABLE_MASK (PMCRLC | PMCRDP | PMCRX | PMCRD | PMCRE)

>   

>   #define PMXEVTYPER_P          0x80000000

>   #define PMXEVTYPER_U          0x40000000

> @@ -1577,9 +1582,8 @@ static void pmcr_write(CPUARMState *env, const ARMCPRegInfo *ri,

>           }

>       }

>   

> -    /* only the DP, X, D and E bits are writable */

> -    env->cp15.c9_pmcr &= ~0x39;

> -    env->cp15.c9_pmcr |= (value & 0x39);


Ah this was missing PMCRLC indeed.

I was tempted to use 'Fixes: 74594c9d813' but the PMCRLC is "Reserved, 
UNK/SBZP" in the ARMv7 reference manual.
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>


> +    env->cp15.c9_pmcr &= ~PMCR_WRITEABLE_MASK;

> +    env->cp15.c9_pmcr |= (value & PMCR_WRITEABLE_MASK);

>   

>       pmu_op_finish(env);

>   }

> @@ -5886,7 +5890,8 @@ static void define_pmu_regs(ARMCPU *cpu)

>           .access = PL0_RW, .accessfn = pmreg_access,

>           .type = ARM_CP_IO,

>           .fieldoffset = offsetof(CPUARMState, cp15.c9_pmcr),

> -        .resetvalue = (cpu->midr & 0xff000000) | (pmcrn << PMCRN_SHIFT),

> +        .resetvalue = (cpu->midr & 0xff000000) | (pmcrn << PMCRN_SHIFT) |

> +                      PMCRLC,

>           .writefn = pmcr_write, .raw_writefn = raw_write,

>       };

>       define_one_arm_cp_reg(cpu, &pmcr);

>
diff mbox series

Patch

diff --git a/target/arm/helper.c b/target/arm/helper.c
index c6758bfbeb5..1d8eafceda8 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -1023,6 +1023,11 @@  static const ARMCPRegInfo v6_cp_reginfo[] = {
 #define PMCRC   0x4
 #define PMCRP   0x2
 #define PMCRE   0x1
+/*
+ * Mask of PMCR bits writeable by guest (not including WO bits like C, P,
+ * which can be written as 1 to trigger behaviour but which stay RAZ).
+ */
+#define PMCR_WRITEABLE_MASK (PMCRLC | PMCRDP | PMCRX | PMCRD | PMCRE)
 
 #define PMXEVTYPER_P          0x80000000
 #define PMXEVTYPER_U          0x40000000
@@ -1577,9 +1582,8 @@  static void pmcr_write(CPUARMState *env, const ARMCPRegInfo *ri,
         }
     }
 
-    /* only the DP, X, D and E bits are writable */
-    env->cp15.c9_pmcr &= ~0x39;
-    env->cp15.c9_pmcr |= (value & 0x39);
+    env->cp15.c9_pmcr &= ~PMCR_WRITEABLE_MASK;
+    env->cp15.c9_pmcr |= (value & PMCR_WRITEABLE_MASK);
 
     pmu_op_finish(env);
 }
@@ -5886,7 +5890,8 @@  static void define_pmu_regs(ARMCPU *cpu)
         .access = PL0_RW, .accessfn = pmreg_access,
         .type = ARM_CP_IO,
         .fieldoffset = offsetof(CPUARMState, cp15.c9_pmcr),
-        .resetvalue = (cpu->midr & 0xff000000) | (pmcrn << PMCRN_SHIFT),
+        .resetvalue = (cpu->midr & 0xff000000) | (pmcrn << PMCRN_SHIFT) |
+                      PMCRLC,
         .writefn = pmcr_write, .raw_writefn = raw_write,
     };
     define_one_arm_cp_reg(cpu, &pmcr);