diff --git a/meson.build b/meson.build index 81688e0..bdaba37 100644 --- a/meson.build +++ b/meson.build @@ -74,6 +74,7 @@ kernel_sources = files([ 'src/kernel/idt.c', 'src/kernel/kernel.c', 'src/kernel/keyboard.c', + 'src/kernel/log.c', 'src/kernel/memory.c', 'src/kernel/panic.c', 'src/kernel/path.c', diff --git a/src/kernel/idt.c b/src/kernel/idt.c index dfb2da4..0c8883a 100644 --- a/src/kernel/idt.c +++ b/src/kernel/idt.c @@ -38,3 +38,7 @@ void idt_set_entry(int vector, void (*handler)(struct interrupt_frame *), uint8_ idt[vector].offset_high = (addr >> 32) & 0xFFFFFFFF; idt[vector].zero = 0; } + +void idt_set_entry_ec(int vector, void (*handler)(struct interrupt_frame *, uint64_t error), uint8_t flags) { + idt_set_entry(vector, (void *)handler, flags); +} diff --git a/src/kernel/idt.h b/src/kernel/idt.h index 878a393..56c8b20 100644 --- a/src/kernel/idt.h +++ b/src/kernel/idt.h @@ -13,3 +13,5 @@ struct interrupt_frame { void idt_init(); void idt_set_entry(int vector, void (*handler)(struct interrupt_frame *), uint8_t flags); + +void idt_set_entry_ec(int vector, void (*handler)(struct interrupt_frame *, uint64_t error), uint8_t flags); diff --git a/src/kernel/kernel.c b/src/kernel/kernel.c index ac90532..5b3d2fd 100644 --- a/src/kernel/kernel.c +++ b/src/kernel/kernel.c @@ -2,11 +2,13 @@ #include "src/kernel/gdt.h" #include "src/kernel/idt.h" #include "src/kernel/keyboard.h" +#include "src/kernel/log.h" #include "src/kernel/panic.h" #include "src/kernel/path.h" #include "src/kernel/pic.h" #include "src/kernel/pipe.h" #include "src/kernel/process.h" +#include "src/kernel/stream.h" #include "src/kernel/syscall.h" #include "src/kernel/timer.h" #include "src/kernel/tss.h" @@ -22,8 +24,14 @@ __attribute__((interrupt)) void isr_divide_by_zero(__attribute__((unused)) struc ; } -__attribute__((interrupt)) void isr_page_fault(__attribute__((unused)) struct interrupt_frame *frame) { - vga_set_string(VGA_HEIGHT - 1, 0, "EXCEPTION: page fault", 0x4F); +__attribute__((interrupt)) void isr_page_fault(__attribute__((unused)) struct interrupt_frame *frame, uint64_t error_code) { + uint64_t cr2; + __asm__ volatile("mov %%cr2, %0" : "=r"(cr2)); + + char msg[80]; + string_format("EXCEPTION: page fault; addr=%x err=%x", 80, msg, cr2, error_code); + + vga_set_string(VGA_HEIGHT - 1, 0, msg, 0x4F); while (1) ; } @@ -40,11 +48,14 @@ __attribute__((interrupt)) void isr_ata_primary(__attribute__((unused)) struct i } void kernel_main() { + stream_t *vga = vga_init(); + log_init(vga); + pic_init(); idt_init(); outb(0x21, inb(0x21) | 0x01); // mask out timer interrupt idt_set_entry(0, isr_divide_by_zero, 0x8E); - idt_set_entry(0x0E, isr_page_fault, 0x8E); + idt_set_entry_ec(0x0E, isr_page_fault, 0x8E); idt_set_entry(0x0D, isr_general_violation, 0x8E); idt_set_entry(46, isr_ata_primary, 0x8E); @@ -59,8 +70,7 @@ void kernel_main() { kernel->user_stack = kernel->user_rsp = (uint8_t *)memory_allocate(PAGE_SIZE) + PAGE_SIZE; kernel->cwd = memory_allocate(sizeof(path_t)); kernel->fds[STDIN] = keyboard_init(); - kernel->fds[STDOUT] = vga_init(); - kernel->fds[STDERR] = kernel->fds[STDOUT]; + kernel->fds[STDOUT] = kernel->fds[STDERR] = vga; kernel->free_fd = STDERR + 1; kernel->code = EXIT_CODE_OK; diff --git a/src/kernel/log.c b/src/kernel/log.c new file mode 100644 index 0000000..b6335ef --- /dev/null +++ b/src/kernel/log.c @@ -0,0 +1,8 @@ +#include "src/kernel/log.h" +#include "src/kernel/stream.h" + +stream_t *kernel_log; + +void log_init(stream_t *log) { + kernel_log = log; +} diff --git a/src/kernel/log.h b/src/kernel/log.h new file mode 100644 index 0000000..506298e --- /dev/null +++ b/src/kernel/log.h @@ -0,0 +1,20 @@ +#pragma once + +#include "src/kernel/stream.h" +#include "src/lib/memory.h" +#include "src/lib/string.h" + +extern stream_t *kernel_log; + +#define LOG(fmt, ...) \ + do { \ + uint64_t _size = string_length(fmt) * 2; \ + char *_string = memory_allocate(_size); \ + _size = string_format(fmt, _size, _string, ##__VA_ARGS__); \ + kernel_log->write(kernel_log, _string, _size); \ + memory_free(_string); \ + } while (0) + +#define TRACE(fmt, ...) + +void log_init(stream_t *log); diff --git a/src/kernel/memory.c b/src/kernel/memory.c index ec67321..16f47ee 100644 --- a/src/kernel/memory.c +++ b/src/kernel/memory.c @@ -1,4 +1,5 @@ #include "src/kernel/memory.h" +#include "src/kernel/log.h" #include "src/kernel/panic.h" #include "src/lib/layout.h" #include "src/lib/memory.h" @@ -66,7 +67,10 @@ void memory_page_map(uint64_t *pml4, void *virt, void *phys, uint64_t flags) { const uint64_t pd_index = (ivirt >> 21) & 0x1FF; const uint64_t pt_index = (ivirt >> 12) & 0x1FF; + TRACE("memory_page_map: Mapping physical %x to virtual %x / [%u, %u, %u, %u]...\n", phys, virt, pml4_index, pdpt_index, pd_index, pt_index); + if (!(pml4[pml4_index] & PAGE_PRESENT)) { + TRACE("memory_page_map: PML4 entry %u does not exist, creating...\n", pml4_index); uint64_t *pdpt = memory_page_allocate(); memory_set(0, PAGE_SIZE, PHYS_TO_VIRT(pdpt)); pml4[pml4_index] = (uint64_t)pdpt | PAGE_PRESENT | PAGE_WRITABLE | PAGE_USER; @@ -74,21 +78,32 @@ void memory_page_map(uint64_t *pml4, void *virt, void *phys, uint64_t flags) { uint64_t *pdpt = PHYS_TO_VIRT(pml4[pml4_index] & ~(uint64_t)0xFFF); if (!(pdpt[pdpt_index] & PAGE_PRESENT)) { + TRACE("memory_page_map: PDPT entry %u does not exist, creating...\n", pdpt_index); uint64_t *pd = memory_page_allocate(); memory_set(0, PAGE_SIZE, PHYS_TO_VIRT(pd)); pdpt[pdpt_index] = (uint64_t)pd | PAGE_PRESENT | PAGE_WRITABLE | PAGE_USER; } uint64_t *pd = PHYS_TO_VIRT(pdpt[pdpt_index] & ~(uint64_t)0xFFF); - ASSERT(!(pd[pd_index] & 0x80), "memory_page_map: huge page in PD"); + ASSERT(!(pd[pd_index] & 0x80), "memory_page_map: Huge page in PD."); if (!(pd[pd_index] & PAGE_PRESENT)) { + TRACE("memory_page_map: PD entry %u does not exist, creating...\n", pd_index); uint64_t *pt = memory_page_allocate(); memory_set(0, PAGE_SIZE, PHYS_TO_VIRT(pt)); pd[pd_index] = (uint64_t)pt | PAGE_PRESENT | PAGE_WRITABLE | PAGE_USER; } uint64_t *pt = PHYS_TO_VIRT(pd[pd_index] & ~(uint64_t)0xFFF); + + ASSERT(!(pt[pt_index] & PAGE_PRESENT), "memory_page_map: Page already mapped.") + + TRACE("memory_page_map: PT entry %u does not exist, creating...\n", pt_index); + pt[pt_index] = (uint64_t)phys | flags | PAGE_PRESENT; + + TRACE("memory_page_map: Created %x.\n", pt[pt_index]); + + TRACE("memory_page_map: Done.\n"); } void memory_page_unmap(uint64_t *pml4, void *virt) {