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

Add utilities for setting and dumping log buffer #25

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
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
11 changes: 10 additions & 1 deletion libsel4debug/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -72,4 +72,13 @@ target_include_directories(
sel4debug
PUBLIC include "arch_include/${KernelArch}" sel4_arch_include/${KernelSel4Arch}
)
target_link_libraries(sel4debug PUBLIC muslc sel4 utils PRIVATE sel4debug_Config sel4_autoconf)
target_link_libraries(
sel4debug
PUBLIC
muslc
sel4
utils
sel4vka
sel4vspace
PRIVATE sel4debug_Config sel4_autoconf
)
100 changes: 100 additions & 0 deletions libsel4debug/include/sel4debug/logbuffer.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
/*
* Copyright 2020, Data61
* Commonwealth Scientific and Industrial Research Organisation (CSIRO)
* ABN 41 687 119 230.
*
* This software may be distributed and modified according to the terms of
* the BSD 2-Clause license. Note that NO WARRANTY is provided.
* See "LICENSE_BSD2.txt" for details.
*
* @TAG(DATA61_BSD)
*/

#pragma once

/* Utilities for working with the debug log buffer */

#include <autoconf.h>
#include <sel4/sel4.h>
#include <sel4/log.h>
#include <sel4/syscalls.h>
#include <utils/base64.h>
#include <vka/object.h>
#include <vspace/vspace.h>

/*
* Allocates and maps a new kernel log buffer.
*
* The large frame used for the kernel log buffer is placed in the frame
* argument and can be mapped into other address spaces.
*/
static int debug_log_buffer_init(vka_t *vka, vspace_t *vspace, vka_object_t *frame, seL4_LogBuffer *buffer)
{
#ifdef CONFIG_KERNEL_DEBUG_LOG_BUFFER
int err;
void *volatile vaddr;

err = vka_alloc_frame(vka, seL4_LogBufferBits, frame);
if (err != 0) {
return err;
}

err = seL4_BenchmarkSetLogBuffer(frame->cptr);
if (err != 0) {
ZF_LOGE("Failed to set debug log buffer frame using cap %lu.\n", frame->cptr);
return err;
}

vaddr = vspace_map_pages(vspace, &frame->cptr, NULL, seL4_AllRights, 1, seL4_LogBufferBits, 1);
if (vaddr == NULL) {
ZF_LOGE("Failed to map log buffer into VMM addrspace.\n");
return -1;
}

*buffer = seL4_LogBuffer_new(vaddr);

ZF_LOGD("Log buffer (cptr %lu) mapped to vaddr %p.\n", frame->cptr, vaddr);

return seL4_NoError;
#else
*buffer = seL4_LogBuffer_new(NULL);
return seL4_NoError;
#endif
}

/*
* Reset the debug log buffer.
*
* All new events will be placed at the start of the buffer.
*/
static int debug_log_buffer_reset(seL4_LogBuffer *buffer)
{
seL4_LogBuffer_reset(buffer);
#ifdef CONFIG_KERNEL_DEBUG_LOG_BUFFER
return seL4_BenchmarkResetLog();
#else
return seL4_NoError;
#endif
}

/*
* Finalise the debug log buffer.
*
* All new events will be placed at the start of the buffer.
*/
static void debug_log_buffer_finalise(seL4_LogBuffer *buffer)
{
#ifdef CONFIG_KERNEL_DEBUG_LOG_BUFFER
seL4_LogBuffer_setSize(buffer, seL4_BenchmarkFinalizeLog());
#else
seL4_LogBuffer_reset(buffer);
#endif
}

/*
* Dump the debug log to the given output.
*
* This will also finalise the kernel log buffer, stopping subsequent
* output.
*/
int debug_log_buffer_dump_cbor64(seL4_LogBuffer *buffer, base64_t *streamer);
121 changes: 121 additions & 0 deletions libsel4debug/src/logbuffer.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
/*
* Copyright 2020, Data61
* Commonwealth Scientific and Industrial Research Organisation (CSIRO)
* ABN 41 687 119 230.
*
* This software may be distributed and modified according to the terms of
* the BSD 2-Clause license. Note that NO WARRANTY is provided.
* See "LICENSE_BSD2.txt" for details.
*
* @TAG(DATA61_BSD)
*/

/* Utilities for working with the debug log buffer */

#include <sel4debug/logbuffer.h>
#include <utils/base64.h>
#include <utils/cbor64.h>

/* Strings tracked and compressed in the string domain */
char *identifiers[] = {
/* Event type */
"type",
"Unknown",

/* None event */
"None",

/* Entry and exit events */
"Entry",
"Exit",
"cpu-id",
"timestamp",

/* NULL array terminator */
NULL,
};

/* Number of fields in event other than the type fields */
size_t field_count[seL4_NumLogTypeIds] = {
[seL4_Log_TypeId(None)] = 0,
[seL4_Log_TypeId(Entry)] = 2,
[seL4_Log_TypeId(Exit)] = 2,
};

/*
* Dump a single event as JSON
*/
static int event_cbor64(seL4_LogEvent *event, cbor64_domain_t *domain, base64_t *streamer)
{
int event_type = seL4_LogEvent_type(event);

/* Display the type */
cbor64_map_length(streamer, field_count[event_type] + 1);
cbor64_utf8_ref(streamer, domain, "type");

switch (event_type) {
case seL4_Log_TypeId(None): {
cbor64_utf8_ref(streamer, domain, "None");
break;
}

case seL4_Log_TypeId(Entry): {
seL4_Log_Type(Entry) *entry = seL4_Log_Cast(Entry)event;
cbor64_utf8_ref(streamer, domain, "Entry");

cbor64_utf8_ref(streamer, domain, "cpu-id");
cbor64_uint(streamer, event->data);

cbor64_utf8_ref(streamer, domain, "timestamp");
cbor64_uint(streamer, entry->timestamp);
break;
}

case seL4_Log_TypeId(Exit): {
seL4_Log_Type(Exit) *exit = seL4_Log_Cast(Exit)event;
cbor64_utf8_ref(streamer, domain, "Exit");

cbor64_utf8_ref(streamer, domain, "cpu-id");
cbor64_uint(streamer, event->data);

cbor64_utf8_ref(streamer, domain, "timestamp");
cbor64_uint(streamer, exit->timestamp);
break;
}

default: {
cbor64_utf8_ref(streamer, domain, "Unknown");
break;
}
}

return 0;
}

/*
* Dump the debug log to the given output
*/
int debug_log_buffer_dump_cbor64(seL4_LogBuffer *buffer, base64_t *streamer)
{
/* Start a new string domain */
cbor64_domain_t domain;
cbor64_string_ref_domain(streamer, identifiers, &domain);

/* Stop logging events */
debug_log_buffer_finalise(buffer);

/* Create a copy of the log buffer to traverse the events */
seL4_LogBuffer cursor = *buffer;

cbor64_array_start(streamer);
seL4_LogEvent *event = seL4_LogBuffer_next(&cursor);
while (event != NULL) {
int err = event_cbor64(event, &domain, streamer);
if (err != 0) {
return err;
}

event = seL4_LogBuffer_next(&cursor);
}
return cbor64_array_end(streamer);
}