Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[patch-axel-16b] improve debug #152

Draft
wants to merge 25 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
5a864c4
add isValidFaultHandlerEp()
axel-h Jul 12, 2024
a415d7f
improve comments
axel-h Jul 26, 2024
8c5a193
cleanup sendFaultIPC(), improve comments
axel-h Jul 24, 2024
f480d4d
factor out debug functions
axel-h Jul 25, 2024
ab40360
set tcbFault and tcbLookupFailure unconditionally
axel-h Jul 25, 2024
4c89b3d
inline functions into handleFault()
axel-h Jul 25, 2024
a17dbda
make sendFaultIPC() private
axel-h Jul 24, 2024
f56164d
tryRaisingTimeoutFault()
axel-h Jul 24, 2024
0c99a80
remove superfluous brackets
axel-h Jul 12, 2024
17f856a
debug: improve print_fault_handler()
axel-h Dec 14, 2021
03f2508
include headers
axel-h Jul 12, 2024
c50ddad
move pragma
axel-h Jul 22, 2024
11632b3
create debug.c and move debug code there
axel-h Jul 26, 2024
63d3ebe
cleanup code in doReplyTransfer()
axel-h Dec 1, 2023
69fa527
make Arch_userStackTrace() interface generic
axel-h Jan 9, 2022
27a5443
reduce global fault variable usage
axel-h Nov 10, 2023
93b0e13
beautify debug_printKernelEntryReason()
axel-h Nov 25, 2021
c74218f
debug: improve debug_dumpScheduler()
axel-h Nov 25, 2021
fcc5550
WIP debug: make stack dump more generic
axel-h Nov 25, 2021
eae594b
even more improved message printed on fault
axel-h Mar 8, 2022
42a6de6
comment end of conditional code block
axel-h Jan 9, 2022
495313f
add cap type helper functions
axel-h Nov 9, 2023
a229ece
Add syscall SysDebugCapPaddr
astevins Feb 18, 2024
052421a
Add syscall SysDebugCapIsLastCopy
astevins Jun 6, 2024
0e49855
Print output on page fault
astevins Apr 6, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
127 changes: 9 additions & 118 deletions include/api/debug.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,133 +4,24 @@
* SPDX-License-Identifier: GPL-2.0-only
*/

#include <config.h>

#ifdef CONFIG_DEBUG_BUILD
#pragma once

#include <benchmark/benchmark_track.h>
#include <arch/api/syscall.h>
#include <arch/kernel/vspace.h>
#include <model/statedata.h>
#include <kernel/thread.h>
#include <config.h>

#ifdef CONFIG_PRINTING

static inline void debug_printKernelEntryReason(void)
{
printf("\nKernel entry via ");
switch (ksKernelEntry.path) {
case Entry_Interrupt:
printf("Interrupt, irq %lu\n", (unsigned long) ksKernelEntry.word);
break;
case Entry_UnknownSyscall:
printf("Unknown syscall, word: %lu", (unsigned long) ksKernelEntry.word);
break;
case Entry_VMFault:
printf("VM Fault, fault type: %lu\n", (unsigned long) ksKernelEntry.word);
break;
case Entry_UserLevelFault:
printf("User level fault, number: %lu", (unsigned long) ksKernelEntry.word);
break;
#ifdef CONFIG_HARDWARE_DEBUG_API
case Entry_DebugFault:
printf("Debug fault. Fault Vaddr: 0x%lx", (unsigned long) ksKernelEntry.word);
break;
#endif
case Entry_Syscall:
printf("Syscall, number: %ld, %s\n", (long) ksKernelEntry.syscall_no, syscall_names[ksKernelEntry.syscall_no]);
if (ksKernelEntry.syscall_no == -SysSend ||
ksKernelEntry.syscall_no == -SysNBSend ||
ksKernelEntry.syscall_no == -SysCall) {
#include <types.h>

printf("Cap type: %lu, Invocation tag: %lu\n", (unsigned long) ksKernelEntry.cap_type,
(unsigned long) ksKernelEntry.invocation_tag);
}
break;
#ifdef CONFIG_ARCH_ARM
case Entry_VCPUFault:
printf("VCPUFault\n");
break;
#endif
#ifdef CONFIG_ARCH_x86
case Entry_VMExit:
printf("VMExit\n");
break;
#endif
default:
printf("Unknown (%u)\n", ksKernelEntry.path);
break;
void print_thread_fault(tcb_t *tptr);

}
}
#ifdef CONFIG_DEBUG_BUILD

