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