1/*
2 * Copyright 2014, General Dynamics C4 Systems
3 *
4 * SPDX-License-Identifier: GPL-2.0-only
5 */
6
7#pragma once
8
9#include <config.h>
10#ifdef CONFIG_ENABLE_BENCHMARKS
11
12#include <armv/benchmark.h>
13#include <mode/machine.h>
14#include <model/statedata.h>
15
16/* these values are consistent across all arm PMUs */
17#define PMCR_ENABLE 0
18#define PMCR_ECNT_RESET 1
19#define PMCR_CCNT_RESET 2
20
21#if defined(CONFIG_BENCHMARK_TRACK_UTILISATION) && defined(KERNEL_PMU_IRQ)
22#define CONFIG_ARM_ENABLE_PMU_OVERFLOW_INTERRUPT 1
23#endif
24
25void arm_init_ccnt(void);
26
27static inline timestamp_t timestamp(void)
28{
29    timestamp_t ccnt;
30    SYSTEM_READ_WORD(CCNT, ccnt);
31    return ccnt;
32}
33
34#ifdef CONFIG_ARM_ENABLE_PMU_OVERFLOW_INTERRUPT
35static inline void handleOverflowIRQ(void)
36{
37    if (likely(NODE_STATE(benchmark_log_utilisation_enabled))) {
38        NODE_STATE(ksCurThread)->benchmark.utilisation += UINT32_MAX - NODE_STATE(ksCurThread)->benchmark.schedule_start_time;
39        NODE_STATE(ksCurThread)->benchmark.schedule_start_time = 0;
40        NODE_STATE(ccnt_num_overflows)++;
41    }
42    armv_handleOverflowIRQ();
43}
44#endif /* CONFIG_ARM_ENABLE_PMU_OVERFLOW_INTERRUPT */
45
46static inline void benchmark_arch_utilisation_reset(void)
47{
48#ifdef CONFIG_ARM_ENABLE_PMU_OVERFLOW_INTERRUPT
49    NODE_STATE(ccnt_num_overflows) = 0;
50#endif /* CONFIG_ARM_ENABLE_PMU_OVERFLOW_INTERRUPT */
51}
52#endif /* CONFIG_ENABLE_BENCHMARKS */
53
54