From bd0b8fe84df4a23c3bf7848d2dde4bb8681d4057 Mon Sep 17 00:00:00 2001 From: liusai Date: Fri, 17 May 2024 11:31:33 +0800 Subject: [PATCH] lib/tnperf:add perf module Signed-off-by: liusai --- lib/Makefile.uk | 1 + lib/tnperf/Config.uk | 15 ++++++++++++ lib/tnperf/Makefile.uk | 6 +++++ lib/tnperf/include/tn/cpu_cycles.h | 35 +++++++++++++++++++++++++++ lib/tnperf/include/tn/perf.h | 38 ++++++++++++++++++++++++++++++ lib/tnperf/perf.c | 25 ++++++++++++++++++++ lib/ukboot/boot.c | 5 ++++ 7 files changed, 125 insertions(+) create mode 100644 lib/tnperf/Config.uk create mode 100644 lib/tnperf/Makefile.uk create mode 100644 lib/tnperf/include/tn/cpu_cycles.h create mode 100644 lib/tnperf/include/tn/perf.h create mode 100644 lib/tnperf/perf.c diff --git a/lib/Makefile.uk b/lib/Makefile.uk index 0c97ada0..306952b4 100644 --- a/lib/Makefile.uk +++ b/lib/Makefile.uk @@ -72,3 +72,4 @@ $(eval $(call import_lib,$(CONFIG_UK_BASE)/lib/ukreloc)) $(eval $(call import_lib,$(CONFIG_UK_BASE)/lib/ukofw)) $(eval $(call import_lib,$(CONFIG_UK_BASE)/lib/tnsystick)) $(eval $(call import_lib,$(CONFIG_UK_BASE)/lib/tntimer)) +$(eval $(call import_lib,$(CONFIG_UK_BASE)/lib/tnperf)) diff --git a/lib/tnperf/Config.uk b/lib/tnperf/Config.uk new file mode 100644 index 00000000..2935b133 --- /dev/null +++ b/lib/tnperf/Config.uk @@ -0,0 +1,15 @@ +menuconfig LIBTNPERF + bool "tnperf: Provide burying point method" + default n + +if LIBTNPERF + +menu "pmu event" + + config LIBTNPERF_CPU_CYCLES + bool "enable pmu event of cpu cycles" + default n + +endmenu + +endif diff --git a/lib/tnperf/Makefile.uk b/lib/tnperf/Makefile.uk new file mode 100644 index 00000000..b7dc9763 --- /dev/null +++ b/lib/tnperf/Makefile.uk @@ -0,0 +1,6 @@ +$(eval $(call addlib_s,libtnperf,$(CONFIG_LIBTNPERF))) + +CINCLUDES-$(CONFIG_LIBTNPERF) += -I$(LIBTNPERF_BASE)/include +CXXINCLUDES-$(CONFIG_LIBTNPERF) += -I$(LIBTNPERF_BASE)/include + +LIBTNPERF_SRCS-y += $(LIBTNPERF_BASE)/perf.c diff --git a/lib/tnperf/include/tn/cpu_cycles.h b/lib/tnperf/include/tn/cpu_cycles.h new file mode 100644 index 00000000..9e7fa13a --- /dev/null +++ b/lib/tnperf/include/tn/cpu_cycles.h @@ -0,0 +1,35 @@ +#ifndef __TN_CPU_CYCLES_H__ +#define __TN_CPU_CYCLES_H__ + +#include "perf.h" + +uint64_t cnt; + +void cpu_cycles_start(void) +{ + asm volatile("msr pmcr_el0, %0" : : "r" (17)); + asm volatile("msr PMCNTENSET_EL0, %0" : : "r" (0x8000000f)); + asm volatile("msr PMOVSCLR_EL0, %0" : : "r" (0x8000000f)); +} + +uint64_t cpu_cycles_read_counter(void) +{ + asm volatile("mrs %0, PMCCNTR_EL0" : "=r" (cnt)); + return cnt; +} + +void tn_pmu_cpu_cycles_create(void) +{ + struct perf_event *e = malloc(sizeof(struct perf_event)); + int enable = 1; + + e->enable = enable; + e->id = CPU_CYCLES; + struct pmu *p = malloc(sizeof(struct pmu)); + + tn_pmu_init(p, cpu_cycles_start, cpu_cycles_read_counter); + e->pmu = p; + cpu_hw_events[CPU_CYCLES] = e; +} + +#endif /* __TN_CPU_CYCLES_H__ */ diff --git a/lib/tnperf/include/tn/perf.h b/lib/tnperf/include/tn/perf.h new file mode 100644 index 00000000..348eb8bb --- /dev/null +++ b/lib/tnperf/include/tn/perf.h @@ -0,0 +1,38 @@ +#ifndef __TN_PERF_H__ +#define __TN_PERF_H__ + +#include + +enum event_id { + CPU_CYCLES = 0, +}; + +typedef void (*tn_pmu_start)(); +typedef uint64_t (*tn_pmu_read_counter)(); + +struct pmu { + tn_pmu_start pmu_start; + tn_pmu_read_counter pmu_read_counter; +}; + +struct perf_event { + int enable; + enum event_id id; + struct pmu *pmu; +}; + +extern struct perf_event *cpu_hw_events[7]; + +#define tn_pmu_init(pmu, pmu_start_func, pmu_read_counter_func) \ + do { \ + (pmu)->pmu_start = pmu_start_func; \ + (pmu)->pmu_read_counter = pmu_read_counter_func; \ + } while (0) + +void tn_cpu_pmu_probe(void); + +struct perf_event *tn_event_get(enum event_id id); + +uint64_t tn_pmu_read(struct perf_event *e); + +#endif /* __TN_PERF_H__ */ diff --git a/lib/tnperf/perf.c b/lib/tnperf/perf.c new file mode 100644 index 00000000..5a825514 --- /dev/null +++ b/lib/tnperf/perf.c @@ -0,0 +1,25 @@ +#include +#include + +struct perf_event *cpu_hw_events[7]; + +void tn_cpu_pmu_probe(void) +{ +#ifdef CONFIG_LIBTNPERF_CPU_CYCLES + tn_pmu_cpu_cycles_create(); +#endif + for (int i = 0; i < 7; i++) { + if (cpu_hw_events[i] && cpu_hw_events[i]->enable) + cpu_hw_events[i]->pmu->pmu_start(); + } +} + +struct perf_event *tn_event_get(enum event_id id) +{ + return cpu_hw_events[id]; +} + +uint64_t tn_pmu_read(struct perf_event *e) +{ + return e->pmu->pmu_read_counter(); +} diff --git a/lib/ukboot/boot.c b/lib/ukboot/boot.c index bf422786..655bd161 100644 --- a/lib/ukboot/boot.c +++ b/lib/ukboot/boot.c @@ -349,6 +349,11 @@ void ukplat_entry(int argc, char *argv[]) UK_CRASH("Could not initialize the IRQ subsystem\n"); #endif /* CONFIG_LIBUKINTCTLR */ +#if CONFIG_LIBTNPERF + uk_pr_info("Initialize the PMU...\n"); + tn_cpu_pmu_probe(); +#endif /* CONFIG_LIBTNPERF */ + /* On most platforms the timer depend on an initialized IRQ subsystem */ uk_pr_info("Initialize platform time...\n"); #if CONFIG_HAVE_SYSTICK -- Gitee