1/*
2 * Copyright 2014, General Dynamics C4 Systems
3 *
4 * SPDX-License-Identifier: GPL-2.0-only
5 */
6
7#include <config.h>
8
9#ifdef CONFIG_DEBUG_BUILD
10#pragma once
11
12#include <benchmark/benchmark_track.h>
13#include <arch/api/syscall.h>
14#include <arch/kernel/vspace.h>
15#include <model/statedata.h>
16#include <kernel/thread.h>
17
18#ifdef CONFIG_PRINTING
19
20static inline void debug_printKernelEntryReason(void)
21{
22    printf("\nKernel entry via ");
23    switch (ksKernelEntry.path) {
24    case Entry_Interrupt:
25        printf("Interrupt, irq %lu\n", (unsigned long) ksKernelEntry.word);
26        break;
27    case Entry_UnknownSyscall:
28        printf("Unknown syscall, word: %lu", (unsigned long) ksKernelEntry.word);
29        break;
30    case Entry_VMFault:
31        printf("VM Fault, fault type: %lu\n", (unsigned long) ksKernelEntry.word);
32        break;
33    case Entry_UserLevelFault:
34        printf("User level fault, number: %lu", (unsigned long) ksKernelEntry.word);
35        break;
36#ifdef CONFIG_HARDWARE_DEBUG_API
37    case Entry_DebugFault:
38        printf("Debug fault. Fault Vaddr: 0x%lx", (unsigned long) ksKernelEntry.word);
39        break;
40#endif
41    case Entry_Syscall:
42        printf("Syscall, number: %ld, %s\n", (long) ksKernelEntry.syscall_no, syscall_names[ksKernelEntry.syscall_no]);
43        if (ksKernelEntry.syscall_no == -SysSend ||
44            ksKernelEntry.syscall_no == -SysNBSend ||
45            ksKernelEntry.syscall_no == -SysCall) {
46
47            printf("Cap type: %lu, Invocation tag: %lu\n", (unsigned long) ksKernelEntry.cap_type,
48                   (unsigned long) ksKernelEntry.invocation_tag);
49        }
50        break;
51#ifdef CONFIG_ARCH_ARM
52    case Entry_VCPUFault:
53        printf("VCPUFault\n");
54        break;
55#endif
56#ifdef CONFIG_ARCH_x86
57    case Entry_VMExit:
58        printf("VMExit\n");
59        break;
60#endif
61    default:
62        printf("Unknown\n");
63        break;
64
65    }
66}
67
68/* Prints the user context and stack trace of the current thread */
69static inline void debug_printUserState(void)
70{
71    tcb_t *tptr = NODE_STATE(ksCurThread);
72    printf("Current thread: %s\n", TCB_PTR_DEBUG_PTR(tptr)->tcbName);
73    printf("Next instruction adress: %lx\n", getRestartPC(tptr));
74    printf("Stack:\n");
75    Arch_userStackTrace(tptr);
76}
77
78static inline void debug_printTCB(tcb_t *tcb)
79{
80    printf("%40s\t", TCB_PTR_DEBUG_PTR(tcb)->tcbName);
81    char *state;
82    switch (thread_state_get_tsType(tcb->tcbState)) {
83    case ThreadState_Inactive:
84        state = "inactive";
85        break;
86    case ThreadState_Running:
87        state = "running";
88        break;
89    case ThreadState_Restart:
90        state = "restart";
91        break;
92    case ThreadState_BlockedOnReceive:
93        state = "blocked on recv";
94        break;
95    case ThreadState_BlockedOnSend:
96        state = "blocked on send";
97        break;
98    case ThreadState_BlockedOnReply:
99        state = "blocked on reply";
100        break;
101    case ThreadState_BlockedOnNotification:
102        state = "blocked on ntfn";
103        break;
104#ifdef CONFIG_VTX
105    case ThreadState_RunningVM:
106        state = "running VM";
107        break;
108#endif
109    case ThreadState_IdleThreadState:
110        state = "idle";
111        break;
112    default:
113        fail("Unknown thread state");
114    }
115
116    word_t core = SMP_TERNARY(tcb->tcbAffinity, 0);
117    printf("%15s\t%p\t%20lu\t%lu", state, (void *) getRestartPC(tcb), tcb->tcbPriority, core);
118#ifdef CONFIG_KERNEL_MCS
119    printf("\t%lu", (word_t) thread_state_get_tcbInReleaseQueue(tcb->tcbState));
120#endif
121    printf("\n");
122}
123
124static inline void debug_dumpScheduler(void)
125{
126    printf("Dumping all tcbs!\n");
127    printf("Name                                    \tState          \tIP                  \t Prio \t Core%s\n",
128           config_set(CONFIG_KERNEL_MCS) ?  "\t InReleaseQueue" : "");
129    printf("--------------------------------------------------------------------------------------\n");
130    for (tcb_t *curr = NODE_STATE(ksDebugTCBs); curr != NULL; curr = TCB_PTR_DEBUG_PTR(curr)->tcbDebugNext) {
131        debug_printTCB(curr);
132    }
133}
134#endif /* CONFIG_PRINTING */
135#endif /* CONFIG_DEBUG_BUILD */
136
137