From a69dbc3c7ab8cae2c9079c7fda6692fcb109b1db Mon Sep 17 00:00:00 2001 From: Benji Dial Date: Thu, 1 Jan 2026 00:05:11 -0500 Subject: [PATCH] rename src/kernel/panic to src/kernel/debug, add serial logging --- compile_flags.txt | 2 + make-build.sh | 12 ++-- src/kernel/debug.c | 109 +++++++++++++++++++++++++++++++ src/kernel/{panic.h => debug.h} | 21 ++++-- src/kernel/entry.c | 13 +++- src/kernel/fs.c | 2 +- src/kernel/input.c | 2 +- src/kernel/interrupts.c | 2 +- src/kernel/ipc-dgram.c | 2 +- src/kernel/iso9660.c | 9 ++- src/kernel/paging.c | 19 +++++- src/kernel/paging.h | 6 ++ src/kernel/pata.c | 12 +++- src/kernel/pci.c | 2 + src/kernel/process.c | 14 +++- src/kernel/scheduler.c | 2 +- src/kernel/serial.asm | 73 +++++++++++++++++++++ src/kernel/serial.c | 54 +++++++++++++++ src/kernel/{panic.c => serial.h} | 20 +++--- src/kernel/syscalls.c | 2 +- 20 files changed, 344 insertions(+), 34 deletions(-) create mode 100644 src/kernel/debug.c rename src/kernel/{panic.h => debug.h} (63%) create mode 100644 src/kernel/serial.asm create mode 100644 src/kernel/serial.c rename src/kernel/{panic.c => serial.h} (71%) diff --git a/compile_flags.txt b/compile_flags.txt index fce5308..eb64b69 100644 --- a/compile_flags.txt +++ b/compile_flags.txt @@ -4,3 +4,5 @@ dependencies/limine -I include +-D +CALCITE_DEBUG diff --git a/make-build.sh b/make-build.sh index a6fb0c2..3630d18 100644 --- a/make-build.sh +++ b/make-build.sh @@ -3,23 +3,23 @@ COMMON_CC_EXTRA_FLAGS="-Wall -Wextra" COMMON_LD_EXTRA_FLAGS="" +COMMON_CC_FLAGS="-std=c23 -ffreestanding -I include ${COMMON_CC_EXTRA_FLAGS}" +COMMON_LD_FLAGS="${COMMON_LD_EXTRA_FLAGS}" + if [ "$1" = debug ]; then - COMMON_CC_EXTRA_FLAGS="-O0 -ggdb ${COMMON_CC_EXTRA_FLAGS}" + COMMON_CC_FLAGS="-O0 -ggdb -D CALCITE_DEBUG ${COMMON_CC_FLAGS}" elif [ "$1" = release ]; then - COMMON_CC_EXTRA_FLAGS="-O3 ${COMMON_CC_EXTRA_FLAGS}" - COMMON_LD_EXTRA_FLAGS="-s ${COMMON_LD_EXTRA_FLAGS}" + COMMON_CC_FLAGS="-O3 -D CALCITE_RELEASE ${COMMON_CC_FLAGS}" + COMMON_LD_FLAGS="-s ${COMMON_LD_FLAGS}" else echo pass either "debug" or "release" as an argument. exit fi -COMMON_CC_FLAGS="-std=c23 -ffreestanding -I include ${COMMON_CC_EXTRA_FLAGS}" KERNEL_CC_FLAGS="-mno-sse -I dependencies/limine ${COMMON_CC_FLAGS}" #in the future user code will be allowed to use sse USER_CC_FLAGS="-mno-sse ${COMMON_CC_FLAGS}" -COMMON_LD_FLAGS="${COMMON_LD_EXTRA_FLAGS}" - if [ -e build.ninja ]; then echo build.ninja already exists. exit diff --git a/src/kernel/debug.c b/src/kernel/debug.c new file mode 100644 index 0000000..72ad60f --- /dev/null +++ b/src/kernel/debug.c @@ -0,0 +1,109 @@ +/* Calcite, src/kernel/debug.c + * Copyright 2025 Benji Dial + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + */ + +#include "serial.h" +#include "debug.h" + +#include + +void log_core(const char *file, const char *function, const char *format, ...) { + + int file_length = 0; + while (file[file_length] != 0) + ++file_length; + + int function_length = 0; + while (function[function_length] != 0) + ++function_length; + + write_serial_string_n(file, file_length); + write_serial_string_n(" ", 1); + write_serial_string_n(function, function_length); + + write_serial_string_n(" -", 2); + for (int i = file_length + function_length + 3; i < 49; ++i) + write_serial_string_n("-", 1); + write_serial_string_n(" ", 1); + + va_list args; + va_start(args, format); + + while (1) { + + int next_percent = 0; + while (format[next_percent] != '%') { + if (format[next_percent] == 0) { + write_serial_string_n(format, next_percent); + va_end(args); + write_serial_string_n("\r\n", 2); + return; + } + ++next_percent; + } + + write_serial_string_n(format, next_percent); + + switch (format[next_percent + 1]) { + case 's': { + const char *arg = va_arg(args, const char *); + write_serial_string(arg); + break; + } + case 'd': { + int arg = va_arg(args, int); + write_serial_integer(arg); + break; + } + case 'h': { + uint64_t arg1 = va_arg(args, uint64_t); + int arg2 = va_arg(args, int); + write_serial_hex(arg1, arg2); + break; + } + case 'B': { + uint64_t arg = va_arg(args, uint64_t); + if (arg < 10000) { + write_serial_integer(arg); + write_serial_string_n(" B", 2); + } + else if ((arg + 512) / 1024 < 10000) { + write_serial_integer((arg + 512) / 1024); + write_serial_string_n(" kiB", 4); + } + else if ((arg + 512 * 1024) / (1024 * 1024) < 10000) { + write_serial_integer((arg + 512 * 1024) / (1024 * 1024)); + write_serial_string_n(" MiB", 4); + } + else if ((arg + 512 * 1024 * 1024) / (1024 * 1024 * 1024) < 10000) { + write_serial_integer((arg + 512 * 1024 * 1024) / (1024 * 1024 * 1024)); + write_serial_string_n(" GiB", 4); + } + else { + write_serial_integer((arg + 512 * 1024 * 1024 * 1024ULL) / (1024 * 1024 * 1024 * 1024ULL)); + write_serial_string_n(" TiB", 4); + } + break; + } + default: + panic("bad format string") + } + + format = &format[next_percent + 2]; + + } + +} diff --git a/src/kernel/panic.h b/src/kernel/debug.h similarity index 63% rename from src/kernel/panic.h rename to src/kernel/debug.h index fbd1626..82f80d4 100644 --- a/src/kernel/panic.h +++ b/src/kernel/debug.h @@ -1,4 +1,4 @@ -/* Calcite, src/kernel/panic.h +/* Calcite, src/kernel/debug.h * Copyright 2025 Benji Dial * * This program is free software: you can redistribute it and/or modify @@ -17,10 +17,23 @@ #pragma once -[[noreturn]] void panic_core( - const char *file, const char *function, int line, const char *message); +void log_core(const char *file, const char *function, const char *format, ...); -#define panic(message) panic_core(__FILE__, __func__, __LINE__, message); +#ifdef CALCITE_DEBUG +#define debug_log(...) { \ + log_core(__FILE__, __func__, __VA_ARGS__); \ +} +#elif CALCITE_RELEASE +#define debug_log(format, ...) {} +#else +#error neither CALCITE_DEBUG nor CALCITE_RELEASE defined +#endif + +#define panic(message) { \ + log_core(__FILE__, __func__, "kernel panic: %s", message); \ + while (1) \ + __asm__ ("hlt"); \ +} #define assert(condition) \ { \ diff --git a/src/kernel/entry.c b/src/kernel/entry.c index 1382190..b725c2d 100644 --- a/src/kernel/entry.c +++ b/src/kernel/entry.c @@ -23,8 +23,9 @@ #include "utility.h" #include "drives.h" #include "paging.h" +#include "serial.h" +#include "debug.h" #include "input.h" -#include "panic.h" #include "timer.h" #include "heap.h" #include "pci.h" @@ -187,6 +188,8 @@ static const char *cmdline_look_up(const char *key) { [[noreturn]] static void with_kernel_page_tables() { + init_serial(); + //store cmdline as key-value pairs if (cmdline_copy[0] == 0) @@ -242,6 +245,10 @@ static const char *cmdline_look_up(const char *key) { } + debug_log("command line:") + for (int i = 0; i < cmdline_pair_count; ++i) + debug_log(" %s = %s", cmdline_pairs[i].key, cmdline_pairs[i].value) + //set up interrupts init_timer(); @@ -302,6 +309,10 @@ static const char *cmdline_look_up(const char *key) { if (start_elf("root://calcite/apps/init/init.elf") == 0) panic("could not start init.elf") + debug_log("about to switch to init") + debug_log(" free physical memory %B", count_free_pram()) + debug_log(" free kernel virtual memory %B", count_free_kernel_vram()) + resume_next_continuation(); } diff --git a/src/kernel/fs.c b/src/kernel/fs.c index b13a0eb..0270dc6 100644 --- a/src/kernel/fs.c +++ b/src/kernel/fs.c @@ -17,7 +17,7 @@ #include "iso9660.h" #include "utility.h" -#include "panic.h" +#include "debug.h" #include "heap.h" #include "fs.h" diff --git a/src/kernel/input.c b/src/kernel/input.c index 0913696..93e9841 100644 --- a/src/kernel/input.c +++ b/src/kernel/input.c @@ -17,8 +17,8 @@ #include "scheduler.h" #include "process.h" +#include "debug.h" #include "input.h" -#include "panic.h" static int is_somebody_waiting_for_mouse_packet = 0; static struct continuation_info waiting_continuation; diff --git a/src/kernel/interrupts.c b/src/kernel/interrupts.c index 9792863..c10326f 100644 --- a/src/kernel/interrupts.c +++ b/src/kernel/interrupts.c @@ -22,7 +22,7 @@ // https://osdev.wiki/wiki/Task_State_Segment #include "interrupts.h" -#include "panic.h" +#include "debug.h" struct [[gnu::packed]] exception_parameter { uint64_t r15; diff --git a/src/kernel/ipc-dgram.c b/src/kernel/ipc-dgram.c index 3472b26..083a09c 100644 --- a/src/kernel/ipc-dgram.c +++ b/src/kernel/ipc-dgram.c @@ -18,7 +18,7 @@ #include "ipc-dgram.h" #include "scheduler.h" #include "utility.h" -#include "panic.h" +#include "debug.h" #include "heap.h" #include diff --git a/src/kernel/iso9660.c b/src/kernel/iso9660.c index 6e7b83f..b89c070 100644 --- a/src/kernel/iso9660.c +++ b/src/kernel/iso9660.c @@ -16,9 +16,10 @@ */ #include "iso9660.h" +#include "kernel-public/files.h" #include "utility.h" #include "drives.h" -#include "panic.h" +#include "debug.h" #include "heap.h" #include "fs.h" @@ -370,6 +371,12 @@ enum fs_access_result create_iso9660_info(const struct drive_info *drive, struct fs_out->look_up_file = &look_up_file_iso9660; fs_out->stat_file = &stat_file_iso9660; fs_out->read_file = &read_file_iso9660; + + debug_log("created iso9660 file system") + debug_log(" drive name %s", drive->name) + debug_log(" path table start block %d", path_table_start) + debug_log(" path table block count %d", path_table_length_rounded_up / 2048) + return FAR_SUCCESS; } diff --git a/src/kernel/paging.c b/src/kernel/paging.c index 5783fbb..66c16c7 100644 --- a/src/kernel/paging.c +++ b/src/kernel/paging.c @@ -16,7 +16,7 @@ */ #include "paging.h" -#include "panic.h" +#include "debug.h" #define MAX_PHYSICAL_GB 64ULL @@ -203,3 +203,20 @@ void destroy_syscall_stack(void *stack_top) { for (uint64_t i = 0; i < SYSCALL_STACK_BYTES; i += 4096) unmap_and_free_kernel_page(stack_top - SYSCALL_STACK_BYTES + i * 4096); } + +uint64_t count_free_pram() { + uint64_t total = 0; + for (uint64_t i = 0; i < (MAX_PHYSICAL_GB << 15); ++i) + for (int j = 0; j < 8; ++j) + if (physical_map[i] & (1 << j)) + total += 4096; + return total; +} + +uint64_t count_free_kernel_vram() { + uint64_t total = 0; + for (uint64_t i = 0; i < 512 * 512; ++i) + if (kernel_p1s[i] == 0) + total += 4096; + return total; +} diff --git a/src/kernel/paging.h b/src/kernel/paging.h index f7bf4c4..eaee047 100644 --- a/src/kernel/paging.h +++ b/src/kernel/paging.h @@ -52,3 +52,9 @@ uint64_t take_free_physical_page(); //returns the top void *create_syscall_stack(); void destroy_syscall_stack(void *stack_top); + +//return value in bytes +uint64_t count_free_pram(); + +//return value in bytes +uint64_t count_free_kernel_vram(); diff --git a/src/kernel/pata.c b/src/kernel/pata.c index 4b1e496..b005b2d 100644 --- a/src/kernel/pata.c +++ b/src/kernel/pata.c @@ -15,12 +15,12 @@ * with this program. If not, see . */ -#include "pci.h" #include "utility.h" #include "drives.h" -#include "panic.h" +#include "debug.h" #include "heap.h" #include "pata.h" +#include "pci.h" //some relevant sources: // https://www.isdaman.com/alsos/hardware/hdc/pciide.pdf @@ -211,6 +211,14 @@ static void probe_pata_drive(uint16_t command_block_base, uint8_t device_byte) { di->read_blocks = &read_blocks_patapi; + debug_log("added pata drive:") + debug_log(" drive name %s", di->name) + debug_log(" command block base 0x%h", command_block_base, 4) + debug_log(" device byte 0x%h", device_byte, 2) + debug_log(" block size %d", di->block_size) + debug_log(" block count %d", di->block_count) + debug_log(" total size %B", di->block_count * di->block_size) + } void probe_pata_drives(uint32_t pci_address_base, uint32_t pci_class_etc) { diff --git a/src/kernel/pci.c b/src/kernel/pci.c index 1f6eed1..ac705f5 100644 --- a/src/kernel/pci.c +++ b/src/kernel/pci.c @@ -15,6 +15,7 @@ * with this program. If not, see . */ +#include "debug.h" #include "pata.h" #include "pci.h" @@ -40,6 +41,7 @@ static void probe_bus(uint32_t bus_address_base) { else if ((header_type & 0x7f) == 0x00) { //this is a normal function uint32_t class_etc = read_pci_config(function_address_base | 0x08); + debug_log("pci device with class %h:%h", class_etc >> 24, 2, class_etc >> 16, 2); switch (class_etc & 0xffff0000) { case 0x01010000: probe_pata_drives(function_address_base, class_etc); diff --git a/src/kernel/process.c b/src/kernel/process.c index 6867c4b..73a696c 100644 --- a/src/kernel/process.c +++ b/src/kernel/process.c @@ -21,7 +21,7 @@ #include "process.h" #include "utility.h" #include "paging.h" -#include "panic.h" +#include "debug.h" #include "heap.h" #include "fs.h" @@ -399,6 +399,12 @@ void syscall_create_thread(void (*f)(uint64_t), uint64_t x) { add_to_queue(&ready_continuations, &ci); + debug_log("started thread") + debug_log(" process struct at 0xffffffff.%h", thread->process, 8) + debug_log(" thread struct at 0xffffffff.%h", thread, 8) + debug_log(" free physical memory %B", count_free_pram()) + debug_log(" free kernel virtual memory %B", count_free_kernel_vram()) + } int syscall_start_elf(const char *path, const struct process_start_info *info) { @@ -439,6 +445,12 @@ int syscall_start_elf(const char *path, const struct process_start_info *info) { for (int i = 0; i < info->set_envvar_count; ++i) set_envvar(process, info->set_envvars[2 * i], info->set_envvars[2 * i + 1]); + debug_log("started process") + debug_log(" path %s", path) + debug_log(" process struct at 0xffffffff.%h", process, 8) + debug_log(" free physical memory %B", count_free_pram()) + debug_log(" free kernel virtual memory %B", count_free_kernel_vram()) + return 1; } diff --git a/src/kernel/scheduler.c b/src/kernel/scheduler.c index 6fa825c..ccaa8a6 100644 --- a/src/kernel/scheduler.c +++ b/src/kernel/scheduler.c @@ -18,7 +18,7 @@ #include "scheduler.h" #include "process.h" #include "utility.h" -#include "panic.h" +#include "debug.h" #include "heap.h" struct continuation_queue ready_continuations; diff --git a/src/kernel/serial.asm b/src/kernel/serial.asm new file mode 100644 index 0000000..c9ddc1e --- /dev/null +++ b/src/kernel/serial.asm @@ -0,0 +1,73 @@ + ; Calcite, src/kernel/serial.asm + ; Copyright 2025 Benji Dial + ; + ; This program is free software: you can redistribute it and/or modify + ; it under the terms of the GNU General Public License as published by + ; the Free Software Foundation, either version 3 of the License, or + ; (at your option) any later version. + ; + ; This program is distributed in the hope that it will be useful, but + ; WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + ; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + ; for more details. + ; + ; You should have received a copy of the GNU General Public License along + ; with this program. If not, see . + + +bits 64 +default rel + +section .text + +global init_serial +init_serial: + mov dx, 0x03f9 + mov al, 0x00 + out dx, al + + mov dl, 0xfb + mov al, 0x80 + out dx, al + + mov dl, 0xf8 + mov al, 0x03 + out dx, al + + mov dl, 0xf9 + mov al, 0x00 + out dx, al + + mov dl, 0xfb + mov al, 0x03 + out dx, al + + mov dl, 0xfa + mov al, 0xc7 + out dx, al + + ret + +global write_serial_string_n +write_serial_string_n: + test esi, esi + jz .ret + movzx rcx, esi + +.wait_ready: + mov dx, 0x03fd + in al, dx + test al, 0x20 + jnz .ready + pause + jmp .wait_ready + +.ready: + mov dl, 0xf8 + mov al, byte [rdi] + out dx, al + + inc rdi + loop .wait_ready +.ret: + ret diff --git a/src/kernel/serial.c b/src/kernel/serial.c new file mode 100644 index 0000000..0c9f4de --- /dev/null +++ b/src/kernel/serial.c @@ -0,0 +1,54 @@ +/* Calcite, src/kernel/serial.c + * Copyright 2025 Benji Dial + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + */ + +#include "serial.h" +#include "debug.h" + +void write_serial_string(const char *string) { + int n = 0; + while (string[n] != 0) + ++n; + write_serial_string_n(string, n); +} + +void write_serial_integer(int integer) { + + if (integer == 0) { + write_serial_string_n("0", 1); + return; + } + + char buffer[10]; + char *ptr = &buffer[9]; + + while (integer != 0) { + *ptr = '0' + integer % 10; + integer /= 10; + --ptr; + } + + write_serial_string_n(ptr + 1, (buffer + 10) - (ptr + 1)); + +} + +void write_serial_hex(uint64_t value, int places) { + assert(places <= 16) + char buffer[16]; + for (int i = 0; i < places; ++i) + buffer[i] = "0123456789abcdef"[(value >> (4 * (places - i - 1))) & 0xf]; + write_serial_string_n(buffer, places); +} diff --git a/src/kernel/panic.c b/src/kernel/serial.h similarity index 71% rename from src/kernel/panic.c rename to src/kernel/serial.h index 74844dd..a70cfdf 100644 --- a/src/kernel/panic.c +++ b/src/kernel/serial.h @@ -1,4 +1,4 @@ -/* Calcite, src/kernel/panic.c +/* Calcite, src/kernel/serial.h * Copyright 2025 Benji Dial * * This program is free software: you can redistribute it and/or modify @@ -15,16 +15,12 @@ * with this program. If not, see . */ -[[noreturn]] void panic_core( - const char *file, const char *function, int line, const char *message) { +#pragma once - //TODO +#include - (void)file; - (void)function; - (void)line; - (void)message; - while (1) - __asm__ ("hlt"); - -} +void init_serial(); +void write_serial_string(const char *string); +void write_serial_string_n(const char *string, int n); +void write_serial_integer(int integer); +void write_serial_hex(uint64_t value, int places); diff --git a/src/kernel/syscalls.c b/src/kernel/syscalls.c index 18e6124..8132dfd 100644 --- a/src/kernel/syscalls.c +++ b/src/kernel/syscalls.c @@ -16,7 +16,7 @@ */ #include "syscalls.h" -#include "panic.h" +#include "debug.h" #define MAX_SYSCALL_NUMBER 99