1/*
2 * Copyright 2017, Data61
3 * Commonwealth Scientific and Industrial Research Organisation (CSIRO)
4 * ABN 41 687 119 230.
5 *
6 * This software may be distributed and modified according to the terms of
7 * the BSD 2-Clause license. Note that NO WARRANTY is provided.
8 * See "LICENSE_BSD2.txt" for details.
9 *
10 * @TAG(DATA61_BSD)
11 */
12#pragma once
13#include <autoconf.h>
14#include <sel4utils/gen_config.h>
15#ifdef CONFIG_BENCHMARK_TRACK_KERNEL_ENTRIES
16
17#include <stdio.h>
18#include <sel4/types.h>
19#include <sel4/benchmark_track_types.h>
20
21/* Print out a summary of what has been tracked */
22static inline void seL4_BenchmarkTrackDumpSummary(benchmark_track_kernel_entry_t *logBuffer, size_t logSize)
23{
24    seL4_Word index = 0;
25    seL4_Word syscall_entries = 0;
26    seL4_Word interrupt_entries = 0;
27    seL4_Word userlevelfault_entries = 0;
28    seL4_Word vmfault_entries = 0;
29
30    /* Default driver to use for output now is serial.
31     * Change this to use other drivers than serial, i.e ethernet
32     */
33    FILE *fd = stdout;
34
35    while (logBuffer[index].start_time != 0 && (index * sizeof(benchmark_track_kernel_entry_t)) < logSize) {
36        if (logBuffer[index].entry.path == Entry_Syscall) {
37            syscall_entries++;
38        } else if (logBuffer[index].entry.path == Entry_Interrupt) {
39            interrupt_entries++;
40        } else if (logBuffer[index].entry.path == Entry_UserLevelFault) {
41            userlevelfault_entries++;
42        } else if (logBuffer[index].entry.path == Entry_VMFault) {
43            vmfault_entries++;
44        }
45        index++;
46    }
47
48    fprintf(fd, "Number of system call invocations %d\n", syscall_entries);
49    fprintf(fd, "Number of interrupt invocations %d\n", interrupt_entries);
50    fprintf(fd, "Number of user-level faults %d\n", userlevelfault_entries);
51    fprintf(fd, "Number of VM faults %d\n", vmfault_entries);
52}
53
54/* Print out logged system call invocations */
55static inline void seL4_BenchmarkTrackDumpFullSyscallLog(benchmark_track_kernel_entry_t *logBuffer, size_t logSize)
56{
57    seL4_Word index = 0;
58    FILE *fd = stdout;
59
60    /* Get details of each system call invocation */
61    fprintf(fd,
62            "-----------------------------------------------------------------------------------------------------------------------------\n");
63    fprintf(fd, "|     %-15s|     %-15s|     %-15s|     %-15s|     %-15s|     %-15s|     %-15s|\n",
64            "Log ID", "System Call ID", "Start Time", "Duration", "Capability Type",
65            "Invocation Tag",  "Fastpath?");
66    fprintf(fd,
67            "-----------------------------------------------------------------------------------------------------------------------------\n");
68
69    while (logBuffer[index].start_time != 0 && (index * sizeof(benchmark_track_kernel_entry_t)) < logSize) {
70        if (logBuffer[index].entry.path == Entry_Syscall) {
71            fprintf(fd, "|     %-15d|     %-15d|     %-15llu|     %-15d|     %-15d|     %-15d|     %-15d|\n",
72                    index,
73                    logBuffer[index].entry.syscall_no,
74                    (uint64_t) logBuffer[index].start_time,
75                    logBuffer[index].duration,
76                    logBuffer[index].entry.cap_type,
77                    logBuffer[index].entry.invocation_tag,
78                    logBuffer[index].entry.is_fastpath);
79        }
80        index++;
81    }
82}
83
84/* Print out logged interrupt invocations */
85static inline void seL4_BenchmarkTrackDumpFullInterruptLog(benchmark_track_kernel_entry_t *logBuffer, size_t logSize)
86{
87    seL4_Word index = 0;
88    FILE *fd = stdout;
89
90    /* Get details of each invocation */
91    fprintf(fd,
92            "-----------------------------------------------------------------------------------------------------------------------------\n");
93    fprintf(fd, "|     %-15s|     %-15s|     %-15s|     %-15s|\n", "Log ID", "IRQ", "Start Time",
94            "Duration");
95    fprintf(fd,
96            "-----------------------------------------------------------------------------------------------------------------------------\n");
97
98    while (logBuffer[index].start_time != 0 && (index * sizeof(benchmark_track_kernel_entry_t)) < logSize) {
99        if (logBuffer[index].entry.path == Entry_Interrupt) {
100            fprintf(fd, "|     %-15d|     %-15d|     %-15llu|     %-15d|\n", \
101                    index,
102                    logBuffer[index].entry.word,
103                    logBuffer[index].start_time,
104                    logBuffer[index].duration);
105        }
106        index++;
107    }
108}
109#endif /* CONFIG_BENCHMARK_TRACK_KERNEL_ENTRIES */
110