target/arm: Don't clear supported PMU events when initializing PMCEID1

A bug was introduced during a respin of:

	commit 57a4a11b2b
	target/arm: Add array for supported PMU events, generate PMCEID[01]_EL0

This patch introduced two calls to get_pmceid() during CPU
initialization - one each for PMCEID0 and PMCEID1. In addition to
building the register values, get_pmceid() clears an internal array
mapping event numbers to their implementations (supported_event_map)
before rebuilding it. This is an optimization since much of the logic is
shared. However, since it was called twice, the contents of
supported_event_map reflect only the events in PMCEID1 (the second call
to get_pmceid()).

Fix this bug by moving the initialization of PMCEID0 and PMCEID1 back
into a single function call, and name it more appropriately since it is
doing more than simply generating the contents of the PMCEID[01]
registers.

Signed-off-by: Aaron Lindsay <aaron@os.amperecomputing.com>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Message-id: 20190123195814.29253-1-aaron@os.amperecomputing.com
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Aaron Lindsay OS 2019-01-29 11:46:04 +00:00 committed by Peter Maydell
parent c8de3f5fd6
commit bf8d09694c
3 changed files with 22 additions and 19 deletions

View file

@ -1039,8 +1039,7 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
unset_feature(env, ARM_FEATURE_PMU);
}
if (arm_feature(env, ARM_FEATURE_PMU)) {
cpu->pmceid0 = get_pmceid(&cpu->env, 0);
cpu->pmceid1 = get_pmceid(&cpu->env, 1);
pmu_init(cpu);
if (!kvm_enabled()) {
arm_register_pre_el_change_hook(cpu, &pmu_pre_el_change, 0);

View file

@ -1012,14 +1012,13 @@ void pmu_pre_el_change(ARMCPU *cpu, void *ignored);
void pmu_post_el_change(ARMCPU *cpu, void *ignored);
/*
* get_pmceid
* @env: CPUARMState
* @which: which PMCEID register to return (0 or 1)
* pmu_init
* @cpu: ARMCPU
*
* Return the PMCEID[01]_EL0 register values corresponding to the counters
* which are supported given the current configuration
* Initialize the CPU's PMCEID[01]_EL0 registers and associated internal state
* for the current configuration
*/
uint64_t get_pmceid(CPUARMState *env, unsigned which);
void pmu_init(ARMCPU *cpu);
/* SCTLR bit meanings. Several bits have been reused in newer
* versions of the architecture; in that case we define constants

View file

@ -1090,22 +1090,24 @@ static const pm_event pm_events[] = {
static uint16_t supported_event_map[MAX_EVENT_ID + 1];
/*
* Called upon initialization to build PMCEID0_EL0 or PMCEID1_EL0 (indicated by
* 'which'). We also use it to build a map of ARM event numbers to indices in
* our pm_events array.
* Called upon CPU initialization to initialize PMCEID[01]_EL0 and build a map
* of ARM event numbers to indices in our pm_events array.
*
* Note: Events in the 0x40XX range are not currently supported.
*/
uint64_t get_pmceid(CPUARMState *env, unsigned which)
void pmu_init(ARMCPU *cpu)
{
uint64_t pmceid = 0;
unsigned int i;
assert(which <= 1);
/*
* Empty supported_event_map and cpu->pmceid[01] before adding supported
* events to them
*/
for (i = 0; i < ARRAY_SIZE(supported_event_map); i++) {
supported_event_map[i] = UNSUPPORTED_EVENT;
}
cpu->pmceid0 = 0;
cpu->pmceid1 = 0;
for (i = 0; i < ARRAY_SIZE(pm_events); i++) {
const pm_event *cnt = &pm_events[i];
@ -1113,13 +1115,16 @@ uint64_t get_pmceid(CPUARMState *env, unsigned which)
/* We do not currently support events in the 0x40xx range */
assert(cnt->number <= 0x3f);
if ((cnt->number & 0x20) == (which << 6) &&
cnt->supported(env)) {
pmceid |= (1 << (cnt->number & 0x1f));
if (cnt->supported(&cpu->env)) {
supported_event_map[cnt->number] = i;
uint64_t event_mask = 1 << (cnt->number & 0x1f);
if (cnt->number & 0x20) {
cpu->pmceid1 |= event_mask;
} else {
cpu->pmceid0 |= event_mask;
}
}
}
return pmceid;
}
/*