diff --git a/kernel/hw/3ds11/config.py b/kernel/hw/3ds11/config.py index b077a95..c0a2d40 100644 --- a/kernel/hw/3ds11/config.py +++ b/kernel/hw/3ds11/config.py @@ -7,5 +7,6 @@ if config["ENABLE_I2C"]: add_driver(False, "mcu") add_driver(True, "framebuffer") add_driver(False, "picafb") +add_driver(False, "vectorinit") print("Enable complete Unicode font: NO (because of the size)") config["ENABLE_FRAMEBUFFER_UNICODE"] = False diff --git a/kernel/hw/3ds11/vectorinit/vectorinit.cpp b/kernel/hw/3ds11/vectorinit/vectorinit.cpp new file mode 100644 index 0000000..bcd4946 --- /dev/null +++ b/kernel/hw/3ds11/vectorinit/vectorinit.cpp @@ -0,0 +1,26 @@ +#include "vectorinit.hpp" +extern "C" { +extern uintptr_t branch_macro; +void data_abort(); +void fast_irq(); +void normal_irq(); +void prefetch_abort(); +void svc_call(); +void undefined_op(); +} +void initVectors() { + uintptr_t *vectors = (uintptr_t *)0x1FFFFFA0; + // branch_macro is a ldr pc, [pc,#-4], meaning it reads the following word as PC + vectors[0] = branch_macro; + vectors[1] = (uintptr_t)&normal_irq; + vectors[2] = branch_macro; + vectors[3] = (uintptr_t)&fast_irq; + vectors[4] = branch_macro; + vectors[5] = (uintptr_t)&svc_call; + vectors[6] = branch_macro; + vectors[7] = (uintptr_t)&undefined_op; + vectors[8] = branch_macro; + vectors[9] = (uintptr_t)&prefetch_abort; + vectors[10] = branch_macro; + vectors[11] = (uintptr_t)&data_abort; +} diff --git a/kernel/hw/3ds11/vectorinit/vectorinit.hpp b/kernel/hw/3ds11/vectorinit/vectorinit.hpp new file mode 100644 index 0000000..4004a27 --- /dev/null +++ b/kernel/hw/3ds11/vectorinit/vectorinit.hpp @@ -0,0 +1,2 @@ +#include +void initVectors(); diff --git a/kernel/hw/3ds9/config.py b/kernel/hw/3ds9/config.py index 62eb5b8..0ca4d86 100644 --- a/kernel/hw/3ds9/config.py +++ b/kernel/hw/3ds9/config.py @@ -1,5 +1,6 @@ config["ENABLE_EXTRA_MEMORY"] = get_yes_no("Enable 512KB of memory on n3DS", True) add_driver(True, "framebuffer") add_driver(False, "picafb") +add_driver(False, "vectorinit") print("Enable complete Unicode font: NO (because of the size)") config["ENABLE_FRAMEBUFFER_UNICODE"] = False diff --git a/kernel/hw/3ds9/vectorinit/vectorinit.cpp b/kernel/hw/3ds9/vectorinit/vectorinit.cpp new file mode 100644 index 0000000..e424ae7 --- /dev/null +++ b/kernel/hw/3ds9/vectorinit/vectorinit.cpp @@ -0,0 +1,26 @@ +#include "vectorinit.hpp" +extern "C" { +extern uintptr_t branch_macro; +void data_abort(); +void fast_irq(); +void normal_irq(); +void prefetch_abort(); +void svc_call(); +void undefined_op(); +} +void initVectors() { + uintptr_t *vectors = (uintptr_t *)0x08000000; + // branch_macro is a ldr pc, [pc,#-4], meaning it reads the following word as PC + vectors[0] = branch_macro; + vectors[1] = (uintptr_t)&normal_irq; + vectors[2] = branch_macro; + vectors[3] = (uintptr_t)&fast_irq; + vectors[4] = branch_macro; + vectors[5] = (uintptr_t)&svc_call; + vectors[6] = branch_macro; + vectors[7] = (uintptr_t)&undefined_op; + vectors[8] = branch_macro; + vectors[9] = (uintptr_t)&prefetch_abort; + vectors[10] = branch_macro; + vectors[11] = (uintptr_t)&data_abort; +} diff --git a/kernel/hw/3ds9/vectorinit/vectorinit.hpp b/kernel/hw/3ds9/vectorinit/vectorinit.hpp new file mode 100644 index 0000000..4004a27 --- /dev/null +++ b/kernel/hw/3ds9/vectorinit/vectorinit.hpp @@ -0,0 +1,2 @@ +#include +void initVectors(); diff --git a/kernel/hw/pc/idt/idt.cpp b/kernel/hw/pc/idt/idt.cpp new file mode 100644 index 0000000..ee5ef09 --- /dev/null +++ b/kernel/hw/pc/idt/idt.cpp @@ -0,0 +1,35 @@ +#include "idt.hpp" +extern "C" void intr_stub_0(); +IDT_entry entries[256]; +void setIDTEntry(int i, void *entry) { + uintptr_t p = (uintptr_t)entry; + entries[i].offset0 = (uint16_t)p; + p >>= 16; +#ifndef __x86_64__ + entries[i].selector = 0x8; +#else + entries[i].selector = 0x28; +#endif + entries[i].zero = 0; + entries[i].type = 0b1110; + entries[i].storageSeg = false; + entries[i].dpl = 3; + entries[i].used = true; + entries[i].offset1 = (uint16_t)p; + p >>= 16; +#ifdef __x86_64__ + entries[i].offset2 = (uint32_t)p; + entries[i].zero2 = 0; +#endif +} +void initIDT() { + void *start_vectors = (void *)&intr_stub_0; + for (int i = 0; i < 256; i++) setIDTEntry(i, start_vectors + 16 * i); + struct { + uint16_t size; + uint32_t off; + } __attribute__((packed)) idtr; + idtr.size = sizeof(entries); + idtr.off = (uint32_t)((uintptr_t)entries); + asm volatile("lidt %0" : : "m"(idtr)); +} diff --git a/kernel/hw/pc/idt/idt.hpp b/kernel/hw/pc/idt/idt.hpp new file mode 100644 index 0000000..4b4e3fc --- /dev/null +++ b/kernel/hw/pc/idt/idt.hpp @@ -0,0 +1,20 @@ +#pragma once +#include +/** + * Element of the interrupt descriptor table. + */ +struct IDT_entry { + uint16_t offset0; ///< bits 0…15 of interrupt entry address + uint16_t selector; ///< segment of the interrupt handler + uint8_t zero; ///< has to be zero + uint8_t type : 4; ///< Type of the interrupt + bool storageSeg : 1; ///< 0 for interrupt gates (???) + uint8_t dpl : 2; ///< Priviledge level required for calling this interrupt + bool used : 1; ///< true if the entry is usable + uint16_t offset1; ///< Bits 16…31 of the entrypoint +#ifdef __x86_64__ + uint32_t offset2; ///< Bits 32…63 of the entrypoint. Only present on AMD64 + uint32_t zero2; ///< Must be zero. Only present on AMD64 +#endif +} __attribute__((packed)); +void initIDT();