diff --git a/arch/x86_64/debug.c b/arch/x86_64/debug.c new file mode 100644 index 0000000..dd0d5b8 --- /dev/null +++ b/arch/x86_64/debug.c @@ -0,0 +1,13 @@ +#include +#include +#include + +kern_status_t debug_read(void *buf, size_t max, size_t *nr_read) +{ + return serial_read(COM1, buf, max, nr_read); +} + +kern_status_t debug_write(const void *buf, size_t max, size_t *nr_written) +{ + return serial_write(COM1, buf, max, nr_written); +} diff --git a/arch/x86_64/include/kernel/machine/debug.h b/arch/x86_64/include/kernel/machine/debug.h new file mode 100644 index 0000000..d539178 --- /dev/null +++ b/arch/x86_64/include/kernel/machine/debug.h @@ -0,0 +1,10 @@ +#ifndef KERNEL_X86_64_DEBUG_H_ +#define KERNEL_X86_64_DEBUG_H_ + +#include +#include + +extern kern_status_t debug_read(void *buf, size_t max, size_t *nr_read); +extern kern_status_t debug_write(const void *buf, size_t max, size_t *nr_read); + +#endif diff --git a/arch/x86_64/init.c b/arch/x86_64/init.c index bcf67e6..cb97d33 100644 --- a/arch/x86_64/init.c +++ b/arch/x86_64/init.c @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -19,6 +20,7 @@ #include #include #include +#include #define HARDWARE_RNG @@ -69,7 +71,8 @@ static void early_vm_init(uintptr_t reserve_end) void early_console_init(void) { const char *dest = arg_value("kernel.early-console"); - if (!dest) { + bool debug = arg_is_set("kernel.enable-debugger"); + if (!dest || debug) { dest = "tty0"; } @@ -186,5 +189,10 @@ int ml_init(uintptr_t arg) pit_start(500); ml_int_enable(); + if (arg_is_set("kernel.enable-debugger")) { + debug_await(); + debug_create_task(); + } + return 0; } diff --git a/include/kernel/debug.h b/include/kernel/debug.h new file mode 100644 index 0000000..b474a4d --- /dev/null +++ b/include/kernel/debug.h @@ -0,0 +1,15 @@ +#ifndef KERNEL_DEBUG_H_ +#define KERNEL_DEBUG_H_ + +#include +#include + +extern kern_status_t debug_await(void); +extern kern_status_t debug_create_task(void); + +extern kern_status_t debug_event_task_created(tid_t id); +extern kern_status_t debug_event_task_started(void); +extern kern_status_t debug_event_task_stopped(void); +extern kern_status_t debug_event_task_destroyed(void); + +#endif diff --git a/init/main.c b/init/main.c index 9c1d3b6..b2565bb 100644 --- a/init/main.c +++ b/init/main.c @@ -23,7 +23,7 @@ extern char __pstart[], __pend[]; void print_kernel_banner(void) { - printk("Magenta version " KERNEL_VERSION); + printk(KERNEL_NAME " version " KERNEL_VERSION); } static void hang(void) diff --git a/kernel/debug.c b/kernel/debug.c new file mode 100644 index 0000000..bcab924 --- /dev/null +++ b/kernel/debug.c @@ -0,0 +1,165 @@ +#include "kernel/panic.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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; +} diff --git a/sched/task.c b/sched/task.c index 6320a3f..c3bec01 100644 --- a/sched/task.c +++ b/sched/task.c @@ -2,6 +2,7 @@ #include #include #include +#include #include #include #include @@ -223,6 +224,8 @@ struct task *task_create( task_list_insert(&task_list, task); spin_unlock_irqrestore(&task_list_lock, flags); + debug_event_task_created(task->t_id); + return task; }