kernel: implement support for magenta_debug over serial
This commit is contained in:
+165
@@ -0,0 +1,165 @@
|
||||
#include "kernel/panic.h"
|
||||
|
||||
#include <kernel/debug.h>
|
||||
#include <kernel/libc/stdio.h>
|
||||
#include <kernel/machine/cpu.h>
|
||||
#include <kernel/machine/debug.h>
|
||||
#include <kernel/printk.h>
|
||||
#include <kernel/sched.h>
|
||||
#include <kernel/task.h>
|
||||
#include <kernel/thread.h>
|
||||
#include <magenta/debug/host.h>
|
||||
#include <magenta/debug/packet.h>
|
||||
|
||||
static volatile bool initial_continue = false;
|
||||
static volatile bool debug_enabled = false;
|
||||
|
||||
static spin_lock_t debug_io_lock = SPIN_LOCK_INIT;
|
||||
|
||||
static enum mxdbg_status read_remote(
|
||||
struct mxdbg_host *host,
|
||||
void *buf,
|
||||
size_t count,
|
||||
size_t *nr_read)
|
||||
{
|
||||
debug_read(buf, count, nr_read);
|
||||
return MXDBG_SUCCESS;
|
||||
}
|
||||
|
||||
static enum mxdbg_status write_remote(
|
||||
struct mxdbg_host *host,
|
||||
const void *buf,
|
||||
size_t count,
|
||||
size_t *nr_written)
|
||||
{
|
||||
spin_lock(&debug_io_lock);
|
||||
debug_write(buf, count, nr_written);
|
||||
spin_unlock(&debug_io_lock);
|
||||
return MXDBG_SUCCESS;
|
||||
}
|
||||
|
||||
static enum mxdbg_status identify(
|
||||
struct mxdbg_host *host,
|
||||
enum mxdbg_identity_key key,
|
||||
void *out,
|
||||
size_t max)
|
||||
{
|
||||
switch (key) {
|
||||
case MXDBG_IDENTITY_KERNEL_NAME:
|
||||
snprintf(out, max, "%s", KERNEL_NAME);
|
||||
break;
|
||||
case MXDBG_IDENTITY_KERNEL_VERSION:
|
||||
snprintf(out, max, "%s", KERNEL_VERSION);
|
||||
break;
|
||||
case MXDBG_IDENTITY_KERNEL_ARCH:
|
||||
snprintf(out, max, "%s", KERNEL_ARCH);
|
||||
break;
|
||||
default:
|
||||
return MXDBG_ERR_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
return MXDBG_SUCCESS;
|
||||
}
|
||||
|
||||
static enum mxdbg_status identify_task(
|
||||
struct mxdbg_host *host,
|
||||
tid_t tid,
|
||||
enum mxdbg_identity_key key,
|
||||
void *out,
|
||||
size_t max)
|
||||
{
|
||||
struct task *task = task_from_tid(tid);
|
||||
if (!task) {
|
||||
return MXDBG_ERR_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
switch (key) {
|
||||
case MXDBG_IDENTITY_TASK_NAME:
|
||||
snprintf(out, max, "%s", task->t_name);
|
||||
break;
|
||||
case MXDBG_IDENTITY_TASK_PARENT:
|
||||
*(uint16_t *)out = task->t_parent ? task->t_parent->t_id : -1;
|
||||
break;
|
||||
case MXDBG_IDENTITY_TASK_NR_THREADS:
|
||||
*(uint16_t *)out = queue_length(&task->t_threads);
|
||||
break;
|
||||
default:
|
||||
return MXDBG_ERR_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
return MXDBG_SUCCESS;
|
||||
}
|
||||
|
||||
static enum mxdbg_status resume(struct mxdbg_host *host)
|
||||
{
|
||||
initial_continue = true;
|
||||
return MXDBG_SUCCESS;
|
||||
}
|
||||
|
||||
static struct mxdbg_host dbg_host = {
|
||||
.read_remote = read_remote,
|
||||
.write_remote = write_remote,
|
||||
.identify = identify,
|
||||
.identify_task = identify_task,
|
||||
.resume = resume,
|
||||
};
|
||||
|
||||
static void debugger(void)
|
||||
{
|
||||
ml_int_enable();
|
||||
while (1) {
|
||||
mxdbg_host_handle_request(&dbg_host);
|
||||
}
|
||||
}
|
||||
|
||||
kern_status_t debug_await(void)
|
||||
{
|
||||
debug_enabled = true;
|
||||
|
||||
printk("debug: waiting for connection...");
|
||||
while (!initial_continue) {
|
||||
mxdbg_host_handle_request(&dbg_host);
|
||||
}
|
||||
|
||||
return KERN_OK;
|
||||
}
|
||||
|
||||
kern_status_t debug_create_task(void)
|
||||
{
|
||||
struct task *kernel_task = get_current_task();
|
||||
struct thread *debug_thread = task_create_thread(kernel_task);
|
||||
thread_init_kernel(debug_thread, (virt_addr_t)debugger);
|
||||
schedule_thread_on_cpu(debug_thread);
|
||||
put_current_task(kernel_task);
|
||||
return KERN_OK;
|
||||
}
|
||||
|
||||
kern_status_t debug_event_task_created(tid_t id)
|
||||
{
|
||||
if (!debug_enabled) {
|
||||
return KERN_OK;
|
||||
}
|
||||
|
||||
struct mxdbg_packet_event ev = {0};
|
||||
mxdbg_packet_init(&ev.ev_base, sizeof ev, MXDBG_PACKET_EVENT, 0);
|
||||
ev.ev_type = MXDBG_EVENT_TASK_CREATED;
|
||||
ev.ev_task = id;
|
||||
size_t w;
|
||||
write_remote(&dbg_host, &ev, sizeof ev, &w);
|
||||
return KERN_OK;
|
||||
}
|
||||
|
||||
kern_status_t debug_event_task_started(void)
|
||||
{
|
||||
return KERN_OK;
|
||||
}
|
||||
|
||||
kern_status_t debug_event_task_stopped(void)
|
||||
{
|
||||
return KERN_OK;
|
||||
}
|
||||
|
||||
kern_status_t debug_event_task_destroyed(void)
|
||||
{
|
||||
return KERN_OK;
|
||||
}
|
||||
Reference in New Issue
Block a user