kernel: implement support for magenta_debug over serial
This commit is contained in:
@@ -0,0 +1,13 @@
|
||||
#include <arch/serial.h>
|
||||
#include <kernel/machine/debug.h>
|
||||
#include <magenta/status.h>
|
||||
|
||||
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);
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
#ifndef KERNEL_X86_64_DEBUG_H_
|
||||
#define KERNEL_X86_64_DEBUG_H_
|
||||
|
||||
#include <magenta/types.h>
|
||||
#include <stddef.h>
|
||||
|
||||
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
|
||||
+9
-1
@@ -7,6 +7,7 @@
|
||||
#include <kernel/clock.h>
|
||||
#include <kernel/console.h>
|
||||
#include <kernel/cpu.h>
|
||||
#include <kernel/debug.h>
|
||||
#include <kernel/init.h>
|
||||
#include <kernel/libc/stdio.h>
|
||||
#include <kernel/machine/cpu.h>
|
||||
@@ -19,6 +20,7 @@
|
||||
#include <kernel/types.h>
|
||||
#include <kernel/util.h>
|
||||
#include <kernel/vm.h>
|
||||
#include <magenta/debug/packet.h>
|
||||
|
||||
#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;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
#ifndef KERNEL_DEBUG_H_
|
||||
#define KERNEL_DEBUG_H_
|
||||
|
||||
#include <magenta/status.h>
|
||||
#include <magenta/types.h>
|
||||
|
||||
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
|
||||
+1
-1
@@ -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)
|
||||
|
||||
+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;
|
||||
}
|
||||
@@ -2,6 +2,7 @@
|
||||
#include <kernel/channel.h>
|
||||
#include <kernel/clock.h>
|
||||
#include <kernel/cpu.h>
|
||||
#include <kernel/debug.h>
|
||||
#include <kernel/handle.h>
|
||||
#include <kernel/libc/stdio.h>
|
||||
#include <kernel/locks.h>
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user