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

A bug was introduced during a respin of:

commit 57a4a11b2b281bb548b419ca81bfafb214e4c77a
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.

Backports commit bf8d09694ccc07487cd73d7562081fdaec3370c8 from qemu
This commit is contained in:
Aaron Lindsay OS 2019-01-29 17:09:33 -05:00 committed by Lioncash
parent 3fa54df972
commit 8d7bb2cab3
No known key found for this signature in database
GPG key ID: 4E3C3CC1031BA9C7
8 changed files with 31 additions and 28 deletions

View file

@ -3337,7 +3337,7 @@
#define fp_exception_el fp_exception_el_aarch64
#define gen_a64_set_pc_im gen_a64_set_pc_im_aarch64
#define gen_cmtst_i64 gen_cmtst_i64_aarch64
#define get_pmceid get_pmceid_aarch64
#define pmu_init pmu_init_aarch64
#define helper_advsimd_acge_f16 helper_advsimd_acge_f16_aarch64
#define helper_advsimd_acgt_f16 helper_advsimd_acgt_f16_aarch64
#define helper_advsimd_add2h helper_advsimd_add2h_aarch64

View file

@ -3337,7 +3337,7 @@
#define fp_exception_el fp_exception_el_aarch64eb
#define gen_a64_set_pc_im gen_a64_set_pc_im_aarch64eb
#define gen_cmtst_i64 gen_cmtst_i64_aarch64eb
#define get_pmceid get_pmceid_aarch64eb
#define pmu_init pmu_init_aarch64eb
#define helper_advsimd_acge_f16 helper_advsimd_acge_f16_aarch64eb
#define helper_advsimd_acgt_f16 helper_advsimd_acgt_f16_aarch64eb
#define helper_advsimd_add2h helper_advsimd_add2h_aarch64eb

View file

@ -3322,7 +3322,7 @@
#define cmtst_op cmtst_op_arm
#define fp_exception_el fp_exception_el_arm
#define gen_cmtst_i64 gen_cmtst_i64_arm
#define get_pmceid get_pmceid_arm
#define pmu_init pmu_init_arm
#define mla_op mla_op_arm
#define mls_op mls_op_arm
#define pmccntr_op_start pmccntr_op_start_arm

View file

@ -3322,7 +3322,7 @@
#define cmtst_op cmtst_op_armeb
#define fp_exception_el fp_exception_el_armeb
#define gen_cmtst_i64 gen_cmtst_i64_armeb
#define get_pmceid get_pmceid_armeb
#define pmu_init pmu_init_armeb
#define mla_op mla_op_armeb
#define mls_op mls_op_armeb
#define pmccntr_op_start pmccntr_op_start_armeb

View file

@ -3331,7 +3331,7 @@ arm_symbols = (
'cmtst_op',
'fp_exception_el',
'gen_cmtst_i64',
'get_pmceid',
'pmu_init',
'mla_op',
'mls_op',
'pmccntr_op_start',
@ -3383,7 +3383,7 @@ aarch64_symbols = (
'fp_exception_el',
'gen_a64_set_pc_im',
'gen_cmtst_i64',
'get_pmceid',
'pmu_init',
'helper_advsimd_acge_f16',
'helper_advsimd_acgt_f16',
'helper_advsimd_add2h',

View file

@ -764,8 +764,7 @@ static int arm_cpu_realizefn(struct uc_struct *uc, DeviceState *dev, Error **err
}
if (arm_feature(env, ARM_FEATURE_PMU)) {
cpu->pmceid0 = get_pmceid(&cpu->env, 0);
cpu->pmceid1 = get_pmceid(&cpu->env, 1);
pmu_init(cpu);
arm_register_pre_el_change_hook(cpu, &pmu_pre_el_change, 0);
arm_register_el_change_hook(cpu, &pmu_post_el_change, 0);

View file

@ -964,14 +964,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

@ -952,22 +952,24 @@ static const pm_event pm_events[] = {
#define UNSUPPORTED_EVENT UINT16_MAX
/*
* 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);
for (i = 0; i < ARRAY_SIZE(env->supported_event_map); i++) {
env->supported_event_map[i] = UNSUPPORTED_EVENT;
/*
* Empty supported_event_map and cpu->pmceid[01] before adding supported
* events to them
*/
for (i = 0; i < ARRAY_SIZE(cpu->env.supported_event_map); i++) {
cpu->env.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];
@ -975,13 +977,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));
env->supported_event_map[cnt->number] = i;
if (cnt->supported(&cpu->env)) {
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;
}
/*