diff options
23 files changed, 804 insertions, 60 deletions
diff --git a/kernel/src/arch/aarch64/aarch64.cpp b/kernel/src/arch/aarch64/aarch64.cpp index 25486dd..3992ad7 100644 --- a/kernel/src/arch/aarch64/aarch64.cpp +++ b/kernel/src/arch/aarch64/aarch64.cpp @@ -1,5 +1,7 @@ #include <cstdint> +#include <arch/aarch64/cpu/el.hpp> +#include <arch/aarch64/cpu/timer.hpp> #include <generic/arch.hpp> namespace arch { @@ -24,7 +26,10 @@ namespace arch { [[gnu::weak]] void tlb_flush(std::uintptr_t hint, std::uintptr_t len) { if (len / PAGE_SIZE > 256 || len == 0) { - asm volatile("tlbi alle1\n" "dsb ish\n" "isb\n" : : : "memory"); + __asm__ volatile("dsb ishst" : : : "memory"); + __asm__ volatile("tlbi vmalle1is" : : : "memory"); + __asm__ volatile("dsb ish" : : : "memory"); + __asm__ volatile("isb" : : : "memory"); } else { for (std::uintptr_t i = 0; i < len; i += PAGE_SIZE) { std::uintptr_t addr = hint + i; @@ -48,7 +53,14 @@ namespace arch { } [[gnu::weak]] void init(int stage) { - (void)stage; + switch(stage) { + case ARCH_INIT_EARLY: + aarch64::el::init(); + aarch64::timer::init(); + return; + case ARCH_INIT_COMMON: + return; + } } }
\ No newline at end of file diff --git a/kernel/src/arch/aarch64/cpu/el.cpp b/kernel/src/arch/aarch64/cpu/el.cpp new file mode 100644 index 0000000..f1cc3a3 --- /dev/null +++ b/kernel/src/arch/aarch64/cpu/el.cpp @@ -0,0 +1,66 @@ +#include <arch/aarch64/cpu/el.hpp> +#include <generic/arch.hpp> +#include <klibc/stdio.hpp> +#include <generic/paging.hpp> +#include <generic/pmm.hpp> + +#define KERNEL_STACK_SIZE 32 * 1024 + +void print_regs(aarch64::el::int_frame* ctx) { + klibc::printf("Kernel panic\n\nReason: %s\n\r","cpu exception"); + klibc::printf("x0: 0x%p x1: 0x%p x2: 0x%p x3: 0x%p\nx4: 0x%p x5: 0x%p x6: 0x%p x7: 0x%p\nx8: 0x%p x9: 0x%p x10: 0x%p " + "x11: 0x%p\nx12: 0x%p x13: 0x%p x14: 0x%p x15: 0x%p\nx16: 0x%p x17: 0x%p x18: 0x%p x19: 0x%p\nx20: 0x%p " + "x21: 0x%p x22: 0x%p x23: 0x%p\nx24: 0x%p x25: 0x%p x26: 0x%p x27: 0x%p\nx28: 0x%p x29: 0x%p x30: 0x%p\r\n" + "sp: 0x%p pc: 0x%p flags: 0x%p, 1 %d",ctx->x[0],ctx->x[1],ctx->x[2],ctx->x[3],ctx->x[4],ctx->x[5],ctx->x[6],ctx->x[7],ctx->x[8],ctx->x[9],ctx->x[10],ctx->x[11],ctx->x[12], + ctx->x[13],ctx->x[14],ctx->x[15],ctx->x[16],ctx->x[17],ctx->x[18],ctx->x[19],ctx->x[20],ctx->x[21],ctx->x[22],ctx->x[23],ctx->x[24],ctx->x[25],ctx->x[26],ctx->x[27],ctx->x[28], + ctx->x[29], ctx->x[30],ctx->sp, ctx->ip, ctx->flags, 1); +} + +std::uint8_t gaster[] = { +#embed "src/gaster.txt" +}; + + +void print_ascii_art() { + klibc::printf("%s\n",gaster); +} + +[[gnu::weak]] void arch::panic(char* msg) { + print_ascii_art(); + klibc::printf("Panic with message \"%s\"\r\n",msg); +} + +extern "C" void C_fault_handler(aarch64::el::int_frame* frame) { + print_ascii_art(); + print_regs(frame); + arch::hcf(); +} + +extern "C" void C_irq_handler(aarch64::el::int_frame* frame) { + print_ascii_art(); + print_regs(frame); + arch::hcf(); +} + +extern "C" void C_userspace_fault_handler(aarch64::el::int_frame* frame) { + print_ascii_art(); + (void)frame; + print_regs(frame); + arch::hcf(); +} + +extern "C" void C_userspace_irq_handler(aarch64::el::int_frame* frame) { + print_ascii_art(); + (void)frame; + print_regs(frame); + arch::hcf(); +} + +extern "C" char int_table[]; +std::uint64_t sp_el1_kernel_stack = 0; + +void aarch64::el::init() { + sp_el1_kernel_stack = (std::uint64_t)(pmm::buddy::alloc(KERNEL_STACK_SIZE).phys + etc::hhdm()); + asm volatile("msr VBAR_EL1, %0" :: "r"(int_table)); + klibc::printf("EL: aarch64 int_table is 0x%p sp_el1 is 0x%p\r\n",int_table, sp_el1_kernel_stack); +}
\ No newline at end of file diff --git a/kernel/src/arch/aarch64/cpu/el.hpp b/kernel/src/arch/aarch64/cpu/el.hpp new file mode 100644 index 0000000..5ca244b --- /dev/null +++ b/kernel/src/arch/aarch64/cpu/el.hpp @@ -0,0 +1,15 @@ +#pragma once +#include <cstdint> +namespace aarch64 { + namespace el { + + struct int_frame { + std::uint64_t ip; + std::uint64_t sp; + std::uint64_t flags; + std::uint64_t x[32]; + }; + + void init(); + }; +};
\ No newline at end of file diff --git a/kernel/src/arch/aarch64/cpu/timer.cpp b/kernel/src/arch/aarch64/cpu/timer.cpp new file mode 100644 index 0000000..eae5cf1 --- /dev/null +++ b/kernel/src/arch/aarch64/cpu/timer.cpp @@ -0,0 +1,49 @@ +#include <cstdint> +#include <generic/time.hpp> +#include <arch/aarch64/cpu/timer.hpp> +#include <generic/arch.hpp> +#include <klibc/stdio.hpp> + +void aarch64::timer::init() { + aarch64::timer::aarch64_timer* aarch64_timer = new aarch64::timer::aarch64_timer; + time::setup_timer(aarch64_timer); + klibc::printf("AArch64 timer: Set aarch64 timer as default\r\n"); +} + +namespace aarch64 { + int timer::aarch64_timer::get_priority() { + return 999999; + } + + std::uint64_t timer::aarch64_timer::current_nano() { + std::uint64_t cntpct_el0 = 0; + std::uint64_t cntfrq_el0 = 0; + asm volatile("mrs %0, CNTPCT_EL0" : "=r"(cntpct_el0)); + asm volatile("mrs %0, CNTFRQ_EL0" : "=r"(cntfrq_el0)); + constexpr std::uint64_t NANOSECONDS_PER_SECOND = 1000000000ULL; + + #ifdef __SIZEOF_INT128__ + __uint128_t temp = static_cast<__uint128_t>(cntpct_el0) * NANOSECONDS_PER_SECOND; + return static_cast<std::uint64_t>(temp / cntfrq_el0); + #else + std::uint64_t whole_seconds = cntpct_el0 / cntfrq_el0; + std::uint64_t remainder_ticks = cntpct_el0 % cntfrq_el0; + + std::uint64_t nanos_from_whole = whole_seconds * NANOSECONDS_PER_SECOND; + std::uint64_t nanos_from_remainder = (remainder_ticks * NANOSECONDS_PER_SECOND) / cntfrq_el0; + + return nanos_from_whole + nanos_from_remainder; + #endif + } + + void timer::aarch64_timer::sleep(std::uint64_t us) { + std::uint64_t current = this->current_nano(); + std::uint64_t end_ns = us * 1000; + std::uint64_t target = current + end_ns; + + while(this->current_nano() < target) { + arch::pause(); + } + } + +};
\ No newline at end of file diff --git a/kernel/src/arch/aarch64/cpu/timer.hpp b/kernel/src/arch/aarch64/cpu/timer.hpp new file mode 100644 index 0000000..7c18e20 --- /dev/null +++ b/kernel/src/arch/aarch64/cpu/timer.hpp @@ -0,0 +1,16 @@ +#pragma once +#include <cstdint> +#include <generic/time.hpp> + +namespace aarch64 { + namespace timer { + class aarch64_timer final : public time::generic_timer { + public: + int get_priority() override; + std::uint64_t current_nano() override; + void sleep(std::uint64_t us) override; + }; + + void init(); + }; +};
\ No newline at end of file diff --git a/kernel/src/arch/aarch64/cpu/vectors.S b/kernel/src/arch/aarch64/cpu/vectors.S new file mode 100644 index 0000000..082a016 --- /dev/null +++ b/kernel/src/arch/aarch64/cpu/vectors.S @@ -0,0 +1,227 @@ + +.extern C_fault_handler +.extern C_irq_handler +.extern C_userspace_fault_handler +.extern C_userspace_irq_handler + +_aarch64_irq_handler: +_aarch64_fault_handler: + msr daifset, #2 + sub sp, sp, #280 + str x0, [sp, #24] + str x1, [sp, #32] + str x2, [sp, #40] + str x3, [sp, #48] + str x4, [sp, #56] + str x5, [sp, #64] + str x6, [sp, #72] + str x7, [sp, #80] + str x8, [sp, #88] + str x9, [sp, #96] + str x10, [sp, #104] + str x11, [sp, #112] + str x12, [sp, #120] + str x13, [sp, #128] + str x14, [sp, #136] + str x15, [sp, #144] + str x16, [sp, #152] + str x17, [sp, #160] + str x18, [sp, #168] + str x19, [sp, #176] + str x20, [sp, #184] + str x21, [sp, #192] + str x22, [sp, #200] + str x23, [sp, #208] + str x24, [sp, #216] + str x25, [sp, #224] + str x26, [sp, #232] + str x27, [sp, #240] + str x28, [sp, #248] + str x29, [sp, #256] + str x30, [sp, #264] + mov x0, sp + add x0, x0, #280 + str x0, [sp, #8] + mrs x0, elr_el1 + str x0, [sp, #0] + mrs x0, spsr_el1 + str x0, [sp, #16] + mov x0, sp + bl C_fault_handler + ldr x0, [sp, #0] + msr elr_el1, x0 + ldr x0, [sp, #16] + msr spsr_el1, x0 + ldr x0, [sp, #24] + ldr x1, [sp, #32] + ldr x2, [sp, #40] + ldr x3, [sp, #48] + ldr x4, [sp, #56] + ldr x5, [sp, #64] + ldr x6, [sp, #72] + ldr x7, [sp, #80] + ldr x8, [sp, #88] + ldr x9, [sp, #96] + ldr x10, [sp, #104] + ldr x11, [sp, #112] + ldr x12, [sp, #120] + ldr x13, [sp, #128] + ldr x14, [sp, #136] + ldr x15, [sp, #144] + ldr x16, [sp, #152] + ldr x17, [sp, #160] + ldr x18, [sp, #168] + ldr x19, [sp, #176] + ldr x20, [sp, #184] + ldr x21, [sp, #192] + ldr x22, [sp, #200] + ldr x23, [sp, #208] + ldr x24, [sp, #216] + ldr x25, [sp, #224] + ldr x26, [sp, #232] + ldr x27, [sp, #240] + ldr x28, [sp, #248] + ldr x29, [sp, #256] + ldr x30, [sp, #264] + add sp, sp, #280 + msr daifclr, #2 + eret + +_aarch64_userspace_irq_handler: +_aarch64_userspace_fault_handler: + msr daifset, #2 + sub sp, sp, #280 + str x0, [sp, #24] + str x1, [sp, #32] + str x2, [sp, #40] + str x3, [sp, #48] + str x4, [sp, #56] + str x5, [sp, #64] + str x6, [sp, #72] + str x7, [sp, #80] + str x8, [sp, #88] + str x9, [sp, #96] + str x10, [sp, #104] + str x11, [sp, #112] + str x12, [sp, #120] + str x13, [sp, #128] + str x14, [sp, #136] + str x15, [sp, #144] + str x16, [sp, #152] + str x17, [sp, #160] + str x18, [sp, #168] + str x19, [sp, #176] + str x20, [sp, #184] + str x21, [sp, #192] + str x22, [sp, #200] + str x23, [sp, #208] + str x24, [sp, #216] + str x25, [sp, #224] + str x26, [sp, #232] + str x27, [sp, #240] + str x28, [sp, #248] + str x29, [sp, #256] + str x30, [sp, #264] + mrs x0, sp_el0 + str x0, [sp, #8] + mrs x0, elr_el1 + str x0, [sp, #0] + mrs x0, spsr_el1 + str x0, [sp, #16] + mov x0, sp + bl C_fault_handler + ldr x0, [sp, #0] + msr elr_el1, x0 + ldr x0, [sp, #16] + msr spsr_el1, x0 + ldr x0, [sp, #8] + msr sp_el0, x0 + ldr x0, [sp, #24] + ldr x1, [sp, #32] + ldr x2, [sp, #40] + ldr x3, [sp, #48] + ldr x4, [sp, #56] + ldr x5, [sp, #64] + ldr x6, [sp, #72] + ldr x7, [sp, #80] + ldr x8, [sp, #88] + ldr x9, [sp, #96] + ldr x10, [sp, #104] + ldr x11, [sp, #112] + ldr x12, [sp, #120] + ldr x13, [sp, #128] + ldr x14, [sp, #136] + ldr x15, [sp, #144] + ldr x16, [sp, #152] + ldr x17, [sp, #160] + ldr x18, [sp, #168] + ldr x19, [sp, #176] + ldr x20, [sp, #184] + ldr x21, [sp, #192] + ldr x22, [sp, #200] + ldr x23, [sp, #208] + ldr x24, [sp, #216] + ldr x25, [sp, #224] + ldr x26, [sp, #232] + ldr x27, [sp, #240] + ldr x28, [sp, #248] + ldr x29, [sp, #256] + ldr x30, [sp, #264] + add sp, sp, #280 + msr daifclr, #2 + eret + +.globl int_table +.balign 0x800 + +int_table: +sync: + b _aarch64_fault_handler +.balign 0x80 +irq: + b _aarch64_irq_handler +.balign 0x80 +fiq: + b . +.balign 0x80 +.sp0: + b . + +.balign 0x80 +sync_ker: + b _aarch64_fault_handler +.balign 0x80 +irq_ker: + b _aarch64_irq_handler +.balign 0x80 +fiq_ker: + b . +.balign 0x80 +ker_sp: + b . + +.balign 0x80 +sync_user: + b _aarch64_userspace_fault_handler +.balign 0x80 +irq_user: + b _aarch64_userspace_irq_handler +.balign 0x80 +fiq_user: + b . +.balign 0x80 +sp_user: + b . + +.balign 0x80 +_32_sync: + b . +.balign 0x80 +_32_irq: + b . +.balign 0x80 +_32_fiq: + b . +.balign 0x80 +_32_sp: + b .
\ No newline at end of file diff --git a/kernel/src/arch/aarch64/main.S b/kernel/src/arch/aarch64/main.S new file mode 100644 index 0000000..fdd9888 --- /dev/null +++ b/kernel/src/arch/aarch64/main.S @@ -0,0 +1,19 @@ + +.extern main +.global kmain + +kmain: + adrp x0, stack_top + mov x1, 1 + msr SPSel, x1 + isb + mov sp, x0 + isb + bl main + + +.section .bss +.align 4 +stack_base: + .skip (4096 * 8) +stack_top:
\ No newline at end of file diff --git a/kernel/src/arch/aarch64/paging.cpp b/kernel/src/arch/aarch64/paging.cpp index 69ecd4b..9137e19 100644 --- a/kernel/src/arch/aarch64/paging.cpp +++ b/kernel/src/arch/aarch64/paging.cpp @@ -4,6 +4,7 @@ #include <generic/hhdm.hpp> #include <generic/pmm.hpp> #include <utils/gobject.hpp> +#include <klibc/stdio.hpp> #define PTE_MASK_VALUE 0x0000fffffffff000 #define PTE_PRESENT (1 << 0) @@ -77,11 +78,11 @@ void aarch64_map_page(std::uintptr_t root, std::uintptr_t phys, std::uintptr_t v namespace arch { [[gnu::weak]] void enable_paging(std::uintptr_t root) { - asm volatile("msr ttbr0_el1, %0" : : "r"(root) : "memory"); if (root == gobject::kernel_root) { asm volatile("msr ttbr1_el1, %0" : : "r"(root) : "memory"); asm volatile("dsb ish; tlbi vmalle1; dsb ish; isb" : : : "memory"); } else { + asm volatile("msr ttbr0_el1, %0" : : "r"(root) : "memory"); asm volatile("dsb ish; tlbi vmalle1; dsb ish; isb" : : : "memory"); } } diff --git a/kernel/src/arch/riscv64/main.S b/kernel/src/arch/riscv64/main.S new file mode 100644 index 0000000..818717d --- /dev/null +++ b/kernel/src/arch/riscv64/main.S @@ -0,0 +1,6 @@ + +.global kmain +.extern main + +kmain: + call main
\ No newline at end of file diff --git a/kernel/src/arch/x86_64/assembly.hpp b/kernel/src/arch/x86_64/assembly.hpp index 4a9bda4..e030e84 100644 --- a/kernel/src/arch/x86_64/assembly.hpp +++ b/kernel/src/arch/x86_64/assembly.hpp @@ -1,28 +1,29 @@ +#pragma once #include <cstdint> namespace assembly { - inline std::uint64_t rdmsr(std::uint32_t msr) { + inline static std::uint64_t rdmsr(std::uint32_t msr) { std::uint32_t lo, hi; __asm__ volatile ("rdmsr" : "=a"(lo), "=d"(hi) : "c"(msr)); return ((std::uint64_t)hi << 32) | lo; } - inline void wrmsr(std::uint32_t msr, std::uint64_t value) { + inline static void wrmsr(std::uint32_t msr, std::uint64_t value) { std::uint32_t lo = (uint32_t)(value & 0xFFFFFFFF); std::uint32_t hi = (uint32_t)(value >> 32); __asm__ volatile ("wrmsr" : : "c"(msr), "a"(lo), "d"(hi)); } - inline void cpuid(int code, int code2, std::uint32_t *a, std::uint32_t *b, std::uint32_t *c , std::uint32_t *d) { + inline static void cpuid(int code, int code2, std::uint32_t *a, std::uint32_t *b, std::uint32_t *c , std::uint32_t *d) { __asm__ volatile("cpuid":"=a"(*a),"=b"(*b),"=c"(*c),"=d"(*d):"a"(code),"c"(code2)); } - inline int cpuid_string(int code, std::uint32_t where[4]) { + inline static int cpuid_string(int code, std::uint32_t where[4]) { __asm__ volatile("cpuid":"=a"(*where),"=b"(*(where+1)),"=c"(*(where+2)),"=d"(*(where+3)):"a"(code)); return (int)where[0]; } - inline std::uint64_t rdtsc() { + inline static std::uint64_t rdtsc() { unsigned int hi, lo; __asm__ volatile ("rdtsc" : "=a"(lo), "=d"(hi)); return ((uint64_t)hi << 32) | lo; diff --git a/kernel/src/arch/x86_64/cpu/idt.cpp b/kernel/src/arch/x86_64/cpu/idt.cpp index f1765ce..19cbbcf 100644 --- a/kernel/src/arch/x86_64/cpu/idt.cpp +++ b/kernel/src/arch/x86_64/cpu/idt.cpp @@ -3,6 +3,7 @@ #include <arch/x86_64/cpu/idt.hpp> #include <utils/bitmap.hpp> #include <klibc/stdio.hpp> +#include <arch/x86_64/cpu/lapic.hpp> x86_64::idt::idt_entry_t idt_entries[255]; utils::bitmap* idt_bitmap; @@ -11,7 +12,7 @@ x86_64::idt::idtr_t idtr; extern "C" void* isrTable[]; extern "C" void ignoreStubC() { - + x86_64::lapic::eoi(); } void x86_64::idt::init() { @@ -32,6 +33,8 @@ void x86_64::idt::init() { idt_bitmap->set(32); load(); + + klibc::printf("IDT: IDTR is 0x%p\r\n",&idtr); } void x86_64::idt::load() { diff --git a/kernel/src/arch/x86_64/cpu/lapic.hpp b/kernel/src/arch/x86_64/cpu/lapic.hpp new file mode 100644 index 0000000..a800116 --- /dev/null +++ b/kernel/src/arch/x86_64/cpu/lapic.hpp @@ -0,0 +1,66 @@ + +#include <cstdint> + +#pragma once + +#include <generic/paging.hpp> +#include <generic/time.hpp> +#include <generic/hhdm.hpp> +#include <utils/gobject.hpp> +#include <arch/x86_64/assembly.hpp> +#include <klibc/stdio.hpp> + +namespace x86_64 { + + inline int is_lapic_init = 0; + + class lapic { + + static inline std::uint64_t base() { + return (std::uint64_t)((assembly::rdmsr(0x1B) & 0xFFFFF000) + etc::hhdm()); + } + + static inline std::uint32_t read(std::uint32_t reg) { + return *(volatile std::uint32_t*)(base() + reg); + } + + static inline void write(std::uint32_t reg,std::uint32_t value) { + *(volatile std::uint32_t*)(base() + reg) = value; + } + + public: + + static inline std::uint32_t id() { + return read(0x20) >> 24; + } + + static inline void eoi() { + write(0xB0,0); + } + + static inline void tick(std::uint64_t tick) { + write(0x380,tick); + } + + static inline std::uint64_t init(std::uint32_t us) { + assembly::wrmsr(0x1B,assembly::rdmsr(0x1B)); + paging::map_range(gobject::kernel_root,assembly::rdmsr(0x1B) & 0xFFFFF000,(assembly::rdmsr(0x1B) & 0xFFFFF000) + etc::hhdm(),PAGE_SIZE, PAGING_PRESENT | PAGING_RW); + write(0xf0,0xff | 0x100); + write(0x3e0,1); + write(0x320,32 | (1 << 16)); + write(0x380,0xFFFFFFFF); + time::timer->sleep(us); + std::uint64_t ticks = 0xFFFFFFFF - read(0x390); + write(0x320, 32 | (1 << 17)); + write(0x3e0,1); + write(0x380,0); + + if(!is_lapic_init) { + klibc::printf("LAPIC: Calibration time is %lli, ticks %lli\r\n",us,ticks); + is_lapic_init = 1; + } + + return ticks; + } + }; +};
\ No newline at end of file diff --git a/kernel/src/arch/x86_64/drivers/ioapic.cpp b/kernel/src/arch/x86_64/drivers/ioapic.cpp new file mode 100644 index 0000000..4b9c04a --- /dev/null +++ b/kernel/src/arch/x86_64/drivers/ioapic.cpp @@ -0,0 +1,120 @@ + +#include <cstdint> +#include <arch/x86_64/drivers/ioapic.hpp> +#include <generic/paging.hpp> +#include <generic/hhdm.hpp> +#include <uacpi/acpi.h> +#include <uacpi/uacpi.h> +#include <uacpi/status.h> +#include <uacpi/tables.h> +#include <arch/x86_64/drivers/io.hpp> +#include <utils/gobject.hpp> +#include <klibc/stdio.hpp> + +struct acpi_madt_ioapic apics[24]; +struct acpi_madt_interrupt_source_override iso[24]; +std::uint8_t apic_ent, iso_ent; +std::uint8_t is_legacy_pic; + +void drivers::ioapic::init() { + apic_ent = 0; iso_ent = 0; + struct uacpi_table apic_table; + uacpi_status ret = uacpi_table_find_by_signature(ACPI_MADT_SIGNATURE,&apic_table); + if(ret != UACPI_STATUS_OK) + return; // ignore just use pic later + else { + x86_64::io::outb(PIC1_DATA, 0xff); + x86_64::io::outb(PIC2_DATA, 0xff); + is_legacy_pic = 0; + } + + struct acpi_madt* apic = (struct acpi_madt*)apic_table.virt_addr; + struct acpi_entry_hdr* current = (struct acpi_entry_hdr*)apic->entries; + while(1) { + + if((std::uint64_t)current >= (std::uint64_t)apic->entries + apic->hdr.length - sizeof(acpi_madt)) + break; + + switch (current->type) + { + case ACPI_MADT_ENTRY_TYPE_IOAPIC: { + struct acpi_madt_ioapic* cur_ioapic = (acpi_madt_ioapic*)current; + paging::map_range(gobject::kernel_root,cur_ioapic->address,cur_ioapic->address + etc::hhdm(),PAGE_SIZE,PAGING_PRESENT | PAGING_RW); + apics[apic_ent++] = *cur_ioapic; + klibc::printf("IOAPIC: Found ioapic with gsi base %d, address 0x%p, id %d\r\n",cur_ioapic->gsi_base,cur_ioapic->address,cur_ioapic->id); + break; + } + case ACPI_MADT_ENTRY_TYPE_INTERRUPT_SOURCE_OVERRIDE: { + struct acpi_madt_interrupt_source_override* cur_iso = (struct acpi_madt_interrupt_source_override*)current; + iso[iso_ent++] = *cur_iso; + klibc::printf("IOAPIC: Found ISO with bus %d, irq %d, gsi base %d, flags %d\r\n",cur_iso->bus,cur_iso->source,cur_iso->gsi,cur_iso->flags); + break; + } + } + current = (acpi_entry_hdr*)((std::uint64_t)current + current->length); + + } +} + +void drivers::ioapic::set(std::uint8_t vec,std::uint8_t irq,std::uint64_t flags,std::uint64_t lapic) { + struct acpi_madt_ioapic* apic; + struct acpi_madt_interrupt_source_override* ciso; + std::uint8_t is_found_iso = 0; + for(std::uint8_t i = 0;i < iso_ent;i++) { + ciso = &iso[i]; + if(ciso->source == irq) { + is_found_iso = 1; + break; + } + } + + std::uint64_t calc_flags = (lapic << 56) | flags | (vec & 0xFF); + if(is_found_iso) { + char pol = (ciso->flags & 0b11) == 0b11 ? 1 : 0; + char mode = ((ciso->flags >> 2) & 0b11) == 0b11 ? 1 : 0; + calc_flags = (lapic << 56) | (mode << 15) | (pol << 13) | (vec & 0xff) | flags; + } + + for(std::uint8_t i = 0;i < apic_ent; i++) { + apic = &apics[i]; + std::uint32_t ver = read(apic->address,1); + std::uint32_t max = ver >> 16; + if(apic->gsi_base <= irq && apic->gsi_base + max > irq) + break; + } + + std::uint32_t irqreg = ((irq - apic->gsi_base) * 2) + 0x10; + write(apic->address,irqreg,(std::uint32_t)calc_flags); + write(apic->address,irqreg + 1,(std::uint32_t)((std::uint64_t)calc_flags >> 32)); + +} + +void drivers::ioapic::mask(std::uint8_t irq) { + struct acpi_madt_ioapic* apic; + + for(std::uint8_t i = 0;i < apic_ent; i++) { + apic = &apics[i]; + std::uint32_t ver = read(apic->address,1); + std::uint32_t max = ver >> 16; + if(apic->gsi_base <= irq && apic->gsi_base + max > irq) + break; + } + + std::uint32_t irqreg = ((irq - apic->gsi_base) * 2) + 0x10; + write(apic->address,irqreg,(std::uint32_t)read(apic->address,irqreg) | (1 << 16)); +} + +void drivers::ioapic::unmask(std::uint8_t irq) { + struct acpi_madt_ioapic* apic; + + for(std::uint8_t i = 0;i < apic_ent; i++) { + apic = &apics[i]; + std::uint32_t ver = read(apic->address,1); + std::uint32_t max = ver >> 16; + if(apic->gsi_base <= irq && apic->gsi_base + max > irq) + break; + } + + std::uint32_t irqreg = ((irq - apic->gsi_base) * 2) + 0x10; + write(apic->address,irqreg,(std::uint32_t)read(apic->address,irqreg) & ~(1 << 16)); +}
\ No newline at end of file diff --git a/kernel/src/arch/x86_64/drivers/ioapic.hpp b/kernel/src/arch/x86_64/drivers/ioapic.hpp new file mode 100644 index 0000000..94e880c --- /dev/null +++ b/kernel/src/arch/x86_64/drivers/ioapic.hpp @@ -0,0 +1,31 @@ +#pragma once +#include <cstdint> +#include <generic/hhdm.hpp> +#define PIC1 0x20 +#define PIC2 0xA0 +#define PIC1_COMMAND PIC1 +#define PIC1_DATA (PIC1+1) +#define PIC2_COMMAND PIC2 +#define PIC2_DATA (PIC2+1) + +namespace drivers { + namespace ioapic { + static inline void write(std::uint64_t base, std::uint32_t reg,std::uint32_t value) { + std::uint64_t virt = (std::uint64_t)(base + etc::hhdm()); + *(volatile std::uint32_t*)virt = reg; + *(volatile std::uint32_t*)(virt + 0x10) = value; + } + + static inline std::uint32_t read(std::uint64_t base, std::uint32_t reg) { + std::uint64_t virt = (std::uint64_t)(base + etc::hhdm()); + *(volatile std::uint32_t*)virt = reg; + return *(volatile std::uint32_t*)(virt + 0x10); + } + + void init(); + void set(std::uint8_t vec,std::uint8_t irq,std::uint64_t flags,std::uint64_t lapic); + void mask(std::uint8_t irq); + void unmask(std::uint8_t irq); + + }; +};
\ No newline at end of file diff --git a/kernel/src/arch/x86_64/irq.cpp b/kernel/src/arch/x86_64/irq.cpp new file mode 100644 index 0000000..da709eb --- /dev/null +++ b/kernel/src/arch/x86_64/irq.cpp @@ -0,0 +1,54 @@ +#include <arch/x86_64/cpu/idt.hpp> +#include <arch/x86_64/irq.hpp> +#include <arch/x86_64/cpu/lapic.hpp> +#include <arch/x86_64/drivers/ioapic.hpp> +#include <cstdint> + +irq_t irq_table[255]; +std::uint16_t irq_ptr = 0; + +extern "C" void* irqTable[]; + +extern "C" void irqHandler(x86_64::idt::int_frame_t* ctx) { + + if(ctx->cs != 0x08) + asm volatile("swapgs"); + + irq_table[ctx->vec - 1].func(irq_table[ctx->vec - 1].arg); + + x86_64::lapic::eoi(); + + if(ctx->cs & 3) + ctx->ss |= 3; + + if(ctx->ss & 3) + ctx->cs |= 3; + + if(ctx->cs == 0x20) + ctx->cs |= 3; + + if(ctx->ss == 0x18) + ctx->ss |= 3; + + if(ctx->cs != 0x08) + asm volatile("swapgs"); + +} + +std::uint8_t x86_64::irq::create(std::uint16_t irq,std::uint8_t type,void (*func)(void* arg),void* arg,std::uint64_t flags) { + uint8_t entry = 0; + + if(type == IRQ_TYPE_LEGACY) { + entry = x86_64::idt::alloc(); + x86_64::idt::set_entry((std::uint64_t)irqTable[entry - 0x20],entry,0x8E,3); + drivers::ioapic::set(entry,irq,flags,x86_64::lapic::id()); + } else { + entry = x86_64::idt::alloc(); + x86_64::idt::set_entry((std::uint64_t)irqTable[entry - 0x20],entry,0x8E,3); + } + + irq_table[irq_ptr].arg = arg; + irq_table[irq_ptr].irq = irq; + irq_table[irq_ptr++].func = func; + return entry; +}
\ No newline at end of file diff --git a/kernel/src/arch/x86_64/irq.hpp b/kernel/src/arch/x86_64/irq.hpp new file mode 100644 index 0000000..c46d1be --- /dev/null +++ b/kernel/src/arch/x86_64/irq.hpp @@ -0,0 +1,15 @@ +#pragma once +#include <cstdint> + +typedef struct { + void (*func)(void* arg); + void* arg; + int irq; + char is_userspace; +} irq_t; + +namespace x86_64 { + namespace irq { + std::uint8_t create(std::uint16_t irq,std::uint8_t type,void (*func)(void* arg),void* arg,std::uint64_t flags); + }; +};
\ No newline at end of file diff --git a/kernel/src/arch/x86_64/main.asm b/kernel/src/arch/x86_64/main.asm new file mode 100644 index 0000000..b6ed5ff --- /dev/null +++ b/kernel/src/arch/x86_64/main.asm @@ -0,0 +1,7 @@ + +extern main +global kmain + +kmain: + cli + jmp main
\ No newline at end of file diff --git a/kernel/src/arch/x86_64/panic.cpp b/kernel/src/arch/x86_64/panic.cpp new file mode 100644 index 0000000..0ae6697 --- /dev/null +++ b/kernel/src/arch/x86_64/panic.cpp @@ -0,0 +1,44 @@ +#include <klibc/stdio.hpp> +#include <arch/x86_64/panic.hpp> +#include <arch/x86_64/cpu/idt.hpp> +#include <generic/arch.hpp> + +void print_regs(x86_64::idt::int_frame_t* ctx) { + uint64_t cr2; + asm volatile("mov %%cr2, %0" : "=r"(cr2) : : "memory"); + klibc::printf("Kernel panic\n\nReason: %s\n\r","cpu exception"); + klibc::printf("RAX: 0x%016llX RBX: 0x%016llX RDX: 0x%016llX RCX: 0x%016llX RDI: 0x%016llX\n\r" + "RSI: 0x%016llX R8: 0x%016llX R9: 0x%016llX R10: 0x%016llX R11: 0x%016llX\n\r" + "R12: 0x%016llX R13: 0x%016llX R14: 0x%016llX R15: 0x%016llX RBP: 0x%016llX\n\r" + "RSP: 0x%016llX CR2: 0x%016llX CR3: 0x%016llX\n\r" + "Vec: %d Err: %d cs: %p ss: %p\n\r", + ctx->rax, ctx->rbx, ctx->rdx, ctx->rcx, ctx->rdi, + ctx->rsi, ctx->r8, ctx->r9, ctx->r10, ctx->r11, + ctx->r12, ctx->r13, ctx->r14, ctx->r15, ctx->rbp, + ctx->rsp, cr2, ctx->cr3, ctx->vec, ctx->err_code, ctx->cs,ctx->ss); + klibc::printf("\n\r Stacktrace\n\r\n\r"); + + stackframe_t* rbp = (stackframe_t*)ctx->rbp; + + klibc::printf("[0] - 0x%016llX (current rip)\n\r",ctx->rip); + for (int i = 1; i < 5 && rbp; ++i) { + std::uint64_t ret_addr = rbp->rip; + klibc::printf("[%d] - 0x%016llX\n\r", i, ret_addr); + rbp = (stackframe_t*)rbp->rbp; + } + +} + +std::uint8_t gaster[] = { +#embed "src/gaster.txt" +}; + +void print_ascii_art() { + klibc::printf("%s\n",gaster); +} + +extern "C" void CPUKernelPanic(x86_64::idt::int_frame_t* frame) { + print_ascii_art(); + print_regs(frame); + arch::hcf(); +}
\ No newline at end of file diff --git a/kernel/src/arch/x86_64/panic.hpp b/kernel/src/arch/x86_64/panic.hpp new file mode 100644 index 0000000..d7c2580 --- /dev/null +++ b/kernel/src/arch/x86_64/panic.hpp @@ -0,0 +1,16 @@ +#pragma once +#include <cstdint> +#include <arch/x86_64/cpu/idt.hpp> + +typedef struct stackframe { + struct stackframe* rbp; + uint64_t rip; +} __attribute__((packed)) stackframe_t; + +namespace x86_64 { + namespace panic { + void print_ascii_art(); + void print_regs(x86_64::idt::int_frame_t* ctx); + extern "C" void CPUKernelPanic(x86_64::idt::int_frame_t* frame); + }; +};
\ No newline at end of file diff --git a/kernel/src/arch/x86_64/x86_64.cpp b/kernel/src/arch/x86_64/x86_64.cpp index e45d336..804c54f 100644 --- a/kernel/src/arch/x86_64/x86_64.cpp +++ b/kernel/src/arch/x86_64/x86_64.cpp @@ -7,52 +7,11 @@ #include <arch/x86_64/drivers/tsc.hpp> #include <arch/x86_64/cpu/gdt.hpp> #include <arch/x86_64/cpu/idt.hpp> +#include <arch/x86_64/cpu/lapic.hpp> +#include <arch/x86_64/panic.hpp> +#include <arch/x86_64/irq.hpp> #include <klibc/stdio.hpp> - -typedef struct stackframe { - struct stackframe* rbp; - uint64_t rip; -} __attribute__((packed)) stackframe_t; - -void print_regs(x86_64::idt::int_frame_t* ctx) { - uint64_t cr2; - asm volatile("mov %%cr2, %0" : "=r"(cr2) : : "memory"); - klibc::printf("Kernel panic\n\nReason: %s\n\r","cpu exception"); - klibc::printf("RAX: 0x%016llX RBX: 0x%016llX RDX: 0x%016llX RCX: 0x%016llX RDI: 0x%016llX\n\r" - "RSI: 0x%016llX R8: 0x%016llX R9: 0x%016llX R10: 0x%016llX R11: 0x%016llX\n\r" - "R12: 0x%016llX R13: 0x%016llX R14: 0x%016llX R15: 0x%016llX RBP: 0x%016llX\n\r" - "RSP: 0x%016llX CR2: 0x%016llX CR3: 0x%016llX\n\r" - "Vec: %d Err: %d cs: %p ss: %p\n\r", - ctx->rax, ctx->rbx, ctx->rdx, ctx->rcx, ctx->rdi, - ctx->rsi, ctx->r8, ctx->r9, ctx->r10, ctx->r11, - ctx->r12, ctx->r13, ctx->r14, ctx->r15, ctx->rbp, - ctx->rsp, cr2, ctx->cr3, ctx->vec, ctx->err_code, ctx->cs,ctx->ss); - klibc::printf("\n\r Stacktrace\n\r\n\r"); - - stackframe_t* rbp = (stackframe_t*)ctx->rbp; - - klibc::printf("[0] - 0x%016llX (current rip)\n\r",ctx->rip); - for (int i = 1; i < 5 && rbp; ++i) { - std::uint64_t ret_addr = rbp->rip; - klibc::printf("[%d] - 0x%016llX\n\r", i, ret_addr); - rbp = (stackframe_t*)rbp->rbp; - } - -} - -std::uint8_t gaster[] = { -#embed "src/gaster.txt" -}; - -void print_ascii_art() { - klibc::printf("%s\n",gaster); -} - -extern "C" void CPUKernelPanic(x86_64::idt::int_frame_t* frame) { - print_ascii_art(); - print_regs(frame); - arch::hcf(); -} +#include <arch/x86_64/drivers/ioapic.hpp> namespace arch { [[gnu::weak]] void disable_interrupts() { @@ -104,17 +63,23 @@ namespace arch { x86_64::init_cpu_data(); drivers::hpet::init(); drivers::tsc::init(); - return; - case ARCH_INIT_COMMON: x86_64::gdt::init(); x86_64::idt::init(); + x86_64::lapic::init(1500); + drivers::ioapic::init(); + return; + case ARCH_INIT_COMMON: return; } } [[gnu::weak]] void panic(char* msg) { - print_ascii_art(); - klibc::printf("Panic with message \"%s\"",msg); + x86_64::panic::print_ascii_art(); + klibc::printf("Panic with message \"%s\"\r\n",msg); + } + + [[gnu::weak]] int register_handler(int irq, int type, std::uint64_t flags, void (*func)(void* arg), void* arg) { + return x86_64::irq::create(irq,type,func,arg,flags); } }
\ No newline at end of file diff --git a/kernel/src/generic/arch.hpp b/kernel/src/generic/arch.hpp index 7649b5b..cd569ef 100644 --- a/kernel/src/generic/arch.hpp +++ b/kernel/src/generic/arch.hpp @@ -10,6 +10,9 @@ #define ARCH_INIT_EARLY 0 #define ARCH_INIT_COMMON 1 +#define IRQ_TYPE_OTHER 0 +#define IRQ_TYPE_LEGACY 1 +#define IRQ_TYPE_MSI 2 namespace arch { @@ -30,6 +33,8 @@ namespace arch { extern void copy_higher_half(std::uintptr_t root, std::uintptr_t src_root); extern int level_paging(); + extern int register_handler(int irq, int type, std::uint64_t flags, void (*func)(void* arg), void* arg); + extern void panic(char* msg); };
\ No newline at end of file diff --git a/kernel/src/generic/paging.cpp b/kernel/src/generic/paging.cpp index 5605e14..5f84c49 100644 --- a/kernel/src/generic/paging.cpp +++ b/kernel/src/generic/paging.cpp @@ -80,6 +80,7 @@ namespace paging { mapentry(kernel_root, LIMINE_MEMMAP_EXECUTABLE_AND_MODULES, 0); map_kernel(kernel_root); arch::enable_paging(kernel_root); + arch::tlb_flush(0,0); klibc::printf("Paging: Enabled kernel root with %d level paging\n\r", arch::level_paging()); } }; diff --git a/kernel/src/main.cpp b/kernel/src/main.cpp index e90731a..3722589 100644 --- a/kernel/src/main.cpp +++ b/kernel/src/main.cpp @@ -7,10 +7,11 @@ #include <generic/paging.hpp> #include <generic/heap.hpp> #include <drivers/acpi.hpp> +#include <generic/time.hpp> extern std::size_t memory_size; -extern "C" void kmain() { +extern "C" void main() { utils::cxx::init_constructors(); bootloader::init(); utils::flanterm::init(); @@ -28,6 +29,10 @@ extern "C" void kmain() { extern int is_early; is_early = 0; klibc::printf("Boot is done\r\n"); - //*(int*)0x100 = 0; + klibc::printf("current sec %lli, waiting 2 sec and page faulting\r\n",time::timer->current_nano() / (1000 * 1000 * 1000)); + klibc::printf("current sec %lli\r\n",time::timer->current_nano() / (1000 * 1000 * 1000)); + arch::tlb_flush(0x47afe000,PAGE_SIZE); + *(int*)0x47afe710 = 0; + arch::hcf(); } |