void debug_printKernelEntryReason(void);
/* Prints the user context and stack trace of the current thread */
static inline void debug_printUserState(void)
{
tcb_t *tptr = NODE_STATE(ksCurThread);
printf("Current thread: %s\n", TCB_PTR_DEBUG_PTR(tptr)->tcbName);
printf("Next instruction adress: %lx\n", getRestartPC(tptr));
printf("Stack:\n");
Arch_userStackTrace(tptr);
}
void debug_printUserState(void);
void debug_printTCB(tcb_t *tcb);
void debug_dumpScheduler(void);

static inline void debug_printTCB(tcb_t *tcb)
{
printf("%40s\t", TCB_PTR_DEBUG_PTR(tcb)->tcbName);
char *state;
switch (thread_state_get_tsType(tcb->tcbState)) {
case ThreadState_Inactive:
state = "inactive";
break;
case ThreadState_Running:
state = "running";
break;
case ThreadState_Restart:
state = "restart";
break;
case ThreadState_BlockedOnReceive:
state = "blocked on recv";
break;
case ThreadState_BlockedOnSend:
state = "blocked on send";
break;
case ThreadState_BlockedOnReply:
state = "blocked on reply";
break;
case ThreadState_BlockedOnNotification:
state = "blocked on ntfn";
break;
#ifdef CONFIG_VTX
case ThreadState_RunningVM:
state = "running VM";
break;
#endif
case ThreadState_IdleThreadState:
state = "idle";
break;
default:
fail("Unknown thread state");
}

word_t core = SMP_TERNARY(tcb->tcbAffinity, 0);
printf("%15s\t%p\t%20lu\t%lu", state, (void *) getRestartPC(tcb), tcb->tcbPriority, core);
#ifdef CONFIG_KERNEL_MCS
printf("\t%lu", (word_t) thread_state_get_tcbInReleaseQueue(tcb->tcbState));
#endif
printf("\n");
}

static inline void debug_dumpScheduler(void)
{
printf("Dumping all tcbs!\n");
printf("Name \tState \tIP \t Prio \t Core%s\n",
config_set(CONFIG_KERNEL_MCS) ? "\t InReleaseQueue" : "");
printf("--------------------------------------------------------------------------------------\n");
for (tcb_t *curr = NODE_STATE(ksDebugTCBs); curr != NULL; curr = TCB_PTR_DEBUG_PTR(curr)->tcbDebugNext) {
debug_printTCB(curr);
}
}
#endif /* CONFIG_PRINTING */
#endif /* CONFIG_DEBUG_BUILD */

#endif /* CONFIG_PRINTING */
8 changes: 8 additions & 0 deletions include/arch/arm/arch/32/mode/machine/registerset.h
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,14 @@ enum _register {
n_contextRegisters = 20,
};

#if defined(CONFIG_PRINTING) && defined(CONFIG_DEBUG_BUILD)
static UNUSED const char *register_names[] = {
"r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11",
"r12", "r13/sp", "r14/lr", "NextIP", "cpsr", "FaultIP", "tpidrurw/tls",
"tpidruro",
};
#endif /* defined(CONFIG_PRINTING) && defined(CONFIG_DEBUG_BUILD) */

#define NEXT_PC_REG NextIP

compile_assert(sp_offset_correct, SP *sizeof(word_t) == PT_SP)
Expand Down
9 changes: 9 additions & 0 deletions include/arch/arm/arch/64/mode/machine/registerset.h
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,15 @@ compile_assert(sp_offset_correct, SP_EL0 *sizeof(word_t) == PT_SP_EL0)
compile_assert(lr_svc_offset_correct, ELR_EL1 *sizeof(word_t) == PT_ELR_EL1)
compile_assert(faultinstruction_offset_correct, FaultIP *sizeof(word_t) == PT_FaultIP)

#if defined(CONFIG_PRINTING) && defined(CONFIG_DEBUG_BUILD)
static UNUSED const char *register_names[] = {
"x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11",
"x12", "x13", "x14", "x15", "x16", "x17", "x18", "x19", "x20", "x21", "x22",
"x23", "x24", "x25", "x26", "x27", "x28", "x29", "x30/lr", "sp", "elr_e11",
"NextIP", "spsr_e11", "tpidr_el0/tls", "tpidrro_el0",
};
#endif /* defined(CONFIG_PRINTING) && defined(CONFIG_DEBUG_BUILD) */

typedef word_t register_t;

