summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--kernel/src/arch/aarch64/aarch64.cpp16
-rw-r--r--kernel/src/arch/aarch64/cpu/el.cpp66
-rw-r--r--kernel/src/arch/aarch64/cpu/el.hpp15
-rw-r--r--kernel/src/arch/aarch64/cpu/timer.cpp49
-rw-r--r--kernel/src/arch/aarch64/cpu/timer.hpp16
-rw-r--r--kernel/src/arch/aarch64/cpu/vectors.S227
-rw-r--r--kernel/src/arch/aarch64/main.S19
-rw-r--r--kernel/src/arch/aarch64/paging.cpp3
-rw-r--r--kernel/src/arch/riscv64/main.S6
-rw-r--r--kernel/src/arch/x86_64/assembly.hpp11
-rw-r--r--kernel/src/arch/x86_64/cpu/idt.cpp5
-rw-r--r--kernel/src/arch/x86_64/cpu/lapic.hpp66
-rw-r--r--kernel/src/arch/x86_64/drivers/ioapic.cpp120
-rw-r--r--kernel/src/arch/x86_64/drivers/ioapic.hpp31
-rw-r--r--kernel/src/arch/x86_64/irq.cpp54
-rw-r--r--kernel/src/arch/x86_64/irq.hpp15
-rw-r--r--kernel/src/arch/x86_64/main.asm7
-rw-r--r--kernel/src/arch/x86_64/panic.cpp44
-rw-r--r--kernel/src/arch/x86_64/panic.hpp16
-rw-r--r--kernel/src/arch/x86_64/x86_64.cpp63
-rw-r--r--kernel/src/generic/arch.hpp5
-rw-r--r--kernel/src/generic/paging.cpp1
-rw-r--r--kernel/src/main.cpp9
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();
}