1 /*
2  * Copyright 2016, General Dynamics C4 Systems
3  *
4  * SPDX-License-Identifier: GPL-2.0-only
5  */
6 
7 #include <config.h>
8 #include <benchmark/benchmark_utilisation.h>
9 
10 #ifdef CONFIG_BENCHMARK_TRACK_UTILISATION
11 
12 timestamp_t ksEnter;
13 
benchmark_track_utilisation_dump(void)14 void benchmark_track_utilisation_dump(void)
15 {
16     uint64_t *buffer = ((uint64_t *) & (((seL4_IPCBuffer *)lookupIPCBuffer(true, NODE_STATE(ksCurThread)))->msg[0]));
17     tcb_t *tcb = NULL;
18     word_t tcb_cptr = getRegister(NODE_STATE(ksCurThread), capRegister);
19     lookupCap_ret_t lu_ret;
20     word_t cap_type;
21 
22     lu_ret = lookupCap(NODE_STATE(ksCurThread), tcb_cptr);
23     /* ensure we got a TCB cap */
24     cap_type = cap_get_capType(lu_ret.cap);
25     if (cap_type != cap_thread_cap) {
26         userError("SysBenchmarkFinalizeLog: cap is not a TCB, halting");
27         return;
28     }
29 
30     tcb = TCB_PTR(cap_thread_cap_get_capTCBPtr(lu_ret.cap));
31 
32     /* Selected TCB counters */
33     buffer[BENCHMARK_TCB_UTILISATION] = tcb->benchmark.utilisation; /* Requested thread utilisation */
34     buffer[BENCHMARK_TCB_NUMBER_SCHEDULES] = tcb->benchmark.number_schedules; /* Number of times scheduled */
35     buffer[BENCHMARK_TCB_KERNEL_UTILISATION] = tcb->benchmark.kernel_utilisation; /* Utilisation spent in kernel */
36     buffer[BENCHMARK_TCB_NUMBER_KERNEL_ENTRIES] = tcb->benchmark.number_kernel_entries; /* Number of kernel entries */
37 
38     /* Idle counters */
39     buffer[BENCHMARK_IDLE_LOCALCPU_UTILISATION] = NODE_STATE(
40                                                       ksIdleThread)->benchmark.utilisation; /* Idle thread utilisation of current CPU */
41 #ifdef ENABLE_SMP_SUPPORT
42     buffer[BENCHMARK_IDLE_TCBCPU_UTILISATION] = NODE_STATE_ON_CORE(ksIdleThread,
43                                                                    tcb->tcbAffinity)->benchmark.utilisation; /* Idle thread utilisation of CPU the TCB is running on */
44 #else
45     buffer[BENCHMARK_IDLE_TCBCPU_UTILISATION] = buffer[BENCHMARK_IDLE_LOCALCPU_UTILISATION];
46 #endif
47 
48     buffer[BENCHMARK_IDLE_NUMBER_SCHEDULES] = NODE_STATE(
49                                                   ksIdleThread)->benchmark.number_schedules; /* Number of times scheduled */
50     buffer[BENCHMARK_IDLE_KERNEL_UTILISATION] = NODE_STATE(
51                                                     ksIdleThread)->benchmark.kernel_utilisation; /* Utilisation spent in kernel */
52     buffer[BENCHMARK_IDLE_NUMBER_KERNEL_ENTRIES] = NODE_STATE(
53                                                        ksIdleThread)->benchmark.number_kernel_entries; /* Number of kernel entries */
54 
55 
56     /* Total counters */
57 #ifdef CONFIG_ARM_ENABLE_PMU_OVERFLOW_INTERRUPT
58     buffer[BENCHMARK_TOTAL_UTILISATION] =
59         (NODE_STATE(ccnt_num_overflows) * 0xFFFFFFFFU) + NODE_STATE(benchmark_end_time) - NODE_STATE(benchmark_start_time);
60 #else
61     buffer[BENCHMARK_TOTAL_UTILISATION] = NODE_STATE(benchmark_end_time) - NODE_STATE(
62                                               benchmark_start_time); /* Overall time */
63 #endif /* CONFIG_ARM_ENABLE_PMU_OVERFLOW_INTERRUPT */
64     buffer[BENCHMARK_TOTAL_NUMBER_SCHEDULES] = NODE_STATE(benchmark_kernel_number_schedules);
65     buffer[BENCHMARK_TOTAL_KERNEL_UTILISATION] = NODE_STATE(benchmark_kernel_time);
66     buffer[BENCHMARK_TOTAL_NUMBER_KERNEL_ENTRIES] = NODE_STATE(benchmark_kernel_number_entries);
67 
68 }
69 
benchmark_track_reset_utilisation(tcb_t * tcb)70 void benchmark_track_reset_utilisation(tcb_t *tcb)
71 {
72     tcb->benchmark.utilisation = 0;
73     tcb->benchmark.number_schedules = 0;
74     tcb->benchmark.number_kernel_entries = 0;
75     tcb->benchmark.kernel_utilisation = 0;
76     tcb->benchmark.schedule_start_time = 0;
77 }
78 #endif /* CONFIG_BENCHMARK_TRACK_UTILISATION */
79