From 62d96ff48510f4bf648ad12f5d3a5507227b026f Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Fri, 14 Feb 2020 17:51:12 +0000 Subject: [PATCH] target/arm: Correct handling of PMCR_EL0.LC bit MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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. Reviewed-by: Richard Henderson Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Peter Maydell Message-id: 20200214175116.9164-18-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 e868b08cc1..15a840f530 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); } @@ -6370,7 +6374,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);