166 lines
3.3 KiB
C
166 lines
3.3 KiB
C
#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;
|
|
}
|