enum messageSizes {
Expand Down
5 changes: 0 additions & 5 deletions include/arch/arm/arch/kernel/vspace.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,3 @@ vm_rights_t CONST maskVMRights(vm_rights_t vm_rights,

exception_t decodeARMMMUInvocation(word_t invLabel, word_t length, cptr_t cptr,
cte_t *cte, cap_t cap, bool_t call, word_t *buffer);

#ifdef CONFIG_PRINTING
void Arch_userStackTrace(tcb_t *tptr);
#endif

5 changes: 0 additions & 5 deletions include/arch/riscv/arch/kernel/vspace.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,3 @@ exception_t performPageInvocationMapPTE(cap_t cap, cte_t *ctSlot,
pte_t pte, pte_t *base);
exception_t performPageInvocationUnmap(cap_t cap, cte_t *ctSlot);
void setVMRoot(tcb_t *tcb);

#ifdef CONFIG_PRINTING
void Arch_userStackTrace(tcb_t *tptr);
#endif

10 changes: 10 additions & 0 deletions include/arch/riscv/arch/machine/registerset.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,16 @@ enum _register {
n_contextRegisters
};

#if defined(CONFIG_PRINTING) && defined(CONFIG_DEBUG_BUILD)
static UNUSED const char *register_names[] = {
"x1/ra", "x2/sp", "x3/gp", "x4/tp", "x5/t0", "x6/t1", "x7/t2", "x8/s0",
"x9/s1", "x10/a0", "x11/a1", "x12/a2", "x13/a3", "x14/a4", "x15/a5",
"x16/a6", "x17/a7", "x18/s2", "x19/s3", "x20/s4", "x21/s5", "x22/s6",
"x23/s7", "x24/s8", "x25/s9", "x26/s10", "x27/s11", "x28/t3", "x29/t4",
"x30/t5", "x31/t6", "scause", "sstatus", "FaultIP", "NextIP",
};
#endif /* defined(CONFIG_PRINTING) && defined(CONFIG_DEBUG_BUILD) */

typedef uint8_t register_t;

enum messageSizes {
Expand Down
2 changes: 2 additions & 0 deletions include/arch/riscv/arch/object/structures.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ typedef word_t vm_rights_t;

typedef pte_t vspace_root_t;

#define VSPACE_PTR(r) ((vspace_root_t *)(r))

/* Generic fastpath.c code expects pde_t for stored_hw_asid
* that's a workaround in the time being.
*/
Expand Down
8 changes: 8 additions & 0 deletions include/arch/x86/arch/32/mode/machine/registerset.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,14 @@ enum _register {
/* 0x44 */ n_contextRegisters = 17
};

#if defined(CONFIG_PRINTING) && defined(CONFIG_DEBUG_BUILD)
static UNUSED const char *register_names[] = {
"(none)", /* enum _register starts with 1 */
"eax", "ebx", "ecx", "edx", "esi", "edi", "ebp", "FaultIP", "Error",
"NextIP", "cs", "flags", "esp", "ss", "fs base", "gs/tls base",
};
#endif /* defined(CONFIG_PRINTING) && defined(CONFIG_DEBUG_BUILD) */

typedef word_t register_t;

enum messageSizes {
Expand Down
8 changes: 8 additions & 0 deletions include/arch/x86/arch/64/mode/machine/registerset.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,14 @@ enum _register {
n_contextRegisters = 24 /* 0xc0 */
};

#if defined(CONFIG_PRINTING) && defined(CONFIG_DEBUG_BUILD)
static UNUSED const char *register_names[] = {
"rdi", "rsi", "rax", "rbx", "rbp", "r12", "r13", "r14", "rdx", "r10", "r8",
"r9", "r15", "FLAGS", "NextIP", "Error", "rsp", "FaultIP", "r11", "rcx",
"cs", "ss", "fs/tls base", "gs base",
};
#endif /* defined(CONFIG_PRINTING) && defined(CONFIG_DEBUG_BUILD) */

typedef uint32_t register_t;

enum messageSizes {
Expand Down
5 changes: 0 additions & 5 deletions include/arch/x86/arch/kernel/vspace.h
Original file line number Diff line number Diff line change
Expand Up @@ -125,12 +125,7 @@ pde_t CONST makeUserPDEPageTable(paddr_t paddr, vm_attributes_t vm_attr);
pde_t CONST makeUserPDEInvalid(void);


#ifdef CONFIG_PRINTING
void Arch_userStackTrace(tcb_t *tptr);
#endif

static inline bool_t checkVPAlignment(vm_page_size_t sz, word_t w)
{
return IS_ALIGNED(w, pageBitsForSize(sz));
}

25 changes: 17 additions & 8 deletions include/kernel/faulthandler.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,29 @@

#pragma once

#include <config.h>
#include <types.h>
#include <object.h>

/* ToDo: seems there is no dedicated value */
#define NO_LOOKUP_FAULT lookup_fault_missing_capability_new(0)

static bool_t isValidFaultHandlerEp(cap_t cap)
{
return ((cap_get_capType(cap) == cap_endpoint_cap) &&
cap_endpoint_cap_get_capCanSend(cap) &&
(cap_endpoint_cap_get_capCanGrant(cap) ||
cap_endpoint_cap_get_capCanGrantReply(cap)));
}

#ifdef CONFIG_KERNEL_MCS
static inline bool_t validTimeoutHandler(tcb_t *tptr)

static bool_t isValidFaultHandlerEpOrNull(cap_t cap)
{
return cap_get_capType(TCB_PTR_CTE_PTR(tptr, tcbTimeoutHandler)->cap) == cap_endpoint_cap;
return ((cap_get_capType(cap) == cap_null_cap) || isValidFaultHandlerEp(cap));
}

void handleTimeout(tcb_t *tptr);
void handleNoFaultHandler(tcb_t *tptr);
bool_t sendFaultIPC(tcb_t *tptr, cap_t handlerCap, bool_t can_donate);
#else
exception_t sendFaultIPC(tcb_t *tptr);
void handleDoubleFault(tcb_t *tptr, seL4_Fault_t ex1);
bool_t tryRaisingTimeoutFault(tcb_t *tptr, word_t scBadge);
#endif
void handleFault(tcb_t *tptr);

42 changes: 42 additions & 0 deletions include/kernel/vspace.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,45 @@
exception_t benchmark_arch_map_logBuffer(word_t frame_cptr);
#endif /* CONFIG_KERNEL_LOG_BUFFER */

#ifdef CONFIG_PRINTING

/* The function readWordFromVSpace() is used for stack dumps, thus it exists
* only if CONFIG_PRINTING is set, regardless of CONFIG_DEBUG.
*/

typedef enum {
VSPACE_ACCESS_SUCCESSFUL = 0,
VSPACE_INVALID_ROOT = 1,
VSPACE_LOOKUP_FAILED = 2,
VSPACE_INVALID_ALIGNMENT = 3,
VSPACE_INVALID_PTE = 4
} vspaceAccessResult_t;

typedef struct readWordFromVSpace_ret {
vspaceAccessResult_t status;
word_t value;
word_t paddr;
} readWordFromVSpace_ret_t;


/* Obviously, vaddr must be word-aligned for this to work. */
readWordFromVSpace_ret_t Arch_readWordFromVSpace(vspace_root_t *vspace,
word_t vaddr);

typedef struct readWordFromStack_ret {
vspaceAccessResult_t status;
word_t value;
/* All architectures supported so far have the stack in the vspace. */
vspace_root_t *vspace_root;
word_t vaddr;
word_t paddr;
} readWordFromStack_ret_t;

/* It is architecture dependent what a thread stack is actually, and how to read
* a word from it. The common mode is that there is a stack pointer that points
* somewhere into the thread's vspace. It is least word aligned, so accessing
* the stack falls down to calling Arch_readWordFromVSpace() then.
*/
readWordFromStack_ret_t Arch_readWordFromThreadStack(tcb_t *tptr, word_t i);

#endif /* CONFIG_PRINTING */
27 changes: 26 additions & 1 deletion include/object/objecttype.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,34 @@ exception_t performInvocation_Reply(tcb_t *thread, cte_t *slot, bool_t canGrant)
#endif
word_t getObjectSize(word_t t, word_t userObjSize);

static inline bool_t is_cap_null(cap_t cap)
{
return (cap_get_capType(cap) == cap_null_cap);
}

static inline bool_t is_cap_endpoint(cap_t cap)
{
return (cap_get_capType(cap) == cap_endpoint_cap);
}

static inline bool_t is_cap_irq_handler(cap_t cap)
{
return (cap_get_capType(cap) == cap_irq_handler_cap);
}

static inline bool_t is_cap_frame(cap_t cap)
{
return (cap_get_capType(cap) == cap_frame_cap);
}

static inline bool_t is_cap_page_table(cap_t cap)
{
return (cap_get_capType(cap) == cap_page_table_cap);
}

static inline void postCapDeletion(cap_t cap)
{
if (cap_get_capType(cap) == cap_irq_handler_cap) {
if (is_cap_irq_handler(cap)) {
irq_t irq = IDX_TO_IRQT(cap_irq_handler_cap_get_capIRQ(cap));
deletedIRQHandler(irq);
} else if (isArchCap(cap)) {
Expand Down
5 changes: 5 additions & 0 deletions include/stdint.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,8 @@ typedef int64_t intmax_t;
#define PRIi64 "lli"
#define PRIu64 "llu"
#define PRIx64 "llx"

#define PRId32 "d"
#define PRIi32 "i"
#define PRIu32 "u"
#define PRIx32 "x"
Loading
Loading