forked from Imagelibrary/seL4
Enabled IPC debug features under new config
Introduced a new config flag to enable userError format strings to be written to the IPC buffer. Another config bool has been introduced to toggle printing the error out and this can also be set at runtime. Signed-off-by: Saer Debel <saer.debel@data61.csiro.au>
This commit is contained in:
@@ -330,6 +330,15 @@ config_option(
|
|||||||
DEPENDS "NOT KernelVerificationBuild"
|
DEPENDS "NOT KernelVerificationBuild"
|
||||||
DEFAULT_DISABLED OFF
|
DEFAULT_DISABLED OFF
|
||||||
)
|
)
|
||||||
|
|
||||||
|
config_option(
|
||||||
|
KernelInvocationReportErrorIPC KERNEL_INVOCATION_REPORT_ERROR_IPC
|
||||||
|
"Allows the kernel to write the userError to the IPC buffer"
|
||||||
|
DEFAULT OFF
|
||||||
|
DEPENDS "KernelPrinting"
|
||||||
|
DEFAULT_DISABLED OFF
|
||||||
|
)
|
||||||
|
|
||||||
config_choice(
|
config_choice(
|
||||||
KernelBenchmarks
|
KernelBenchmarks
|
||||||
KERNEL_BENCHMARK
|
KERNEL_BENCHMARK
|
||||||
|
|||||||
@@ -36,13 +36,15 @@ struct syscall_error {
|
|||||||
};
|
};
|
||||||
typedef struct syscall_error syscall_error_t;
|
typedef struct syscall_error syscall_error_t;
|
||||||
|
|
||||||
|
#ifdef CONFIG_KERNEL_INVOCATION_REPORT_ERROR_IPC
|
||||||
struct debug_syscall_error {
|
struct debug_syscall_error {
|
||||||
word_t errorMessage[DEBUG_MESSAGE_MAXLEN];
|
word_t errorMessage[DEBUG_MESSAGE_MAXLEN];
|
||||||
};
|
};
|
||||||
typedef struct debug_syscall_error debug_syscall_error_t;
|
typedef struct debug_syscall_error debug_syscall_error_t;
|
||||||
|
|
||||||
|
extern debug_syscall_error_t current_debug_error;
|
||||||
|
#endif
|
||||||
extern lookup_fault_t current_lookup_fault;
|
extern lookup_fault_t current_lookup_fault;
|
||||||
extern seL4_Fault_t current_fault;
|
extern seL4_Fault_t current_fault;
|
||||||
extern syscall_error_t current_syscall_error;
|
extern syscall_error_t current_syscall_error;
|
||||||
extern debug_syscall_error_t current_debug_error;
|
|
||||||
|
|
||||||
|
|||||||
@@ -110,24 +110,29 @@ static inline word_t CONST wordFromMessageInfo(seL4_MessageInfo_t mi)
|
|||||||
#define THREAD_NAME ""
|
#define THREAD_NAME ""
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef CONFIG_KERNEL_INVOCATION_REPORT_ERROR_IPC
|
||||||
extern struct debug_syscall_error current_debug_error;
|
extern struct debug_syscall_error current_debug_error;
|
||||||
|
|
||||||
|
#define out_error(...) \
|
||||||
|
snprintf((char *)current_debug_error.errorMessage, \
|
||||||
|
DEBUG_MESSAGE_MAXLEN * sizeof(word_t), __VA_ARGS__);
|
||||||
|
#else
|
||||||
|
#define out_error printf
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Print to serial a message helping userspace programmers to determine why the
|
* Print to serial a message helping userspace programmers to determine why the
|
||||||
* kernel is not performing their requested operation.
|
* kernel is not performing their requested operation.
|
||||||
*/
|
*/
|
||||||
#define userError(...) \
|
#define userError(M, ...) \
|
||||||
do { \
|
do { \
|
||||||
printf(ANSI_DARK "<<" ANSI_GREEN "seL4(CPU %lu)" ANSI_DARK \
|
out_error(ANSI_DARK "<<" ANSI_GREEN "seL4(CPU %lu)" ANSI_DARK \
|
||||||
" [%s/%d T%p \"%s\" @%lx]: ", \
|
" [%s/%d T%p \"%s\" @%lx]: " M ">>" ANSI_RESET "\n", \
|
||||||
SMP_TERNARY(getCurrentCPUIndex(), 0lu), \
|
SMP_TERNARY(getCurrentCPUIndex(), 0lu), \
|
||||||
__func__, __LINE__, NODE_STATE(ksCurThread), \
|
__func__, __LINE__, NODE_STATE(ksCurThread), \
|
||||||
THREAD_NAME, \
|
THREAD_NAME, \
|
||||||
(word_t)getRestartPC(NODE_STATE(ksCurThread))); \
|
(word_t)getRestartPC(NODE_STATE(ksCurThread)), \
|
||||||
printf(__VA_ARGS__); \
|
## __VA_ARGS__); \
|
||||||
printf(">>" ANSI_RESET "\n"); \
|
|
||||||
snprintf((char *)current_debug_error.errorMessage, \
|
|
||||||
DEBUG_MESSAGE_MAXLEN * sizeof(word_t), __VA_ARGS__); \
|
|
||||||
} while (0)
|
} while (0)
|
||||||
#else /* !CONFIG_PRINTING */
|
#else /* !CONFIG_PRINTING */
|
||||||
#define userError(...)
|
#define userError(...)
|
||||||
|
|||||||
@@ -35,6 +35,14 @@ config_option(
|
|||||||
DEFAULT OFF
|
DEFAULT OFF
|
||||||
)
|
)
|
||||||
|
|
||||||
|
config_string(
|
||||||
|
LibSel4PrintInvocationErrors LIB_SEL4_PRINT_INVOCATION_ERRORS
|
||||||
|
"Generated stubs on error will print the message contained in the IPC buffer"
|
||||||
|
DEFAULT 1
|
||||||
|
DEPENDS "KernelInvocationReportErrorIPC" DEFAULT_DISABLED 0
|
||||||
|
UNQUOTE
|
||||||
|
)
|
||||||
|
|
||||||
if(LibSel4StubsUseIPCBufferOnly)
|
if(LibSel4StubsUseIPCBufferOnly)
|
||||||
set(buffer "--buffer")
|
set(buffer "--buffer")
|
||||||
endif()
|
endif()
|
||||||
|
|||||||
@@ -584,6 +584,14 @@ LIBSEL4_INLINE_FUNC void seL4_DebugPutChar(char c)
|
|||||||
arm_sys_send_recv(seL4_SysDebugPutChar, c, &unused0, 0, &unused1, &unused2, &unused3, &unused4, &unused5, 0);
|
arm_sys_send_recv(seL4_SysDebugPutChar, c, &unused0, 0, &unused1, &unused2, &unused3, &unused4, &unused5, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LIBSEL4_INLINE_FUNC void seL4_DebugPutString(char *str)
|
||||||
|
{
|
||||||
|
for (char *s = str; *s; s++) {
|
||||||
|
seL4_DebugPutChar(*s);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
LIBSEL4_INLINE_FUNC void seL4_DebugDumpScheduler(void)
|
LIBSEL4_INLINE_FUNC void seL4_DebugDumpScheduler(void)
|
||||||
{
|
{
|
||||||
seL4_Word unused0 = 0;
|
seL4_Word unused0 = 0;
|
||||||
|
|||||||
@@ -786,6 +786,14 @@ LIBSEL4_INLINE_FUNC void seL4_DebugPutChar(char c)
|
|||||||
&unused4, &unused5, 0);
|
&unused4, &unused5, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LIBSEL4_INLINE_FUNC void seL4_DebugPutString(char *str)
|
||||||
|
{
|
||||||
|
for (char *s = str; *s; s++) {
|
||||||
|
seL4_DebugPutChar(*s);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
LIBSEL4_INLINE_FUNC void seL4_DebugDumpScheduler(void)
|
LIBSEL4_INLINE_FUNC void seL4_DebugDumpScheduler(void)
|
||||||
{
|
{
|
||||||
seL4_Word unused0 = 0;
|
seL4_Word unused0 = 0;
|
||||||
|
|||||||
@@ -97,6 +97,7 @@ static inline seL4_Word seL4_MaxExtraRefills(seL4_Word size)
|
|||||||
#endif /* !__ASSEMBLER__ */
|
#endif /* !__ASSEMBLER__ */
|
||||||
#endif /* CONFIG_KERNEL_MCS */
|
#endif /* CONFIG_KERNEL_MCS */
|
||||||
|
|
||||||
|
#ifdef CONFIG_KERNEL_INVOCATION_REPORT_ERROR_IPC
|
||||||
#define DEBUG_MESSAGE_START 6
|
#define DEBUG_MESSAGE_START 6
|
||||||
#define DEBUG_MESSAGE_MAXLEN 50
|
#define DEBUG_MESSAGE_MAXLEN 50
|
||||||
|
#endif
|
||||||
|
|||||||
@@ -13,6 +13,26 @@
|
|||||||
extern __thread seL4_IPCBuffer *__sel4_ipc_buffer;
|
extern __thread seL4_IPCBuffer *__sel4_ipc_buffer;
|
||||||
__thread __attribute__((weak)) seL4_IPCBuffer *__sel4_ipc_buffer;
|
__thread __attribute__((weak)) seL4_IPCBuffer *__sel4_ipc_buffer;
|
||||||
|
|
||||||
|
#ifdef CONFIG_KERNEL_INVOCATION_REPORT_ERROR_IPC
|
||||||
|
extern __thread char __sel4_print_error;
|
||||||
|
|
||||||
|
LIBSEL4_INLINE_FUNC char *seL4_GetDebugError(void)
|
||||||
|
{
|
||||||
|
return (char *)(__sel4_ipc_buffer->msg + DEBUG_MESSAGE_START);
|
||||||
|
}
|
||||||
|
|
||||||
|
LIBSEL4_INLINE_FUNC void seL4_SetPrintError(char print_error)
|
||||||
|
{
|
||||||
|
__sel4_print_error = print_error;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
LIBSEL4_INLINE_FUNC char seL4_CanPrintError(void)
|
||||||
|
{
|
||||||
|
return __sel4_print_error;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
LIBSEL4_INLINE_FUNC void seL4_SetIPCBuffer(seL4_IPCBuffer *ipc_buffer)
|
LIBSEL4_INLINE_FUNC void seL4_SetIPCBuffer(seL4_IPCBuffer *ipc_buffer)
|
||||||
{
|
{
|
||||||
__sel4_ipc_buffer = ipc_buffer;
|
__sel4_ipc_buffer = ipc_buffer;
|
||||||
|
|||||||
@@ -815,6 +815,15 @@ LIBSEL4_INLINE_FUNC void seL4_DebugPutChar(char c)
|
|||||||
x86_sys_send_recv(seL4_SysDebugPutChar, c, &unused0, 0, &unused1, &unused2, MCS_COND(0, &unused3));
|
x86_sys_send_recv(seL4_SysDebugPutChar, c, &unused0, 0, &unused1, &unused2, MCS_COND(0, &unused3));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LIBSEL4_INLINE_FUNC void seL4_DebugPutString(char *str)
|
||||||
|
{
|
||||||
|
for (char *s = str; *s; s++) {
|
||||||
|
seL4_DebugPutChar(*s);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
LIBSEL4_INLINE_FUNC void seL4_DebugDumpScheduler(void)
|
LIBSEL4_INLINE_FUNC void seL4_DebugDumpScheduler(void)
|
||||||
{
|
{
|
||||||
seL4_Word unused0 = 0;
|
seL4_Word unused0 = 0;
|
||||||
|
|||||||
@@ -588,6 +588,14 @@ LIBSEL4_INLINE_FUNC void seL4_DebugPutChar(char c)
|
|||||||
x64_sys_send_recv(seL4_SysDebugPutChar, c, &unused0, 0, &unused1, &unused2, &unused3, &unused4, &unused5, 0);
|
x64_sys_send_recv(seL4_SysDebugPutChar, c, &unused0, 0, &unused1, &unused2, &unused3, &unused4, &unused5, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LIBSEL4_INLINE_FUNC void seL4_DebugPutString(char *str)
|
||||||
|
{
|
||||||
|
for (char *s = str; *s; s++) {
|
||||||
|
seL4_DebugPutChar(*s);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
LIBSEL4_INLINE_FUNC void seL4_DebugDumpScheduler(void)
|
LIBSEL4_INLINE_FUNC void seL4_DebugDumpScheduler(void)
|
||||||
{
|
{
|
||||||
seL4_Word unused0 = 0;
|
seL4_Word unused0 = 0;
|
||||||
|
|||||||
@@ -6,6 +6,10 @@
|
|||||||
|
|
||||||
#include <sel4/sel4.h>
|
#include <sel4/sel4.h>
|
||||||
|
|
||||||
|
#ifdef CONFIG_KERNEL_INVOCATION_REPORT_ERROR_IPC
|
||||||
|
__thread char __sel4_print_error = CONFIG_LIB_SEL4_PRINT_INVOCATION_ERRORS;
|
||||||
|
#endif
|
||||||
|
|
||||||
/** Userland per-thread IPC buffer address **/
|
/** Userland per-thread IPC buffer address **/
|
||||||
__thread seL4_IPCBuffer *__sel4_ipc_buffer;
|
__thread seL4_IPCBuffer *__sel4_ipc_buffer;
|
||||||
|
|
||||||
|
|||||||
@@ -715,6 +715,11 @@ def generate_stub(arch, wordsize, interface_name, method_name, method_id, input_
|
|||||||
result.append("\tif (%s != seL4_NoError) {" % label)
|
result.append("\tif (%s != seL4_NoError) {" % label)
|
||||||
for i in range(num_mrs):
|
for i in range(num_mrs):
|
||||||
result.append("\t\tseL4_SetMR(%d, mr%d);" % (i, i))
|
result.append("\t\tseL4_SetMR(%d, mr%d);" % (i, i))
|
||||||
|
result.append("#ifdef CONFIG_KERNEL_INVOCATION_REPORT_ERROR_IPC")
|
||||||
|
result.append("\t\tif (seL4_CanPrintError()) {")
|
||||||
|
result.append("\t\t\tseL4_DebugPutString(seL4_GetDebugError());")
|
||||||
|
result.append("\t\t}")
|
||||||
|
result.append("#endif")
|
||||||
if returning_struct:
|
if returning_struct:
|
||||||
result.append("\t\treturn result;")
|
result.append("\t\treturn result;")
|
||||||
result.append("\t}")
|
result.append("\t}")
|
||||||
|
|||||||
@@ -10,4 +10,7 @@
|
|||||||
lookup_fault_t current_lookup_fault;
|
lookup_fault_t current_lookup_fault;
|
||||||
seL4_Fault_t current_fault;
|
seL4_Fault_t current_fault;
|
||||||
syscall_error_t current_syscall_error;
|
syscall_error_t current_syscall_error;
|
||||||
|
#ifdef CONFIG_KERNEL_INVOCATION_REPORT_ERROR_IPC
|
||||||
debug_syscall_error_t current_debug_error;
|
debug_syscall_error_t current_debug_error;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|||||||
@@ -262,11 +262,13 @@ void replyFromKernel_error(tcb_t *thread)
|
|||||||
setRegister(thread, badgeRegister, 0);
|
setRegister(thread, badgeRegister, 0);
|
||||||
len = setMRs_syscall_error(thread, ipcBuffer);
|
len = setMRs_syscall_error(thread, ipcBuffer);
|
||||||
|
|
||||||
|
#ifdef CONFIG_KERNEL_INVOCATION_REPORT_ERROR_IPC
|
||||||
char *debugBuffer = (char *)(ipcBuffer + DEBUG_MESSAGE_START + 1);
|
char *debugBuffer = (char *)(ipcBuffer + DEBUG_MESSAGE_START + 1);
|
||||||
word_t add = strlcpy(debugBuffer, (char *)current_debug_error.errorMessage,
|
word_t add = strlcpy(debugBuffer, (char *)current_debug_error.errorMessage,
|
||||||
DEBUG_MESSAGE_MAXLEN * sizeof(word_t));
|
DEBUG_MESSAGE_MAXLEN * sizeof(word_t));
|
||||||
|
|
||||||
len += (add / sizeof(word_t)) + 1;
|
len += (add / sizeof(word_t)) + 1;
|
||||||
|
#endif
|
||||||
|
|
||||||
setRegister(thread, msgInfoRegister, wordFromMessageInfo(
|
setRegister(thread, msgInfoRegister, wordFromMessageInfo(
|
||||||
seL4_MessageInfo_new(current_syscall_error.type, 0, 0, len)));
|
seL4_MessageInfo_new(current_syscall_error.type, 0, 0, len)));
|
||||||
|
|||||||
Reference in New Issue
Block a user