Index: sys/dev/tprof/tprof_armv8.c =================================================================== RCS file: /cvsroot/src/sys/dev/tprof/tprof_armv8.c,v retrieving revision 1.7 diff -u -p -r1.7 tprof_armv8.c --- sys/dev/tprof/tprof_armv8.c 26 Sep 2021 13:37:36 -0000 1.7 +++ sys/dev/tprof/tprof_armv8.c 26 Oct 2021 09:04:42 -0000 @@ -42,9 +42,9 @@ __KERNEL_RCSID(0, "$NetBSD: tprof_armv8. #include static tprof_param_t armv8_pmu_param; -static const u_int armv8_pmu_counter = 1; -static uint32_t counter_val; -static uint32_t counter_reset_val; +static const u_int armv8_pmu_evcounter = 0; +static uint32_t evcounter_val; +static uint32_t evcounter_reset_val; static bool armv8_pmu_event_implemented(uint16_t event) @@ -57,6 +57,7 @@ armv8_pmu_event_implemented(uint16_t eve eid[0] = reg_pmceid0_el0_read(); eid[1] = reg_pmceid1_el0_read(); + /* The low 32bits of PMCEID[01]_EL0 contain the commmon events 0 to n */ const u_int idx = event / 32; const u_int bit = event % 32; @@ -67,17 +68,17 @@ armv8_pmu_event_implemented(uint16_t eve } static void -armv8_pmu_set_pmevtyper(u_int counter, uint64_t val) +armv8_pmu_set_pmevtyper(u_int evcounter, uint64_t val) { - reg_pmselr_el0_write(counter); + reg_pmselr_el0_write(evcounter); isb(); reg_pmxevtyper_el0_write(val); } static void -armv8_pmu_set_pmevcntr(u_int counter, uint32_t val) +armv8_pmu_set_pmevcntr(u_int evcounter, uint32_t val) { - reg_pmselr_el0_write(counter); + reg_pmselr_el0_write(evcounter); isb(); reg_pmxevcntr_el0_write(val); } @@ -85,11 +86,11 @@ armv8_pmu_set_pmevcntr(u_int counter, ui static void armv8_pmu_start_cpu(void *arg1, void *arg2) { - const uint32_t counter_mask = __BIT(armv8_pmu_counter); + const uint32_t evcounter_mask = __BIT(armv8_pmu_evcounter); uint64_t pmevtyper; /* Disable event counter */ - reg_pmcntenclr_el0_write(counter_mask); + reg_pmcntenclr_el0_write(evcounter_mask); /* Configure event counter */ pmevtyper = __SHIFTIN(armv8_pmu_param.p_event, PMEVTYPER_EVTCOUNT); @@ -98,32 +99,32 @@ armv8_pmu_start_cpu(void *arg1, void *ar if (!ISSET(armv8_pmu_param.p_flags, TPROF_PARAM_KERN)) pmevtyper |= PMEVTYPER_P; - armv8_pmu_set_pmevtyper(armv8_pmu_counter, pmevtyper); + armv8_pmu_set_pmevtyper(armv8_pmu_evcounter, pmevtyper); /* Enable overflow interrupts */ - reg_pmintenset_el1_write(counter_mask); + reg_pmintenset_el1_write(evcounter_mask); /* Clear overflow flag */ - reg_pmovsclr_el0_write(counter_mask); + reg_pmovsclr_el0_write(evcounter_mask); /* Initialize event counter value */ - armv8_pmu_set_pmevcntr(armv8_pmu_counter, counter_reset_val); + armv8_pmu_set_pmevcntr(armv8_pmu_evcounter, evcounter_reset_val); /* Enable event counter */ - reg_pmcntenset_el0_write(counter_mask); + reg_pmcntenset_el0_write(evcounter_mask); reg_pmcr_el0_write(PMCR_E); } static void armv8_pmu_stop_cpu(void *arg1, void *arg2) { - const uint32_t counter_mask = __BIT(armv8_pmu_counter); + const uint32_t evcounter_mask = __BIT(armv8_pmu_evcounter); /* Disable overflow interrupts */ - reg_pmintenclr_el1_write(counter_mask); + reg_pmintenclr_el1_write(evcounter_mask); /* Disable event counter */ - reg_pmcntenclr_el0_write(counter_mask); + reg_pmcntenclr_el0_write(evcounter_mask); reg_pmcr_el0_write(0); } @@ -133,9 +134,9 @@ armv8_pmu_estimate_freq(void) uint64_t cpufreq = curcpu()->ci_data.cpu_cc_freq; uint64_t freq = 10000; - counter_val = cpufreq / freq; - if (counter_val == 0) - counter_val = 4000000000ULL / freq; + evcounter_val = cpufreq / freq; + if (evcounter_val == 0) + evcounter_val = 4000000000ULL / freq; return freq; } @@ -149,7 +150,13 @@ armv8_pmu_ident(void) static int armv8_pmu_start(const tprof_param_t *param) { - uint64_t xc; + uint64_t pmcr_el0 = reg_pmcr_el0_read(); + + // PMCR.N of 0 means that no event counters are available + if (__SHIFTOUT(pmcr_el0, PMCR_N) == 0) { +printf("%s: number of event counters: %ld\n", __func__, __SHIFTOUT(pmcr_el0, PMCR_N)); + return EINVAL; + } if (!armv8_pmu_event_implemented(param->p_event)) { printf("%s: event %#" PRIx64 " not implemented on this CPU\n", @@ -157,10 +164,10 @@ armv8_pmu_start(const tprof_param_t *par return EINVAL; } - counter_reset_val = -counter_val + 1; + evcounter_reset_val = -evcounter_val + 1; armv8_pmu_param = *param; - xc = xc_broadcast(0, armv8_pmu_start_cpu, NULL, NULL); + uint64_t xc = xc_broadcast(0, armv8_pmu_start_cpu, NULL, NULL); xc_wait(xc); return 0; @@ -186,17 +193,17 @@ int armv8_pmu_intr(void *priv) { const struct trapframe * const tf = priv; - const uint32_t counter_mask = __BIT(armv8_pmu_counter); + const uint32_t evcounter_mask = __BIT(armv8_pmu_evcounter); tprof_frame_info_t tfi; const uint32_t pmovs = reg_pmovsset_el0_read(); - if ((pmovs & counter_mask) != 0) { + if ((pmovs & evcounter_mask) != 0) { tfi.tfi_pc = tf->tf_pc; tfi.tfi_inkernel = tfi.tfi_pc >= VM_MIN_KERNEL_ADDRESS && tfi.tfi_pc < VM_MAX_KERNEL_ADDRESS; tprof_sample(NULL, &tfi); - armv8_pmu_set_pmevcntr(armv8_pmu_counter, counter_reset_val); + armv8_pmu_set_pmevcntr(armv8_pmu_evcounter, evcounter_reset_val); } reg_pmovsclr_el0_write(pmovs); @@ -205,7 +212,7 @@ armv8_pmu_intr(void *priv) static void armv8_pmu_init_cpu(void *arg1, void *arg2) -{ +{ /* Disable EL0 access to performance monitors */ reg_pmuserenr_el0_write(0); @@ -219,9 +226,13 @@ armv8_pmu_init_cpu(void *arg1, void *arg int armv8_pmu_init(void) { - uint64_t xc; - xc = xc_broadcast(0, armv8_pmu_init_cpu, NULL, NULL); +#if 0 + if (no counters available) + return EINVAL; + +#endif + uint64_t xc = xc_broadcast(0, armv8_pmu_init_cpu, NULL, NULL); xc_wait(xc); return tprof_backend_register("tprof_armv8", &tprof_armv8_pmu_ops,