target/arm: Correct handling of PMCR_EL0.LC bit

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.

Backports commit 62d96ff48510f4bf648ad12f5d3a5507227b026f from qemu
This commit is contained in:
Peter Maydell 2020-03-21 18:40:24 -04:00 committed by Lioncash
parent de428e4b45
commit e72fa1cb33

View file

@ -877,6 +877,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
@ -1375,8 +1380,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);
}
@ -6165,7 +6170,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);