A chained event overflowing on the low counter can set the overflow flag in PMOVS. KVM does not set it, but real HW and the fast-model seem to. Moreover, the AArch64.IncrementEventCounter() pseudocode in the ARM ARM (DDI 0487H.a, J1.1.1 "aarch64/debug") also sets the PMOVS bit on overflow. The pmu chain tests fail on bare metal when checking the overflow flag of the low counter _not_ being set on overflow. Fix by removing the checks. Signed-off-by: Ricardo Koller <ricarkol@xxxxxxxxxx> --- arm/pmu.c | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/arm/pmu.c b/arm/pmu.c index a7899c3c..4f2c5096 100644 --- a/arm/pmu.c +++ b/arm/pmu.c @@ -581,7 +581,6 @@ static void test_chained_counters(void) precise_instrs_loop(22, pmu.pmcr_ro | PMU_PMCR_E); report(read_regn_el0(pmevcntr, 1) == 1, "CHAIN counter #1 incremented"); - report(!read_sysreg(pmovsclr_el0), "no overflow recorded for chained incr #1"); /* test 64b overflow */ @@ -593,7 +592,7 @@ static void test_chained_counters(void) precise_instrs_loop(22, pmu.pmcr_ro | PMU_PMCR_E); report_info("overflow reg = 0x%lx", read_sysreg(pmovsclr_el0)); report(read_regn_el0(pmevcntr, 1) == 2, "CHAIN counter #1 set to 2"); - report(!read_sysreg(pmovsclr_el0), "no overflow recorded for chained incr #2"); + report((read_sysreg(pmovsclr_el0) & 0x2) == 0, "no overflow recorded for chained incr #2"); write_regn_el0(pmevcntr, 0, PRE_OVERFLOW); write_regn_el0(pmevcntr, 1, ALL_SET); @@ -601,7 +600,7 @@ static void test_chained_counters(void) precise_instrs_loop(22, pmu.pmcr_ro | PMU_PMCR_E); report_info("overflow reg = 0x%lx", read_sysreg(pmovsclr_el0)); report(!read_regn_el0(pmevcntr, 1), "CHAIN counter #1 wrapped"); - report(read_sysreg(pmovsclr_el0) == 0x2, "overflow on chain counter"); + report(read_sysreg(pmovsclr_el0) & 0x2, "overflow on chain counter"); } static void test_chained_sw_incr(void) @@ -626,10 +625,10 @@ static void test_chained_sw_incr(void) for (i = 0; i < 100; i++) write_sysreg(0x1, pmswinc_el0); - report(!read_sysreg(pmovsclr_el0) && (read_regn_el0(pmevcntr, 1) == 1), - "no overflow and chain counter incremented after 100 SW_INCR/CHAIN"); + report(read_regn_el0(pmevcntr, 1) == 1, + "no chain counter incremented after 100 SW_INCR/CHAIN"); report_info("overflow=0x%lx, #0=%ld #1=%ld", read_sysreg(pmovsclr_el0), - read_regn_el0(pmevcntr, 0), read_regn_el0(pmevcntr, 1)); + read_regn_el0(pmevcntr, 0), read_regn_el0(pmevcntr, 1)); /* 64b SW_INCR and overflow on CHAIN counter*/ pmu_reset(); @@ -644,7 +643,7 @@ static void test_chained_sw_incr(void) for (i = 0; i < 100; i++) write_sysreg(0x1, pmswinc_el0); - report((read_sysreg(pmovsclr_el0) == 0x2) && + report((read_sysreg(pmovsclr_el0) & 0x2) && (read_regn_el0(pmevcntr, 1) == 0) && (read_regn_el0(pmevcntr, 0) == 84), "overflow on chain counter and expected values after 100 SW_INCR/CHAIN"); @@ -727,8 +726,8 @@ static void test_chain_promotion(void) report_info("MEM_ACCESS counter #0 has value 0x%lx", read_regn_el0(pmevcntr, 0)); - report((read_regn_el0(pmevcntr, 1) == 1) && !read_sysreg(pmovsclr_el0), - "CHAIN counter enabled: CHAIN counter was incremented and no overflow"); + report((read_regn_el0(pmevcntr, 1) == 1), + "CHAIN counter enabled: CHAIN counter was incremented"); report_info("CHAIN counter #1 = 0x%lx, overflow=0x%lx", read_regn_el0(pmevcntr, 1), read_sysreg(pmovsclr_el0)); @@ -755,8 +754,8 @@ static void test_chain_promotion(void) report_info("MEM_ACCESS counter #0 has value 0x%lx", read_regn_el0(pmevcntr, 0)); - report((read_regn_el0(pmevcntr, 1) == 1) && !read_sysreg(pmovsclr_el0), - "32b->64b: CHAIN counter incremented and no overflow"); + report((read_regn_el0(pmevcntr, 1) == 1), + "32b->64b: CHAIN counter incremented"); report_info("CHAIN counter #1 = 0x%lx, overflow=0x%lx", read_regn_el0(pmevcntr, 1), read_sysreg(pmovsclr_el0)); -- 2.37.0.170.g444d1eabd0-goog