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/clock.h>
|
||||||
#include <kernel/console.h>
|
#include <kernel/console.h>
|
||||||
#include <kernel/cpu.h>
|
#include <kernel/cpu.h>
|
||||||
|
#include <kernel/debug.h>
|
||||||
#include <kernel/init.h>
|
#include <kernel/init.h>
|
||||||
#include <kernel/libc/stdio.h>
|
#include <kernel/libc/stdio.h>
|
||||||
#include <kernel/machine/cpu.h>
|
#include <kernel/machine/cpu.h>
|
||||||
@@ -19,6 +20,7 @@
|
|||||||
#include <kernel/types.h>
|
#include <kernel/types.h>
|
||||||
#include <kernel/util.h>
|
#include <kernel/util.h>
|
||||||
#include <kernel/vm.h>
|
#include <kernel/vm.h>
|
||||||
|
#include <magenta/debug/packet.h>
|
||||||
|
|
||||||
#define HARDWARE_RNG
|
#define HARDWARE_RNG
|
||||||
|
|
||||||
@@ -69,7 +71,8 @@ static void early_vm_init(uintptr_t reserve_end)
|
|||||||
void early_console_init(void)
|
void early_console_init(void)
|
||||||
{
|
{
|
||||||
const char *dest = arg_value("kernel.early-console");
|
const char *dest = arg_value("kernel.early-console");
|
||||||
if (!dest) {
|
bool debug = arg_is_set("kernel.enable-debugger");
|
||||||
|
if (!dest || debug) {
|
||||||
dest = "tty0";
|
dest = "tty0";
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -186,5 +189,10 @@ int ml_init(uintptr_t arg)
|
|||||||
pit_start(500);
|
pit_start(500);
|
||||||
ml_int_enable();
|
ml_int_enable();
|
||||||
|
|
||||||
|
if (arg_is_set("kernel.enable-debugger")) {
|
||||||
|
debug_await();
|
||||||
|
debug_create_task();
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
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)
|
void print_kernel_banner(void)
|
||||||
{
|
{
|
||||||
printk("Magenta version " KERNEL_VERSION);
|
printk(KERNEL_NAME " version " KERNEL_VERSION);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void hang(void)
|
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/channel.h>
|
||||||
#include <kernel/clock.h>
|
#include <kernel/clock.h>
|
||||||
#include <kernel/cpu.h>
|
#include <kernel/cpu.h>
|
||||||
|
#include <kernel/debug.h>
|
||||||
#include <kernel/handle.h>
|
#include <kernel/handle.h>
|
||||||
#include <kernel/libc/stdio.h>
|
#include <kernel/libc/stdio.h>
|
||||||
#include <kernel/locks.h>
|
#include <kernel/locks.h>
|
||||||
@@ -223,6 +224,8 @@ struct task *task_create(
|
|||||||
task_list_insert(&task_list, task);
|
task_list_insert(&task_list, task);
|
||||||
spin_unlock_irqrestore(&task_list_lock, flags);
|
spin_unlock_irqrestore(&task_list_lock, flags);
|
||||||
|
|
||||||
|
debug_event_task_created(task->t_id);
|
||||||
|
|
||||||
return task;
|
return task;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user