From af0d97d6f5cfb631c863ce2a0fae7bbc8852fd35 Mon Sep 17 00:00:00 2001 From: Max Wash Date: Tue, 3 Feb 2026 21:28:15 +0000 Subject: [PATCH] misc: changes from a long time ago --- CMakeLists.txt | 9 +- arch/x86_64/init.c | 7 +- arch/x86_64/pmap.c | 108 ++++++++++++++--------- arch/x86_64/ports.c | 55 +++++++----- arch/x86_64/targets.cmake | 14 +++ arch/x86_64/toolchain.cmake | 2 + arch/x86_64/vga.c | 126 +++++++++++++++++++++++++++ tools/kernel-debug/debug_session.sh | 15 ++-- tools/kernel-debug/gdb_session_init | 2 +- tools/kernel-debug/lldb_session_init | 2 +- 10 files changed, 266 insertions(+), 74 deletions(-) create mode 100644 arch/x86_64/vga.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 1a7c191..27684fc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -45,7 +45,14 @@ target_include_directories(${kernel_exe_name} PRIVATE target_compile_options(${kernel_exe_name} PRIVATE -nostdlib -ffreestanding -Wall -Werror -pedantic -Wno-language-extension-token -Wno-unused-function -Wno-gnu-statement-expression - -O2 -g -fPIC -Iinclude -Iarch/${kernel_arch}/include -Ilibc/include) + -g -fPIC -Iinclude -Iarch/${kernel_arch}/include -Ilibc/include) + +add_custom_command( + TARGET ${kernel_exe_name} + POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy $ $.debug + COMMAND ${CMAKE_STRIP} -g $) + target_link_libraries(${kernel_exe_name} -nostdlib -ffreestanding -lgcc) target_compile_definitions(${kernel_exe_name} PRIVATE BUILD_ID="0") diff --git a/arch/x86_64/init.c b/arch/x86_64/init.c index 70de4de..84316d8 100644 --- a/arch/x86_64/init.c +++ b/arch/x86_64/init.c @@ -1,7 +1,7 @@ -#include "arch/serial.h" - #include #include +#include +#include #include #include #include @@ -52,11 +52,12 @@ void early_console_init(void) { const char *dest = arg_value("kernel.early-console"); if (!dest) { - dest = "ttyS0"; + dest = "tty0"; } if (!strcmp(dest, "tty0")) { /* show log messages on VGA */ + vgacon_init(); } else if (!strcmp(dest, "ttyS0")) { /* write log messages to serial port */ early_serialcon_init(115200); diff --git a/arch/x86_64/pmap.c b/arch/x86_64/pmap.c index 3a358c7..acc9a7b 100644 --- a/arch/x86_64/pmap.c +++ b/arch/x86_64/pmap.c @@ -1,20 +1,20 @@ -#include +#include #include -#include +#include #include #include -#include -#include +#include +#include /* some helpful datasize constants */ -#define C_1GiB 0x40000000ULL -#define C_2GiB (2 * C_1GiB) +#define C_1GiB 0x40000000ULL +#define C_2GiB (2 * C_1GiB) -#define BAD_INDEX ((unsigned int)-1) +#define BAD_INDEX ((unsigned int)-1) #define PTR_TO_ENTRY(x) (((x) & ~VM_PAGE_MASK) | PTE_PRESENT | PTE_RW) #define ENTRY_TO_PTR(x) ((x) & ~VM_PAGE_MASK) -#define PFN(x) ((x) >> VM_PAGE_SHIFT) +#define PFN(x) ((x) >> VM_PAGE_SHIFT) static int can_use_gbpages = 0; static pmap_t kernel_pmap; @@ -33,7 +33,7 @@ static size_t ps_size(enum page_size ps) } } -static pmap_t alloc_pmap() +static pmap_t alloc_pmap(void) { struct pml4t *p = kzalloc(sizeof *p, 0); return vm_virt_to_phys(p); @@ -45,12 +45,14 @@ static pte_t make_pte(pfn_t pfn, enum vm_prot prot, enum page_size size) switch (size) { case PS_1G: - /* pfn_t is in terms of 4KiB pages, convert to 1GiB page frame number */ + /* pfn_t is in terms of 4KiB pages, convert to 1GiB page frame + * number */ pfn >>= 18; v = (pfn & 0x3FFFFF) << 30; break; case PS_2M: - /* pfn_t is in terms of 4KiB pages, convert to 2MiB page frame number */ + /* pfn_t is in terms of 4KiB pages, convert to 2MiB page frame + * number */ pfn >>= 9; v = (pfn & 0x7FFFFFFF) << 21; break; @@ -129,14 +131,16 @@ static void delete_pdir(phys_addr_t pd) kfree(pdir); } -static kern_status_t do_pmap_add(pmap_t pmap, void *p, pfn_t pfn, enum vm_prot prot, enum page_size size) +static kern_status_t do_pmap_add( + pmap_t pmap, + void *p, + pfn_t pfn, + enum vm_prot prot, + enum page_size size) { uintptr_t pv = (uintptr_t)p; - unsigned int - pml4t_index = BAD_INDEX, - pdpt_index = BAD_INDEX, - pd_index = BAD_INDEX, - pt_index = BAD_INDEX; + unsigned int pml4t_index = BAD_INDEX, pdpt_index = BAD_INDEX, + pd_index = BAD_INDEX, pt_index = BAD_INDEX; switch (size) { case PS_4K: @@ -171,16 +175,19 @@ static kern_status_t do_pmap_add(pmap_t pmap, void *p, pfn_t pfn, enum vm_prot p struct pdpt *pdpt = NULL; if (!pml4t->p_entries[pml4t_index]) { pdpt = kzalloc(sizeof *pdpt, 0); - pml4t->p_entries[pml4t_index] = PTR_TO_ENTRY(vm_virt_to_phys(pdpt)); + pml4t->p_entries[pml4t_index] + = PTR_TO_ENTRY(vm_virt_to_phys(pdpt)); } else { - pdpt = vm_phys_to_virt(ENTRY_TO_PTR(pml4t->p_entries[pml4t_index])); + pdpt = vm_phys_to_virt( + ENTRY_TO_PTR(pml4t->p_entries[pml4t_index])); } /* if we're mapping a 1GiB page, we stop here */ if (size == PS_1G) { if (pdpt->p_entries[pdpt_index] != 0) { /* this slot points to a pdir, delete it. - if this slot points to a hugepage, this does nothing */ + if this slot points to a hugepage, this does nothing + */ delete_pdir(pdpt->p_entries[pdpt_index]); } @@ -189,22 +196,25 @@ static kern_status_t do_pmap_add(pmap_t pmap, void *p, pfn_t pfn, enum vm_prot p return KERN_OK; } - /* 3. traverse PDPT, get PDIR (optional, 4K and 2M only) */ struct pdir *pdir = NULL; - if (!pdpt->p_entries[pdpt_index] || pdpt->p_pages[pdpt_index] & PTE_PAGESIZE) { + if (!pdpt->p_entries[pdpt_index] + || pdpt->p_pages[pdpt_index] & PTE_PAGESIZE) { /* entry is null, or points to a hugepage */ pdir = kzalloc(sizeof *pdir, 0); - pdpt->p_entries[pdpt_index] = PTR_TO_ENTRY(vm_virt_to_phys(pdir)); + pdpt->p_entries[pdpt_index] + = PTR_TO_ENTRY(vm_virt_to_phys(pdir)); } else { - pdir = vm_phys_to_virt(ENTRY_TO_PTR(pdpt->p_entries[pdpt_index])); + pdir = vm_phys_to_virt( + ENTRY_TO_PTR(pdpt->p_entries[pdpt_index])); } /* if we're mapping a 2MiB page, we stop here */ if (size == PS_2M) { if (pdir->p_entries[pd_index] != 0) { /* this slot points to a ptab, delete it. - if this slot points to a hugepage, this does nothing */ + if this slot points to a hugepage, this does nothing + */ delete_ptab(pdir->p_entries[pd_index]); } @@ -214,7 +224,8 @@ static kern_status_t do_pmap_add(pmap_t pmap, void *p, pfn_t pfn, enum vm_prot p /* 4. traverse PDIR, get PTAB (optional, 4K only) */ struct ptab *ptab = NULL; - if (!pdir->p_entries[pd_index] || pdir->p_pages[pd_index] & PTE_PAGESIZE) { + if (!pdir->p_entries[pd_index] + || pdir->p_pages[pd_index] & PTE_PAGESIZE) { /* entry is null, or points to a hugepage */ ptab = kzalloc(sizeof *ptab, 0); pdir->p_entries[pd_index] = PTR_TO_ENTRY(vm_virt_to_phys(ptab)); @@ -234,7 +245,8 @@ pmap_t get_kernel_pmap(void) void pmap_bootstrap(void) { can_use_gbpages = gigabyte_pages(); - printk("pmap: gigabyte pages %sabled", can_use_gbpages == 1 ? "en" : "dis"); + printk("pmap: gigabyte pages %sabled", + can_use_gbpages == 1 ? "en" : "dis"); enable_nx(); printk("pmap: NX protection enabled"); @@ -251,16 +263,19 @@ void pmap_bootstrap(void) the kernel and memblock-allocated data. */ uintptr_t vbase = VM_KERNEL_VOFFSET; for (size_t i = 0; i < C_2GiB; i += hugepage_sz) { - do_pmap_add(kernel_pmap, - (void *)(vbase + i), - PFN(i), - VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXEC | VM_PROT_SVR, - hugepage); + do_pmap_add( + kernel_pmap, + (void *)(vbase + i), + PFN(i), + VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXEC + | VM_PROT_SVR, + hugepage); } phys_addr_t pmem_limit = 0x0; struct memblock_iter it; - for_each_mem_range(&it, 0x00, UINTPTR_MAX) { + for_each_mem_range(&it, 0x00, UINTPTR_MAX) + { if (it.it_limit > pmem_limit) { pmem_limit = it.it_limit; } @@ -268,10 +283,13 @@ void pmap_bootstrap(void) vbase = VM_PAGEMAP_BASE; for (size_t i = 0; i < pmem_limit; i += hugepage_sz) { - do_pmap_add(kernel_pmap, - (void *)(vbase + i), - PFN(i), - VM_PROT_READ | VM_PROT_WRITE | VM_PROT_SVR | VM_PROT_NOCACHE, hugepage); + do_pmap_add( + kernel_pmap, + (void *)(vbase + i), + PFN(i), + VM_PROT_READ | VM_PROT_WRITE | VM_PROT_SVR + | VM_PROT_NOCACHE, + hugepage); } pmap_switch(kernel_pmap); @@ -284,10 +302,14 @@ pmap_t pmap_create(void) void pmap_destroy(pmap_t pmap) { - } -kern_status_t pmap_add(pmap_t pmap, void *p, pfn_t pfn, enum vm_prot prot, enum pmap_flags flags) +kern_status_t pmap_add( + pmap_t pmap, + void *p, + pfn_t pfn, + enum vm_prot prot, + enum pmap_flags flags) { enum page_size ps = PS_4K; if (flags & PMAP_HUGEPAGE) { @@ -297,7 +319,13 @@ kern_status_t pmap_add(pmap_t pmap, void *p, pfn_t pfn, enum vm_prot prot, enum return do_pmap_add(pmap, p, pfn, prot, ps); } -kern_status_t pmap_add_block(pmap_t pmap, void *p, pfn_t pfn, size_t len, enum vm_prot prot, enum pmap_flags flags) +kern_status_t pmap_add_block( + pmap_t pmap, + void *p, + pfn_t pfn, + size_t len, + enum vm_prot prot, + enum pmap_flags flags) { return KERN_OK; } diff --git a/arch/x86_64/ports.c b/arch/x86_64/ports.c index 0a226ed..c1db9d6 100644 --- a/arch/x86_64/ports.c +++ b/arch/x86_64/ports.c @@ -1,39 +1,50 @@ #include -uint8_t inportb(uint16_t port) { - uint8_t data; - __asm__ __volatile__("inb %1, %0" : "=a"(data) : "dN"(port)); - return data; +uint8_t inportb(uint16_t port) +{ + uint8_t data; + __asm__ __volatile__("inb %1, %0" : "=a"(data) : "dN"(port)); + return data; } -void outportb(uint16_t port, uint8_t data) { - __asm__ __volatile__("outb %1, %0" : : "dN"(port), "a"(data)); +void outportb(uint16_t port, uint8_t data) +{ + __asm__ __volatile__("outb %1, %0" : : "dN"(port), "a"(data)); } -uint16_t inportw(uint16_t port) { - uint16_t data; - __asm__ __volatile__("inw %1, %0" : "=a"(data) : "dN"(port)); - return data; +uint16_t inportw(uint16_t port) +{ + uint16_t data; + __asm__ __volatile__("inw %1, %0" : "=a"(data) : "dN"(port)); + return data; } -void outportw(uint16_t port, uint16_t data) { - __asm__ __volatile__("outw %1, %0" : : "dN"(port), "a"(data)); +void outportw(uint16_t port, uint16_t data) +{ + __asm__ __volatile__("outw %1, %0" : : "dN"(port), "a"(data)); } -uint32_t inportl(uint16_t port) { - uint32_t data; - __asm__ __volatile__("inl %%dx, %%eax" : "=a"(data) : "dN"(port)); - return data; +uint32_t inportl(uint16_t port) +{ + uint32_t data; + __asm__ __volatile__("inl %%dx, %%eax" : "=a"(data) : "dN"(port)); + return data; } -void outportl(uint16_t port, uint32_t data) { - __asm__ __volatile__("outl %%eax, %%dx" : : "dN"(port), "a"(data)); +void outportl(uint16_t port, uint32_t data) +{ + __asm__ __volatile__("outl %%eax, %%dx" : : "dN"(port), "a"(data)); } -void outportsw(uint16_t port, void *data, uint32_t size) { - __asm__ __volatile__("rep outsw" : "+S"(data), "+c"(size) : "d"(port)); +void outportsw(uint16_t port, void *data, uint32_t size) +{ + __asm__ __volatile__("rep outsw" : "+S"(data), "+c"(size) : "d"(port)); } -void inportsw(uint16_t port, unsigned char *data, unsigned long size) { - __asm__ __volatile__("rep insw" : "+D"(data), "+c"(size) : "d"(port) : "memory"); +void inportsw(uint16_t port, unsigned char *data, unsigned long size) +{ + __asm__ __volatile__("rep insw" + : "+D"(data), "+c"(size) + : "d"(port) + : "memory"); } diff --git a/arch/x86_64/targets.cmake b/arch/x86_64/targets.cmake index 9bf8810..86e7e40 100644 --- a/arch/x86_64/targets.cmake +++ b/arch/x86_64/targets.cmake @@ -1,7 +1,21 @@ find_program(QEMU qemu-system-x86_64) +set(DEBUG_SESSION ${CMAKE_SOURCE_DIR}/tools/kernel-debug/debug_session.sh) +set(DEBUG_CFG_GDB ${CMAKE_SOURCE_DIR}/tools/kernel-debug/gdb_session_init) +set(DEBUG_CFG_LLDB ${CMAKE_SOURCE_DIR}/tools/kernel-debug/lldb_session_init) add_custom_target(run USES_TERMINAL COMMAND ${QEMU} -kernel $ -serial stdio) + +# LLDB DEPENDS ON AN ELF64 EXECUTABLE. +# .DBG FILE MUST NOT BE PATCHED WITH E64PATCH! +add_custom_target(debug + USES_TERMINAL + COMMAND ${DEBUG_SESSION} + ${DEBUG_CFG_GDB} + ${DEBUG_CFG_LLDB} + ${QEMU} -kernel $ + -S -s + -monitor stdio) diff --git a/arch/x86_64/toolchain.cmake b/arch/x86_64/toolchain.cmake index e6818cd..84b3da7 100644 --- a/arch/x86_64/toolchain.cmake +++ b/arch/x86_64/toolchain.cmake @@ -6,6 +6,8 @@ set(CMAKE_C_COMPILER x86_64-elf-gcc) set(CMAKE_ASM_COMPILER x86_64-elf-gcc) set(CMAKE_CXX_COMPILER x86_64-elf-g++) +set(CMAKE_STRIP x86_64-elf-strip) + set(CMAKE_C_COMPILER_WORKS TRUE) set(CMAKE_CXX_COMPILER_WORKS TRUE) diff --git a/arch/x86_64/vga.c b/arch/x86_64/vga.c new file mode 100644 index 0000000..0aff2cd --- /dev/null +++ b/arch/x86_64/vga.c @@ -0,0 +1,126 @@ +#include +#include +#include +#include +#include +#include + +struct vga_console { + uint16_t *vga_framebuffer; + unsigned int vga_cursor_x, vga_cursor_y; + unsigned int vga_screen_width, vga_screen_height; + uint8_t vga_attrib; +}; + +static struct vga_console vga_con = { + .vga_attrib = 0x0F, + .vga_screen_width = 80, + .vga_screen_height = 25, + .vga_framebuffer = (uint16_t *)0xffffffff800b8000, +}; + +static void vga_console_clear(struct vga_console *con) +{ + size_t len = con->vga_screen_width * con->vga_screen_height; + + for (size_t i = 0; i < len; i++) { + con->vga_framebuffer[i] = (uint16_t)con->vga_attrib << 8; + } + + con->vga_cursor_x = 0; + con->vga_cursor_y = 0; +} + +static void vga_console_show_cursor(struct vga_console *con) +{ + size_t start = 0, end = 15; + + outportb(0x3D4, 0x0A); + outportb(0x3D5, (inportb(0x3D5) & 0xC0) | start); + + outportb(0x3D4, 0x0B); + outportb(0x3D5, (inportb(0x3D5) & 0xE0) | end); +} + +static void vga_console_update_cursor(struct vga_console *con) +{ + uint16_t pos + = con->vga_cursor_y * con->vga_screen_width + con->vga_cursor_x; + + outportb(0x3D4, 0x0F); + outportb(0x3D5, (uint8_t)(pos & 0xFF)); + outportb(0x3D4, 0x0E); + outportb(0x3D5, (uint8_t)((pos >> 8) & 0xFF)); +} + +static void vga_console_scroll(struct vga_console *con) +{ + uint16_t *src = &con->vga_framebuffer[con->vga_screen_width]; + uint16_t *dest = &con->vga_framebuffer[0]; + size_t len = (con->vga_screen_height - 1) * con->vga_screen_width + * sizeof *con->vga_framebuffer; + + memcpy(dest, src, len); + + dest = &con->vga_framebuffer + [(con->vga_screen_height - 1) * con->vga_screen_width]; + len = con->vga_screen_width; + for (size_t i = 0; i < len; i++) { + dest[i] = (uint16_t)con->vga_attrib << 8; + } + + con->vga_cursor_x = 0; + con->vga_cursor_y = con->vga_screen_height - 1; +} + +static void vga_console_putc(struct vga_console *con, char c) +{ + switch (c) { + case '\n': + con->vga_cursor_x = 0; + con->vga_cursor_y++; + break; + case '\r': + con->vga_cursor_x = 0; + break; + default: + con->vga_framebuffer + [con->vga_cursor_y * con->vga_screen_width + + con->vga_cursor_x] + = ((uint16_t)con->vga_attrib << 8) | c; + con->vga_cursor_x++; + break; + } + + if (con->vga_cursor_x >= con->vga_screen_width) { + con->vga_cursor_x = 0; + con->vga_cursor_y++; + } + + if (con->vga_cursor_y >= con->vga_screen_height) { + vga_console_scroll(con); + } +} + +static void vgacon_write(struct console *con, const char *s, unsigned int len) +{ + for (unsigned int i = 0; i < len; i++) { + vga_console_putc(&vga_con, s[i]); + } + + vga_console_update_cursor(&vga_con); +} + +static struct console vgacon = { + .c_name = "vgacon", + .c_flags = CON_BOOT, + .c_write = vgacon_write, + .c_lock = SPIN_LOCK_INIT, +}; + +void vgacon_init(void) +{ + vga_console_clear(&vga_con); + vga_console_show_cursor(&vga_con); + console_register(&vgacon); +} diff --git a/tools/kernel-debug/debug_session.sh b/tools/kernel-debug/debug_session.sh index 5042b05..b0d29d7 100755 --- a/tools/kernel-debug/debug_session.sh +++ b/tools/kernel-debug/debug_session.sh @@ -7,24 +7,27 @@ shift 2 if command -v gdb &> /dev/null; then printf " \033[93;1mGDB\033[0m boot/mango_kernel\n" tmux \ - new-session -d -s hz-debug "sleep 0.3; gdb -tui -x $gdb_cfg" \; \ + new-session -d -s mango-debug "sleep 0.3; gdb -tui -x $gdb_cfg" \; \ split-window -h -l 80 \; \ split-window -v -l 25 "$@"\; \ select-pane -t 1 \; \ - resize-pane -R 20 + resize-pane -R 20 \; \ + select-pane -t 0 + elif command -v lldb &> /dev/null; then printf " \033[93;1mLLDB\033[0m boot/mango_kernel\n" tmux \ - new-session -d -s hz-debug "sleep 0.1; lldb --source $lldb_cfg" \; \ + new-session -d -s mango-debug "sleep 0.1; lldb --source $lldb_cfg" \; \ split-window -h -l 160 \; \ split-window -v -l 25 "$@"\; \ select-pane -t 1 \; \ - resize-pane -R 50 + resize-pane -R 50 \; \ + select-pane -t 0 else printf " \033[91;1mERR\033[0m No debugger available\n" exit -1 fi -tmux a -t hz-debug -tmux kill-session -t hz-debug +tmux a -t mango-debug +tmux kill-session -t mango-debug diff --git a/tools/kernel-debug/gdb_session_init b/tools/kernel-debug/gdb_session_init index 82d254d..c5fd706 100644 --- a/tools/kernel-debug/gdb_session_init +++ b/tools/kernel-debug/gdb_session_init @@ -1,4 +1,4 @@ set confirm off -symbol-file build/mango_kernel.dbg +symbol-file mango_kernel.debug target remote localhost:1234 set confirm on diff --git a/tools/kernel-debug/lldb_session_init b/tools/kernel-debug/lldb_session_init index 02ba887..258d050 100644 --- a/tools/kernel-debug/lldb_session_init +++ b/tools/kernel-debug/lldb_session_init @@ -1,2 +1,2 @@ -file build/mango_kernel.dbg +file mango_kernel.debug gdb-remote localhost:1234