Compare commits
12 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| a14d0173c8 | |||
| bd6872d672 | |||
| 2ca7a34a22 | |||
| c425d6e389 | |||
| eb15d2ffa3 | |||
| 249ac7a8cf | |||
| 44bcc8c805 | |||
| 4f0d3c1071 | |||
| 4d30949a4d | |||
| c90ee285cc | |||
| 6f178f1a60 | |||
| 5e9a165578 |
+32
-5
@@ -1,10 +1,6 @@
|
||||
cmake_minimum_required(VERSION 3.31)
|
||||
project(magenta C ASM)
|
||||
|
||||
if (NOT BUILD_TOOLS_DIR)
|
||||
message(FATAL_ERROR "No build tools directory specified. Please run build.sh")
|
||||
endif ()
|
||||
|
||||
set(CMAKE_C_STANDARD 17)
|
||||
|
||||
set(kernel_arch x86_64)
|
||||
@@ -16,6 +12,23 @@ set(generic_src_dirs ds init kernel libc sched util vm syscall)
|
||||
set(kernel_sources "")
|
||||
set(kernel_headers "")
|
||||
|
||||
set(version_args --arch ${CMAKE_SYSTEM_PROCESSOR})
|
||||
|
||||
if (CMAKE_BUILD_TYPE)
|
||||
if (NOT "${CMAKE_BUILD_TYPE}" STREQUAL "Debug")
|
||||
set(version_args ${version_args} "--release")
|
||||
endif ()
|
||||
endif()
|
||||
|
||||
execute_process(
|
||||
COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/tools/magenta.buildid
|
||||
${version_args}
|
||||
OUTPUT_VARIABLE kernel_version
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||
|
||||
message(STATUS "Magenta kernel version: ${kernel_version}")
|
||||
|
||||
foreach (dir ${generic_src_dirs})
|
||||
file(GLOB_RECURSE dir_sources ${dir}/*.c)
|
||||
file(GLOB_RECURSE dir_headers ${dir}/*.h)
|
||||
@@ -52,7 +65,21 @@ add_custom_command(
|
||||
COMMAND ${CMAKE_STRIP} -g $<TARGET_FILE:${kernel_exe_name}>)
|
||||
|
||||
target_link_libraries(${kernel_exe_name} -nostdlib -ffreestanding -lgcc)
|
||||
target_compile_definitions(${kernel_exe_name} PRIVATE BUILD_ID="0")
|
||||
target_compile_definitions(${kernel_exe_name} PRIVATE
|
||||
KERNEL_NAME="${kernel_name}"
|
||||
KERNEL_VERSION="${kernel_version}"
|
||||
KERNEL_ARCH="${kernel_arch}")
|
||||
|
||||
include(arch/${kernel_arch}/config.cmake)
|
||||
include(arch/${kernel_arch}/targets.cmake)
|
||||
|
||||
add_subdirectory(debug)
|
||||
target_link_libraries(${kernel_exe_name} magenta_debug)
|
||||
target_compile_definitions(magenta_debug PRIVATE KERNEL_VERSION="${kernel_version}")
|
||||
target_include_directories(magenta_debug PRIVATE
|
||||
include
|
||||
libc/include
|
||||
libmagenta/include
|
||||
arch/${kernel_arch}/include)
|
||||
|
||||
install(TARGETS ${kernel_exe_name} DESTINATION boot)
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -1,14 +1,21 @@
|
||||
#ifndef ARCH_SERIAL_H_
|
||||
#define ARCH_SERIAL_H_
|
||||
|
||||
#include <magenta/types.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define SERIAL_PORT_A 0x3F8
|
||||
#define SERIAL_PORT_B 0x2F8
|
||||
#define SERIAL_PORT_C 0x3E8
|
||||
#define SERIAL_PORT_D 0x2E8
|
||||
#define COM(x) (x)
|
||||
|
||||
#define COM1 COM(1)
|
||||
#define COM2 COM(2)
|
||||
#define COM3 COM(3)
|
||||
#define COM4 COM(4)
|
||||
|
||||
extern void serial_init(int baud);
|
||||
|
||||
extern void serial_putchar(int port, char ch);
|
||||
|
||||
@@ -18,7 +25,18 @@ extern char serial_recv_byte(int device);
|
||||
|
||||
extern int serial_rcvd(int device);
|
||||
|
||||
extern void early_serialcon_init(int baud);
|
||||
extern kern_status_t serial_read(
|
||||
int device,
|
||||
void *buf,
|
||||
size_t max,
|
||||
size_t *nr_read);
|
||||
extern kern_status_t serial_write(
|
||||
int device,
|
||||
const void *buf,
|
||||
size_t count,
|
||||
size_t *nr_written);
|
||||
|
||||
extern void early_serialcon_init(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -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
|
||||
+11
-4
@@ -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";
|
||||
}
|
||||
|
||||
@@ -78,7 +81,7 @@ void early_console_init(void)
|
||||
vgacon_init();
|
||||
} else if (!strcmp(dest, "ttyS0")) {
|
||||
/* write log messages to serial port */
|
||||
early_serialcon_init(115200);
|
||||
early_serialcon_init();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -92,8 +95,6 @@ static void find_bsp(multiboot_info_t *mb, struct boot_module *out)
|
||||
{
|
||||
memset(out, 0x0, sizeof *out);
|
||||
|
||||
printk("modules=%u: %llx", mb->mods_count, mb->mods_addr);
|
||||
|
||||
multiboot_module_t *mods = PTR32(mb->mods_addr);
|
||||
size_t nr_mods = mb->mods_count;
|
||||
|
||||
@@ -111,6 +112,7 @@ int ml_init(uintptr_t arg)
|
||||
|
||||
parse_cmdline(PTR32(mb->cmdline));
|
||||
|
||||
serial_init(115200);
|
||||
early_console_init();
|
||||
|
||||
bootstrap_cpu_init();
|
||||
@@ -187,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;
|
||||
}
|
||||
|
||||
+144
-41
@@ -3,50 +3,78 @@
|
||||
#include <arch/serial.h>
|
||||
#include <kernel/libc/stdio.h>
|
||||
#include <kernel/printk.h>
|
||||
#include <kernel/ringbuf.h>
|
||||
|
||||
#define COM1 0x3F8
|
||||
#define COM2 0x2F8
|
||||
#define COM3 0x3E8
|
||||
#define COM4 0x2E8
|
||||
#define SERIAL_BUFFER_SIZE 1024
|
||||
|
||||
static int transmit_empty(int device)
|
||||
RINGBUF_DECLARE(com1_queue, SERIAL_BUFFER_SIZE);
|
||||
RINGBUF_DECLARE(com2_queue, SERIAL_BUFFER_SIZE);
|
||||
RINGBUF_DECLARE(com3_queue, SERIAL_BUFFER_SIZE);
|
||||
RINGBUF_DECLARE(com4_queue, SERIAL_BUFFER_SIZE);
|
||||
|
||||
static const uint16_t port_addresses[] = {
|
||||
[COM1] = 0x3F8,
|
||||
[COM2] = 0x2F8,
|
||||
[COM3] = 0x3E8,
|
||||
[COM4] = 0x2E8,
|
||||
};
|
||||
|
||||
static int port_active[] = {
|
||||
[COM1] = 0,
|
||||
[COM2] = 0,
|
||||
[COM3] = 0,
|
||||
[COM4] = 0,
|
||||
};
|
||||
|
||||
static struct ringbuf *port_buffer[] = {
|
||||
[COM1] = &com1_queue,
|
||||
[COM2] = &com2_queue,
|
||||
[COM3] = &com3_queue,
|
||||
[COM4] = &com4_queue,
|
||||
};
|
||||
|
||||
static int transmit_empty(int port)
|
||||
{
|
||||
return inportb(device + 5) & 0x20;
|
||||
return inportb(port_addresses[port] + 5) & 0x20;
|
||||
}
|
||||
|
||||
static int serial_received(int device)
|
||||
static int serial_received(int port)
|
||||
{
|
||||
return inportb(device + 5) & 0x1;
|
||||
return inportb(port_addresses[port] + 5) & 0x1;
|
||||
}
|
||||
|
||||
void serial_send_byte(int device, char out)
|
||||
void serial_send_byte(int port, char out)
|
||||
{
|
||||
uint16_t address = port_addresses[port];
|
||||
volatile unsigned int _count = 0;
|
||||
while (!transmit_empty(device)) {
|
||||
while (!transmit_empty(port)) {
|
||||
_count++;
|
||||
}
|
||||
(void)_count;
|
||||
|
||||
outportb(device, out);
|
||||
outportb(address, out);
|
||||
|
||||
if (device == COM1) {
|
||||
if (port == COM1) {
|
||||
outportb(0xe9, out);
|
||||
}
|
||||
|
||||
while (!transmit_empty(device)) {
|
||||
while (!transmit_empty(port)) {
|
||||
_count++;
|
||||
}
|
||||
}
|
||||
|
||||
char serial_recv_byte(int device)
|
||||
char serial_recv_byte(int port)
|
||||
{
|
||||
uint16_t address = port_addresses[port];
|
||||
volatile unsigned int _count = 0;
|
||||
while (!serial_received(device)) {
|
||||
while (!serial_received(port)) {
|
||||
_count++;
|
||||
}
|
||||
(void)_count;
|
||||
|
||||
char c = inportb(device);
|
||||
char c = inportb(address);
|
||||
|
||||
outportb(device + 5, inportb(device + 5) & ~0x1);
|
||||
outportb(address + 5, inportb(address + 5) & ~0x1);
|
||||
|
||||
return c;
|
||||
}
|
||||
@@ -100,37 +128,75 @@ static int get_baud_divisor(int baud)
|
||||
|
||||
static void init_serial_port(int port, int baud)
|
||||
{
|
||||
uint16_t address = port_addresses[port];
|
||||
int baud_div = get_baud_divisor(baud);
|
||||
outportb(port + 1, 0x00); // Disable all interrupts
|
||||
outportb(port + 3, 0x80); // Enable DLAB (set baud rate divisor)
|
||||
outportb(port + 0, baud_div); // Set divisor
|
||||
outportb(port + 1, 0x00);
|
||||
outportb(port + 3, 0x03); // 8 bits, no parity, one stop bit
|
||||
outportb(address + 1, 0x00); // Disable all interrupts
|
||||
outportb(address + 3, 0x80); // Enable DLAB (set baud rate divisor)
|
||||
outportb(address + 0, baud_div); // Set divisor
|
||||
outportb(address + 1, 0x00);
|
||||
outportb(address + 3, 0x03); // 8 bits, no parity, one stop bit
|
||||
outportb(
|
||||
port + 2,
|
||||
address + 2,
|
||||
0xC7); // Enable FIFO, clear them, with 14-byte threshold
|
||||
outportb(port + 4, 0x0B); // IRQs enabled, RTS/DSR set
|
||||
outportb(address + 4, 0x0B); // IRQs enabled, RTS/DSR set
|
||||
outportb(
|
||||
port + 4,
|
||||
address + 4,
|
||||
0x1E); // Set in loopback mode, test the serial chip
|
||||
outportb(port + 0, 0xAE); // Test serial chip (send byte 0xAE and
|
||||
outportb(address + 0, 0xAE); // Test serial chip (send byte 0xAE and
|
||||
// check if serial returns same byte)
|
||||
|
||||
volatile unsigned int q = 0;
|
||||
while (!serial_received(port)) {
|
||||
q++;
|
||||
}
|
||||
(void)q;
|
||||
|
||||
// Check if serial is faulty (i.e: not same byte as sent)
|
||||
if (inportb(port + 0) != 0xAE) {
|
||||
if (inportb(address + 0) != 0xAE) {
|
||||
printk("serial: COM%d is faulty", port);
|
||||
return;
|
||||
}
|
||||
|
||||
// If serial is not faulty set it in normal operation mode
|
||||
// (not-loopback with IRQs enabled and OUT#1 and OUT#2 bits enabled)
|
||||
outportb(port + 1, 0x01);
|
||||
outportb(port + 4, 0x0F);
|
||||
printk("serial: port %x initialised", port);
|
||||
outportb(address + 1, 0x01);
|
||||
outportb(address + 4, 0x0F);
|
||||
port_active[port] = 1;
|
||||
printk("serial: COM%d initialised", port);
|
||||
}
|
||||
|
||||
kern_status_t serial_read(int device, void *buf, size_t max, size_t *nr_read)
|
||||
{
|
||||
struct ringbuf *src = port_buffer[device];
|
||||
|
||||
unsigned long flags;
|
||||
ringbuf_lock(src, &flags);
|
||||
kern_status_t status = ringbuf_read(src, buf, max, nr_read, &flags);
|
||||
ringbuf_unlock(src, flags);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
kern_status_t serial_write(
|
||||
int device,
|
||||
const void *buf,
|
||||
size_t count,
|
||||
size_t *nr_written)
|
||||
{
|
||||
if (!port_active[device]) {
|
||||
return KERN_BAD_STATE;
|
||||
}
|
||||
|
||||
const unsigned char *p = buf;
|
||||
|
||||
size_t w = 0;
|
||||
for (size_t i = 0; i < count; i++) {
|
||||
serial_send_byte(device, p[i]);
|
||||
w++;
|
||||
}
|
||||
|
||||
*nr_written = w;
|
||||
return KERN_OK;
|
||||
}
|
||||
|
||||
static struct console serialcon = {
|
||||
@@ -140,30 +206,67 @@ static struct console serialcon = {
|
||||
.c_lock = SPIN_LOCK_INIT,
|
||||
};
|
||||
|
||||
static int serial_irq1(void)
|
||||
static int serial_irq_com1_com3(void)
|
||||
{
|
||||
#if 0
|
||||
if (serial_received(COM1)) {
|
||||
unsigned long flags;
|
||||
|
||||
if (port_active[COM1] && serial_received(COM1)) {
|
||||
unsigned char c = serial_recv_byte(COM1);
|
||||
printk("serial: COM1 received %c", c);
|
||||
ringbuf_lock(&com1_queue, &flags);
|
||||
ringbuf_write(&com1_queue, &c, 1, NULL, &flags);
|
||||
ringbuf_unlock(&com1_queue, flags);
|
||||
}
|
||||
|
||||
if (serial_received(COM3)) {
|
||||
if (port_active[COM3] && serial_received(COM3)) {
|
||||
unsigned char c = serial_recv_byte(COM3);
|
||||
printk("serial: COM3 received %c", c);
|
||||
ringbuf_lock(&com3_queue, &flags);
|
||||
ringbuf_write(&com3_queue, &c, 1, NULL, &flags);
|
||||
ringbuf_unlock(&com3_queue, flags);
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct irq_hook irq1_hook = {
|
||||
.irq_callback = serial_irq1,
|
||||
static int serial_irq_com2_com4(void)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
if (port_active[COM2] && serial_received(COM2)) {
|
||||
unsigned char c = serial_recv_byte(COM2);
|
||||
ringbuf_lock(&com2_queue, &flags);
|
||||
ringbuf_write(&com2_queue, &c, 1, NULL, &flags);
|
||||
ringbuf_unlock(&com2_queue, flags);
|
||||
}
|
||||
|
||||
if (port_active[COM4] && serial_received(COM4)) {
|
||||
unsigned char c = serial_recv_byte(COM4);
|
||||
ringbuf_lock(&com4_queue, &flags);
|
||||
ringbuf_write(&com4_queue, &c, 1, NULL, &flags);
|
||||
ringbuf_unlock(&com4_queue, flags);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct irq_hook irq_hook_com1_com3 = {
|
||||
.irq_callback = serial_irq_com1_com3,
|
||||
};
|
||||
|
||||
void early_serialcon_init(int baud)
|
||||
static struct irq_hook irq_hook_com2_com4 = {
|
||||
.irq_callback = serial_irq_com2_com4,
|
||||
};
|
||||
|
||||
void serial_init(int baud)
|
||||
{
|
||||
hook_irq(IRQ4, &irq1_hook);
|
||||
hook_irq(IRQ4, &irq_hook_com1_com3);
|
||||
hook_irq(IRQ3, &irq_hook_com2_com4);
|
||||
init_serial_port(COM1, baud);
|
||||
init_serial_port(COM2, baud);
|
||||
init_serial_port(COM3, baud);
|
||||
init_serial_port(COM4, baud);
|
||||
}
|
||||
|
||||
void early_serialcon_init(void)
|
||||
{
|
||||
console_register(&serialcon);
|
||||
}
|
||||
|
||||
@@ -93,6 +93,8 @@ kern_status_t ml_thread_clone_user_context(
|
||||
memcpy(regs, src_regs, sizeof *regs);
|
||||
|
||||
regs->rax = return_value;
|
||||
regs->ss = 0x1b;
|
||||
regs->cs = 0x23;
|
||||
|
||||
dest_ml->tr_fsbase = src_ml->tr_fsbase;
|
||||
dest_ml->tr_gsbase = src_ml->tr_gsbase;
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
file(GLOB sources *.c *.h include/magenta/debug/*.h)
|
||||
|
||||
add_library(magenta_debug STATIC ${sources})
|
||||
target_include_directories(magenta_debug PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include)
|
||||
target_compile_options(magenta_debug PRIVATE -ffreestanding -nostdlib)
|
||||
@@ -0,0 +1,29 @@
|
||||
#include <magenta/debug/event.h>
|
||||
|
||||
const char *mxdbg_event_type_get_description(enum mxdbg_event_type type)
|
||||
{
|
||||
switch (type) {
|
||||
case MXDBG_EVENT_TASK_CREATED:
|
||||
return "task-create";
|
||||
case MXDBG_EVENT_TASK_STARTED:
|
||||
return "task-start";
|
||||
case MXDBG_EVENT_TASK_STOPPED:
|
||||
return "task-stop";
|
||||
case MXDBG_EVENT_TASK_DESTROYED:
|
||||
return "task-destroy";
|
||||
case MXDBG_EVENT_THREAD_CREATED:
|
||||
return "thread-create";
|
||||
case MXDBG_EVENT_THREAD_STARTED:
|
||||
return "thread-start";
|
||||
case MXDBG_EVENT_THREAD_STOPPED:
|
||||
return "thread-stop";
|
||||
case MXDBG_EVENT_THREAD_DESTROYED:
|
||||
return "thread-destroy";
|
||||
case MXDBG_EVENT_THREAD_FAULT:
|
||||
return "thread-fault";
|
||||
case MXDBG_EVENT_PANIC:
|
||||
return "panic";
|
||||
default:
|
||||
return "<unknown>";
|
||||
}
|
||||
}
|
||||
+110
@@ -0,0 +1,110 @@
|
||||
#include "magenta/debug/util.h"
|
||||
|
||||
#include <magenta/debug/host.h>
|
||||
#include <magenta/debug/packet.h>
|
||||
#include <magenta/debug/request.h>
|
||||
|
||||
enum mxdbg_status mxdbg_host_handle_request(struct mxdbg_host *host)
|
||||
{
|
||||
struct mxdbg_packet packet = {0};
|
||||
enum mxdbg_status status = mxdbg_host_recv(host, &packet);
|
||||
if (status != MXDBG_SUCCESS) {
|
||||
debug_printf("debug: failed to read packet");
|
||||
return status;
|
||||
}
|
||||
|
||||
if (packet.pkt_magic != MXDBG_PACKET_MAGIC) {
|
||||
debug_printf(
|
||||
"debug: packet is malformed (magic=%08x)",
|
||||
packet.pkt_magic);
|
||||
return MXDBG_ERR_BAD_FORMAT;
|
||||
}
|
||||
|
||||
return mxdbg_handle_request(host, &packet);
|
||||
}
|
||||
|
||||
enum mxdbg_status mxdbg_host_recv(
|
||||
struct mxdbg_host *host,
|
||||
struct mxdbg_packet *packet)
|
||||
{
|
||||
size_t r;
|
||||
|
||||
if (host->read_remote) {
|
||||
return host->read_remote(host, packet, sizeof *packet, &r);
|
||||
}
|
||||
|
||||
return MXDBG_ERR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
enum mxdbg_status mxdbg_host_recv_packet_data(
|
||||
struct mxdbg_host *host,
|
||||
struct mxdbg_packet *packet)
|
||||
{
|
||||
if (packet->pkt_magic != MXDBG_PACKET_MAGIC) {
|
||||
return MXDBG_ERR_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
if (!packet->pkt_length) {
|
||||
return MXDBG_SUCCESS;
|
||||
}
|
||||
|
||||
size_t r;
|
||||
void *dest = packet + 1;
|
||||
if (host->read_remote) {
|
||||
return host->read_remote(
|
||||
host,
|
||||
dest,
|
||||
packet->pkt_length - sizeof *packet,
|
||||
&r);
|
||||
}
|
||||
|
||||
return MXDBG_ERR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
enum mxdbg_status mxdbg_host_send(
|
||||
struct mxdbg_host *host,
|
||||
const struct mxdbg_packet *packet)
|
||||
{
|
||||
size_t w;
|
||||
if (host->write_remote) {
|
||||
return host->write_remote(host, packet, packet->pkt_length, &w);
|
||||
}
|
||||
|
||||
return MXDBG_ERR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
enum mxdbg_status mxdbg_host_identify(
|
||||
struct mxdbg_host *host,
|
||||
enum mxdbg_identity_key key,
|
||||
void *out,
|
||||
size_t max)
|
||||
{
|
||||
if (host->identify) {
|
||||
return host->identify(host, key, out, max);
|
||||
}
|
||||
|
||||
return MXDBG_ERR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
enum mxdbg_status mxdbg_host_identify_task(
|
||||
struct mxdbg_host *host,
|
||||
unsigned int tid,
|
||||
enum mxdbg_identity_key key,
|
||||
void *out,
|
||||
size_t max)
|
||||
{
|
||||
if (host->identify_task) {
|
||||
return host->identify_task(host, tid, key, out, max);
|
||||
}
|
||||
|
||||
return MXDBG_ERR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
enum mxdbg_status mxdbg_host_resume(struct mxdbg_host *host)
|
||||
{
|
||||
if (host->resume) {
|
||||
return host->resume(host);
|
||||
}
|
||||
|
||||
return MXDBG_ERR_NOT_SUPPORTED;
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
#ifndef MAGENTA_DEBUG_EVENT_H_
|
||||
#define MAGENTA_DEBUG_EVENT_H_
|
||||
|
||||
enum mxdbg_event_type {
|
||||
MXDBG_EVENT_NONE = 0,
|
||||
|
||||
MXDBG_EVENT_TASK_CREATED,
|
||||
MXDBG_EVENT_TASK_STARTED,
|
||||
MXDBG_EVENT_TASK_STOPPED,
|
||||
MXDBG_EVENT_TASK_DESTROYED,
|
||||
|
||||
MXDBG_EVENT_THREAD_CREATED,
|
||||
MXDBG_EVENT_THREAD_STARTED,
|
||||
MXDBG_EVENT_THREAD_STOPPED,
|
||||
MXDBG_EVENT_THREAD_DESTROYED,
|
||||
MXDBG_EVENT_THREAD_FAULT,
|
||||
|
||||
MXDBG_EVENT_PANIC,
|
||||
};
|
||||
|
||||
extern const char *mxdbg_event_type_get_description(enum mxdbg_event_type type);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,61 @@
|
||||
#ifndef MAGENTA_DEBUG_HOST_H_
|
||||
#define MAGENTA_DEBUG_HOST_H_
|
||||
|
||||
#include <magenta/debug/identity.h>
|
||||
#include <magenta/debug/status.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
struct mxdbg_packet;
|
||||
struct mxdbg_packet_event;
|
||||
|
||||
struct mxdbg_host {
|
||||
enum mxdbg_status (
|
||||
*read_remote)(struct mxdbg_host *, void *, size_t, size_t *);
|
||||
enum mxdbg_status (*write_remote)(
|
||||
struct mxdbg_host *,
|
||||
const void *,
|
||||
size_t,
|
||||
size_t *);
|
||||
enum mxdbg_status (*identify)(
|
||||
struct mxdbg_host *,
|
||||
enum mxdbg_identity_key,
|
||||
void *,
|
||||
size_t);
|
||||
enum mxdbg_status (*identify_task)(
|
||||
struct mxdbg_host *,
|
||||
unsigned int,
|
||||
enum mxdbg_identity_key,
|
||||
void *,
|
||||
size_t);
|
||||
enum mxdbg_status (*resume)(struct mxdbg_host *);
|
||||
};
|
||||
|
||||
extern enum mxdbg_status mxdbg_host_handle_request(struct mxdbg_host *host);
|
||||
|
||||
extern enum mxdbg_status mxdbg_host_recv(
|
||||
struct mxdbg_host *host,
|
||||
struct mxdbg_packet *packet);
|
||||
extern enum mxdbg_status mxdbg_host_recv_packet_data(
|
||||
struct mxdbg_host *host,
|
||||
struct mxdbg_packet *packet);
|
||||
extern enum mxdbg_status mxdbg_host_send(
|
||||
struct mxdbg_host *host,
|
||||
const struct mxdbg_packet *packet);
|
||||
extern enum mxdbg_status mxdbg_host_identify(
|
||||
struct mxdbg_host *host,
|
||||
enum mxdbg_identity_key key,
|
||||
void *out,
|
||||
size_t max);
|
||||
extern enum mxdbg_status mxdbg_host_identify_task(
|
||||
struct mxdbg_host *host,
|
||||
unsigned int task,
|
||||
enum mxdbg_identity_key key,
|
||||
void *out,
|
||||
size_t max);
|
||||
extern enum mxdbg_status mxdbg_host_resume(struct mxdbg_host *host);
|
||||
extern enum mxdbg_status mxdbg_host_send_event(
|
||||
struct mxdbg_host *host,
|
||||
struct mxdbg_packet_event *ev);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,16 @@
|
||||
#ifndef MAGENTA_DEBUG_IDENTITY_H_
|
||||
#define MAGENTA_DEBUG_IDENTITY_H_
|
||||
|
||||
enum mxdbg_identity_key {
|
||||
MXDBG_IDENTITY_NONE = 0,
|
||||
MXDBG_IDENTITY_KERNEL_NAME,
|
||||
MXDBG_IDENTITY_KERNEL_VERSION,
|
||||
MXDBG_IDENTITY_KERNEL_ARCH,
|
||||
|
||||
/* identify_task keys */
|
||||
MXDBG_IDENTITY_TASK_NAME,
|
||||
MXDBG_IDENTITY_TASK_PARENT,
|
||||
MXDBG_IDENTITY_TASK_NR_THREADS,
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,66 @@
|
||||
#ifndef MAGENTA_DEBUG_PACKET_H_
|
||||
#define MAGENTA_DEBUG_PACKET_H_
|
||||
|
||||
#include <magenta/debug/event.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#define MXDBG_PACKET_MAGIC 0xdecafbaf
|
||||
|
||||
enum mxdbg_packet_type {
|
||||
MXDBG_PACKET_NONE = 0,
|
||||
MXDBG_PACKET_IDENTIFY_KERNEL,
|
||||
MXDBG_PACKET_IDENTIFY_TASK,
|
||||
MXDBG_PACKET_LIST_TASK,
|
||||
MXDBG_PACKET_RESUME,
|
||||
MXDBG_PACKET_STOP,
|
||||
MXDBG_PACKET_EVENT,
|
||||
};
|
||||
|
||||
enum mxdbg_packet_flags {
|
||||
MXDBG_PACKET_F_NONE = 0,
|
||||
MXDBG_PACKET_F_RESPONSE = 0x01u,
|
||||
};
|
||||
|
||||
struct mxdbg_packet {
|
||||
uint32_t pkt_magic;
|
||||
uint16_t pkt_length;
|
||||
uint8_t pkt_type;
|
||||
uint8_t pkt_flags;
|
||||
};
|
||||
|
||||
struct mxdbg_packet_identify_kernel {
|
||||
struct mxdbg_packet id_base;
|
||||
char id_kernel_name[32];
|
||||
char id_kernel_version[32];
|
||||
char id_kernel_arch[16];
|
||||
};
|
||||
|
||||
struct mxdbg_packet_list_task {
|
||||
struct mxdbg_packet l_base;
|
||||
uint16_t l_task_count;
|
||||
};
|
||||
|
||||
struct mxdbg_packet_identify_task {
|
||||
struct mxdbg_packet id_base;
|
||||
uint16_t id_task, id_parent;
|
||||
uint16_t id_thread_count;
|
||||
char id_task_name[64];
|
||||
};
|
||||
|
||||
struct mxdbg_packet_event {
|
||||
struct mxdbg_packet ev_base;
|
||||
uint16_t ev_type;
|
||||
uint16_t ev_task, ev_thread;
|
||||
uint32_t ev_code;
|
||||
};
|
||||
|
||||
extern void mxdbg_packet_init(
|
||||
struct mxdbg_packet *packet,
|
||||
size_t size,
|
||||
enum mxdbg_packet_type type,
|
||||
enum mxdbg_packet_flags flags);
|
||||
extern bool mxdbg_packet_validate(const struct mxdbg_packet *packet);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
#ifndef MAGENTA_DEBUG_REQUEST_H_
|
||||
#define MAGENTA_DEBUG_REQUEST_H_
|
||||
|
||||
struct mxdbg_host;
|
||||
struct mxdbg_packet;
|
||||
|
||||
extern enum mxdbg_status mxdbg_handle_request(
|
||||
struct mxdbg_host *host,
|
||||
const struct mxdbg_packet *req);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,12 @@
|
||||
#ifndef MAGENTA_DEBUG_STATUS_H_
|
||||
#define MAGENTA_DEBUG_STATUS_H_
|
||||
|
||||
enum mxdbg_status {
|
||||
MXDBG_SUCCESS = 0,
|
||||
MXDBG_ERR_INVALID_ARGUMENT,
|
||||
MXDBG_ERR_NOT_SUPPORTED,
|
||||
MXDBG_ERR_BAD_FORMAT,
|
||||
MXDBG_ERR_IO_FAILURE,
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,14 @@
|
||||
#ifndef MAGENTA_DEBUG_UTIL_H_
|
||||
#define MAGENTA_DEBUG_UTIL_H_
|
||||
|
||||
#if defined(KERNEL_VERSION)
|
||||
#include <kernel/libc/string.h>
|
||||
#include <kernel/printk.h>
|
||||
#define debug_printf(...) printk(__VA_ARGS__)
|
||||
#else
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#define debug_printf(...) printf(__VA_ARGS__)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,20 @@
|
||||
#include <magenta/debug/packet.h>
|
||||
#include <magenta/debug/util.h>
|
||||
|
||||
void mxdbg_packet_init(
|
||||
struct mxdbg_packet *packet,
|
||||
size_t size,
|
||||
enum mxdbg_packet_type type,
|
||||
enum mxdbg_packet_flags flags)
|
||||
{
|
||||
memset(packet, 0x0, sizeof *packet);
|
||||
packet->pkt_magic = MXDBG_PACKET_MAGIC;
|
||||
packet->pkt_length = size;
|
||||
packet->pkt_type = type;
|
||||
packet->pkt_flags = flags;
|
||||
}
|
||||
|
||||
bool mxdbg_packet_validate(const struct mxdbg_packet *packet)
|
||||
{
|
||||
return packet->pkt_magic == MXDBG_PACKET_MAGIC;
|
||||
}
|
||||
+106
@@ -0,0 +1,106 @@
|
||||
#include <magenta/debug/host.h>
|
||||
#include <magenta/debug/packet.h>
|
||||
#include <magenta/debug/util.h>
|
||||
|
||||
static enum mxdbg_status identify_kernel(
|
||||
struct mxdbg_host *host,
|
||||
const struct mxdbg_packet *req)
|
||||
{
|
||||
struct mxdbg_packet_identify_kernel id = {0};
|
||||
mxdbg_packet_init(
|
||||
&id.id_base,
|
||||
sizeof id,
|
||||
MXDBG_PACKET_IDENTIFY_KERNEL,
|
||||
MXDBG_PACKET_F_RESPONSE);
|
||||
|
||||
mxdbg_host_identify(
|
||||
host,
|
||||
MXDBG_IDENTITY_KERNEL_NAME,
|
||||
id.id_kernel_name,
|
||||
sizeof id.id_kernel_name);
|
||||
mxdbg_host_identify(
|
||||
host,
|
||||
MXDBG_IDENTITY_KERNEL_VERSION,
|
||||
id.id_kernel_version,
|
||||
sizeof id.id_kernel_version);
|
||||
mxdbg_host_identify(
|
||||
host,
|
||||
MXDBG_IDENTITY_KERNEL_ARCH,
|
||||
id.id_kernel_arch,
|
||||
sizeof id.id_kernel_arch);
|
||||
|
||||
mxdbg_host_send(host, &id.id_base);
|
||||
|
||||
return MXDBG_SUCCESS;
|
||||
}
|
||||
|
||||
static enum mxdbg_status identify_task(
|
||||
struct mxdbg_host *host,
|
||||
const struct mxdbg_packet *packet)
|
||||
{
|
||||
struct mxdbg_packet_identify_task *req
|
||||
= (struct mxdbg_packet_identify_task *)packet;
|
||||
struct mxdbg_packet_identify_task id = {0};
|
||||
id.id_base = *packet;
|
||||
mxdbg_host_recv_packet_data(host, &id.id_base);
|
||||
unsigned int tid = id.id_task;
|
||||
|
||||
mxdbg_packet_init(
|
||||
&id.id_base,
|
||||
sizeof id,
|
||||
MXDBG_PACKET_IDENTIFY_TASK,
|
||||
MXDBG_PACKET_F_RESPONSE);
|
||||
|
||||
mxdbg_host_identify_task(
|
||||
host,
|
||||
tid,
|
||||
MXDBG_IDENTITY_TASK_NAME,
|
||||
id.id_task_name,
|
||||
sizeof id.id_task_name);
|
||||
mxdbg_host_identify_task(
|
||||
host,
|
||||
tid,
|
||||
MXDBG_IDENTITY_TASK_PARENT,
|
||||
&id.id_parent,
|
||||
sizeof id.id_parent);
|
||||
mxdbg_host_identify_task(
|
||||
host,
|
||||
tid,
|
||||
MXDBG_IDENTITY_TASK_NR_THREADS,
|
||||
&id.id_thread_count,
|
||||
sizeof id.id_thread_count);
|
||||
|
||||
size_t w;
|
||||
mxdbg_host_send(host, &id.id_base);
|
||||
debug_printf("debug: identify_task response sent");
|
||||
|
||||
return MXDBG_SUCCESS;
|
||||
}
|
||||
|
||||
static enum mxdbg_status resume(
|
||||
struct mxdbg_host *host,
|
||||
const struct mxdbg_packet *req)
|
||||
{
|
||||
return mxdbg_host_resume(host);
|
||||
}
|
||||
|
||||
enum mxdbg_status mxdbg_handle_request(
|
||||
struct mxdbg_host *host,
|
||||
const struct mxdbg_packet *req)
|
||||
{
|
||||
switch (req->pkt_type) {
|
||||
case MXDBG_PACKET_IDENTIFY_KERNEL:
|
||||
return identify_kernel(host, req);
|
||||
case MXDBG_PACKET_IDENTIFY_TASK:
|
||||
return identify_task(host, req);
|
||||
case MXDBG_PACKET_RESUME:
|
||||
return resume(host, req);
|
||||
default:
|
||||
debug_printf(
|
||||
"debug: unrecognised packet 0x%02x",
|
||||
req->pkt_type);
|
||||
return MXDBG_ERR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
return MXDBG_SUCCESS;
|
||||
}
|
||||
+323
@@ -0,0 +1,323 @@
|
||||
#include <kernel/ringbuf.h>
|
||||
#include <kernel/sched.h>
|
||||
#include <kernel/thread.h>
|
||||
#include <kernel/wait.h>
|
||||
#include <magenta/status.h>
|
||||
|
||||
#define BUF_LOCKED(buf) \
|
||||
(((buf)->buf_flags & (RINGBUF_READ_LOCKED | RINGBUF_WRITE_LOCKED)) != 0)
|
||||
|
||||
enum ringbuf_flags {
|
||||
RINGBUF_READ_LOCKED = 0x01u,
|
||||
RINGBUF_WRITE_LOCKED = 0x02u,
|
||||
};
|
||||
|
||||
kern_status_t ringbuf_lock(struct ringbuf *buf, unsigned long *flags)
|
||||
{
|
||||
spin_lock_irqsave(&buf->buf_lock, flags);
|
||||
return KERN_OK;
|
||||
}
|
||||
|
||||
kern_status_t ringbuf_unlock(struct ringbuf *buf, unsigned long flags)
|
||||
{
|
||||
spin_unlock_irqrestore(&buf->buf_lock, flags);
|
||||
return KERN_OK;
|
||||
}
|
||||
|
||||
static kern_status_t ringbuf_clear(struct ringbuf *buf)
|
||||
{
|
||||
buf->buf_read = buf->buf_write = 0;
|
||||
return KERN_OK;
|
||||
}
|
||||
|
||||
static size_t ringbuf_write_capacity_remaining(const struct ringbuf *buf)
|
||||
{
|
||||
if (buf->buf_read > buf->buf_write) {
|
||||
return buf->buf_read - buf->buf_write - 1;
|
||||
} else {
|
||||
return buf->buf_capacity - buf->buf_write + buf->buf_read - 1;
|
||||
}
|
||||
}
|
||||
|
||||
static size_t ringbuf_available_data_remaining(const struct ringbuf *buf)
|
||||
{
|
||||
if (buf->buf_read < buf->buf_write) {
|
||||
return buf->buf_write - buf->buf_read;
|
||||
} else if (buf->buf_read > buf->buf_write) {
|
||||
return buf->buf_capacity - buf->buf_read + buf->buf_write;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static kern_status_t ringbuf_open_read_buffer(
|
||||
struct ringbuf *buf,
|
||||
const void **ptr,
|
||||
size_t *length)
|
||||
{
|
||||
if (BUF_LOCKED(buf)) {
|
||||
return KERN_BUSY;
|
||||
}
|
||||
|
||||
size_t contiguous_capacity = 0;
|
||||
if (buf->buf_read > buf->buf_write) {
|
||||
contiguous_capacity = buf->buf_capacity - buf->buf_read;
|
||||
} else {
|
||||
contiguous_capacity = buf->buf_write - buf->buf_read;
|
||||
}
|
||||
|
||||
if (contiguous_capacity == 0) {
|
||||
return KERN_NO_DATA;
|
||||
}
|
||||
|
||||
buf->buf_opened_ptr = (unsigned char *)buf->buf_ptr + buf->buf_read;
|
||||
buf->buf_opened_capacity = contiguous_capacity;
|
||||
|
||||
buf->buf_flags |= RINGBUF_READ_LOCKED;
|
||||
*ptr = buf->buf_opened_ptr;
|
||||
*length = contiguous_capacity;
|
||||
|
||||
return KERN_OK;
|
||||
}
|
||||
|
||||
static kern_status_t ringbuf_close_read_buffer(
|
||||
struct ringbuf *buf,
|
||||
const void **ptr,
|
||||
size_t nbuf_read)
|
||||
{
|
||||
if (!(buf->buf_flags & RINGBUF_READ_LOCKED)) {
|
||||
return KERN_BAD_STATE;
|
||||
}
|
||||
|
||||
if (*ptr != buf->buf_opened_ptr) {
|
||||
return KERN_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
if (nbuf_read > buf->buf_opened_capacity) {
|
||||
return KERN_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
buf->buf_read += nbuf_read;
|
||||
if (buf->buf_read >= buf->buf_capacity) {
|
||||
buf->buf_read = 0;
|
||||
}
|
||||
|
||||
if (buf->buf_read == buf->buf_write) {
|
||||
/* the ringbuf is now empty. set both pointers to 0.
|
||||
* this ensures that the whole buffer will be available
|
||||
* contiguously to the next call to open_write_buffer */
|
||||
buf->buf_read = 0;
|
||||
buf->buf_write = 0;
|
||||
}
|
||||
|
||||
buf->buf_opened_ptr = NULL;
|
||||
buf->buf_opened_capacity = 0;
|
||||
buf->buf_flags &= ~RINGBUF_READ_LOCKED;
|
||||
|
||||
return KERN_OK;
|
||||
}
|
||||
|
||||
static kern_status_t ringbuf_open_write_buffer(
|
||||
struct ringbuf *buf,
|
||||
void **ptr,
|
||||
size_t *capacity)
|
||||
{
|
||||
if (BUF_LOCKED(buf)) {
|
||||
return KERN_BUSY;
|
||||
}
|
||||
|
||||
size_t contiguous_capacity = 0;
|
||||
if (buf->buf_write >= buf->buf_read) {
|
||||
contiguous_capacity = buf->buf_capacity - buf->buf_write - 1;
|
||||
|
||||
if (buf->buf_read > 0) {
|
||||
contiguous_capacity++;
|
||||
}
|
||||
} else {
|
||||
contiguous_capacity = buf->buf_read - buf->buf_write - 1;
|
||||
}
|
||||
|
||||
if (contiguous_capacity == 0) {
|
||||
return KERN_NO_SPACE;
|
||||
}
|
||||
|
||||
buf->buf_opened_ptr = (unsigned char *)buf->buf_ptr + buf->buf_write;
|
||||
buf->buf_opened_capacity = contiguous_capacity;
|
||||
|
||||
buf->buf_flags |= RINGBUF_WRITE_LOCKED;
|
||||
*ptr = buf->buf_opened_ptr;
|
||||
*capacity = contiguous_capacity;
|
||||
|
||||
return KERN_OK;
|
||||
}
|
||||
|
||||
static kern_status_t ringbuf_close_write_buffer(
|
||||
struct ringbuf *buf,
|
||||
void **ptr,
|
||||
size_t nbuf_written)
|
||||
{
|
||||
if (!(buf->buf_flags & RINGBUF_WRITE_LOCKED)) {
|
||||
return KERN_BAD_STATE;
|
||||
}
|
||||
|
||||
if (*ptr != buf->buf_opened_ptr) {
|
||||
return KERN_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
if (nbuf_written > buf->buf_opened_capacity) {
|
||||
return KERN_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
buf->buf_write += nbuf_written;
|
||||
if (buf->buf_write >= buf->buf_capacity) {
|
||||
buf->buf_write = 0;
|
||||
}
|
||||
|
||||
buf->buf_opened_ptr = NULL;
|
||||
buf->buf_opened_capacity = 0;
|
||||
buf->buf_flags &= ~RINGBUF_WRITE_LOCKED;
|
||||
|
||||
return KERN_OK;
|
||||
}
|
||||
|
||||
static void wait_for_data(struct ringbuf *buf, unsigned long *flags)
|
||||
{
|
||||
struct thread *self = get_current_thread();
|
||||
struct wait_item waiter;
|
||||
wait_item_init(&waiter, self);
|
||||
for (;;) {
|
||||
thread_wait_begin(&waiter, &buf->buf_read_queue);
|
||||
if (ringbuf_available_data_remaining(buf) > 0) {
|
||||
break;
|
||||
}
|
||||
ringbuf_unlock(buf, *flags);
|
||||
schedule(SCHED_NORMAL);
|
||||
ringbuf_lock(buf, flags);
|
||||
}
|
||||
thread_wait_end(&waiter, &buf->buf_read_queue);
|
||||
put_current_thread(self);
|
||||
}
|
||||
|
||||
static void wait_for_capacity(struct ringbuf *buf, unsigned long *flags)
|
||||
{
|
||||
struct thread *self = get_current_thread();
|
||||
struct wait_item waiter;
|
||||
wait_item_init(&waiter, self);
|
||||
for (;;) {
|
||||
thread_wait_begin(&waiter, &buf->buf_write_queue);
|
||||
if (ringbuf_write_capacity_remaining(buf) > 0) {
|
||||
break;
|
||||
}
|
||||
ringbuf_unlock(buf, *flags);
|
||||
schedule(SCHED_NORMAL);
|
||||
ringbuf_lock(buf, flags);
|
||||
}
|
||||
thread_wait_end(&waiter, &buf->buf_write_queue);
|
||||
put_current_thread(self);
|
||||
}
|
||||
|
||||
kern_status_t ringbuf_read(
|
||||
struct ringbuf *buf,
|
||||
void *p,
|
||||
size_t count,
|
||||
size_t *nbuf_read,
|
||||
unsigned long *irq_flags)
|
||||
{
|
||||
if (BUF_LOCKED(buf)) {
|
||||
return KERN_BUSY;
|
||||
}
|
||||
|
||||
size_t r = 0;
|
||||
unsigned char *dest = p;
|
||||
size_t remaining = count;
|
||||
kern_status_t status = KERN_OK;
|
||||
|
||||
while (remaining > 0) {
|
||||
const void *src;
|
||||
size_t available;
|
||||
wait_for_data(buf, irq_flags);
|
||||
|
||||
status = ringbuf_open_read_buffer(buf, &src, &available);
|
||||
|
||||
if (status != KERN_OK) {
|
||||
break;
|
||||
}
|
||||
|
||||
size_t to_copy = remaining;
|
||||
if (to_copy > available) {
|
||||
to_copy = available;
|
||||
}
|
||||
|
||||
memcpy(dest, src, to_copy);
|
||||
|
||||
remaining -= to_copy;
|
||||
dest += to_copy;
|
||||
r += to_copy;
|
||||
|
||||
ringbuf_close_read_buffer(buf, &src, to_copy);
|
||||
}
|
||||
|
||||
wakeup_queue(&buf->buf_write_queue);
|
||||
if (nbuf_read) {
|
||||
*nbuf_read = r;
|
||||
}
|
||||
|
||||
if (status == KERN_NO_DATA && r > 0) {
|
||||
status = KERN_OK;
|
||||
}
|
||||
|
||||
return KERN_OK;
|
||||
}
|
||||
|
||||
kern_status_t ringbuf_write(
|
||||
struct ringbuf *buf,
|
||||
const void *p,
|
||||
size_t count,
|
||||
size_t *nbuf_written,
|
||||
unsigned long *irq_flags)
|
||||
{
|
||||
if (BUF_LOCKED(buf)) {
|
||||
return KERN_BUSY;
|
||||
}
|
||||
|
||||
size_t w = 0;
|
||||
const unsigned char *src = p;
|
||||
size_t remaining = count;
|
||||
kern_status_t status = KERN_OK;
|
||||
|
||||
while (remaining > 0) {
|
||||
void *dest = NULL;
|
||||
size_t available = 0;
|
||||
wait_for_capacity(buf, irq_flags);
|
||||
|
||||
status = ringbuf_open_write_buffer(buf, &dest, &available);
|
||||
|
||||
if (status == KERN_NO_SPACE) {
|
||||
break;
|
||||
}
|
||||
|
||||
size_t to_copy = remaining;
|
||||
if (to_copy > available) {
|
||||
to_copy = available;
|
||||
}
|
||||
|
||||
memcpy(dest, src, to_copy);
|
||||
|
||||
remaining -= to_copy;
|
||||
src += to_copy;
|
||||
w += to_copy;
|
||||
|
||||
ringbuf_close_write_buffer(buf, &dest, to_copy);
|
||||
}
|
||||
|
||||
wakeup_queue(&buf->buf_read_queue);
|
||||
if (nbuf_written) {
|
||||
*nbuf_written = w;
|
||||
}
|
||||
|
||||
if (status == KERN_NO_SPACE && w > 0) {
|
||||
status = KERN_OK;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
@@ -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
|
||||
@@ -0,0 +1,45 @@
|
||||
#ifndef KERNEL_RINGBUF_H_
|
||||
#define KERNEL_RINGBUF_H_
|
||||
|
||||
#include <kernel/wait.h>
|
||||
#include <magenta/types.h>
|
||||
|
||||
struct ringbuf {
|
||||
unsigned int buf_read;
|
||||
unsigned int buf_write;
|
||||
unsigned int buf_capacity;
|
||||
|
||||
unsigned int buf_flags;
|
||||
unsigned char *buf_ptr;
|
||||
struct waitqueue buf_read_queue;
|
||||
struct waitqueue buf_write_queue;
|
||||
spin_lock_t buf_lock;
|
||||
|
||||
unsigned char *buf_opened_ptr;
|
||||
unsigned int buf_opened_capacity;
|
||||
};
|
||||
|
||||
#define RINGBUF_DECLARE(name, size) \
|
||||
static unsigned char __buf_##name[size] = {0}; \
|
||||
static struct ringbuf name = { \
|
||||
.buf_ptr = __buf_##name, \
|
||||
.buf_capacity = size, \
|
||||
}
|
||||
|
||||
extern kern_status_t ringbuf_lock(struct ringbuf *buf, unsigned long *flags);
|
||||
extern kern_status_t ringbuf_unlock(struct ringbuf *buf, unsigned long flags);
|
||||
|
||||
extern kern_status_t ringbuf_read(
|
||||
struct ringbuf *buf,
|
||||
void *out,
|
||||
size_t count,
|
||||
size_t *nr_read,
|
||||
unsigned long *irq_flags);
|
||||
extern kern_status_t ringbuf_write(
|
||||
struct ringbuf *buf,
|
||||
const void *out,
|
||||
size_t count,
|
||||
size_t *nr_written,
|
||||
unsigned long *irq_flags);
|
||||
|
||||
#endif
|
||||
+1
-1
@@ -23,7 +23,7 @@ extern char __pstart[], __pend[];
|
||||
|
||||
void print_kernel_banner(void)
|
||||
{
|
||||
printk("Magenta kernel version " BUILD_ID);
|
||||
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;
|
||||
}
|
||||
+1
-1
@@ -17,7 +17,7 @@ void panic_irq(struct ml_cpu_context *ctx, const char *fmt, ...)
|
||||
va_end(args);
|
||||
|
||||
printk("---[ kernel panic: %s", buf);
|
||||
printk("kernel: " BUILD_ID ", compiler version: " __VERSION__);
|
||||
printk("kernel: " KERNEL_VERSION ", compiler version: " __VERSION__);
|
||||
|
||||
struct task *task = get_current_task();
|
||||
struct thread *thr = get_current_thread();
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
file(GLOB headers ${CMAKE_CURRENT_SOURCE_DIR}/include/magenta/*.h)
|
||||
cmake_minimum_required(VERSION 3.31)
|
||||
project(libmagenta C ASM)
|
||||
|
||||
file(GLOB headers
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/include/magenta/*.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/include-user/magenta/*.h)
|
||||
file(GLOB asm_sources
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/arch/${CMAKE_SYSTEM_PROCESSOR}/*.S)
|
||||
|
||||
@@ -6,7 +11,14 @@ set(public_include_dirs
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/include
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/include-user)
|
||||
|
||||
add_library(libmagenta STATIC ${asm_sources})
|
||||
add_library(libmagenta STATIC ${asm_sources} ${headers})
|
||||
target_include_directories(libmagenta PUBLIC
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/include
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/include-user)
|
||||
target_compile_options(libmagenta PRIVATE -ffreestanding -nostdlib)
|
||||
|
||||
set_target_properties(libmagenta PROPERTIES
|
||||
PREFIX "")
|
||||
|
||||
install(TARGETS libmagenta)
|
||||
install(FILES ${headers} DESTINATION include/magenta)
|
||||
|
||||
@@ -17,5 +17,7 @@
|
||||
#define KERN_BAD_STATE (13)
|
||||
#define KERN_MEMORY_FAULT (14)
|
||||
#define KERN_ACCESS_DENIED (15)
|
||||
#define KERN_NO_DATA (16)
|
||||
#define KERN_NO_SPACE (17)
|
||||
|
||||
#endif
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
file(GLOB sources *.c *.h)
|
||||
|
||||
add_executable(e64patch ${sources})
|
||||
|
||||
install(TARGETS e64patch)
|
||||
|
||||
@@ -33,7 +33,7 @@ if is_arg_set('release'):
|
||||
build_type = 'release'
|
||||
|
||||
current_tag = subprocess.check_output(['git', 'describe', '--tags', '--abbrev=0']).decode('utf-8').strip()
|
||||
current_tag = current_tag[1:]
|
||||
revision = subprocess.check_output(['git', 'rev-list', '{}..HEAD'.format(current_tag), '--count']).decode('utf-8').strip()
|
||||
|
||||
build_id = '{}/{}_{}'.format(current_tag, build_type, arch)
|
||||
build_id = '{}~{}/{}_{}'.format(current_tag[1:], revision, build_type, arch)
|
||||
print('{}'.format(build_id.upper()))
|
||||
|
||||
@@ -105,11 +105,9 @@ static size_t zone_free_bytes(struct vm_zone *z)
|
||||
for (enum vm_page_order i = VM_PAGE_MIN_ORDER; i <= VM_PAGE_MAX_ORDER;
|
||||
i++) {
|
||||
size_t page_bytes = vm_page_order_to_bytes(i);
|
||||
size_t nr_pages = 0;
|
||||
queue_foreach(struct vm_page, pg, &z->z_free_pages[i], p_list)
|
||||
{
|
||||
free_bytes += page_bytes;
|
||||
nr_pages++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user