hook the vectors the b9/b11 jumps to on interrupt

This commit is contained in:
Morten Delenk 2017-04-30 16:54:36 +00:00
parent 352e211fb0
commit 20038f84ab
8 changed files with 113 additions and 0 deletions

View file

@ -7,5 +7,6 @@ if config["ENABLE_I2C"]:
add_driver(False, "mcu") add_driver(False, "mcu")
add_driver(True, "framebuffer") add_driver(True, "framebuffer")
add_driver(False, "picafb") add_driver(False, "picafb")
add_driver(False, "vectorinit")
print("Enable complete Unicode font: NO (because of the size)") print("Enable complete Unicode font: NO (because of the size)")
config["ENABLE_FRAMEBUFFER_UNICODE"] = False config["ENABLE_FRAMEBUFFER_UNICODE"] = False

View file

@ -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;
}

View file

@ -0,0 +1,2 @@
#include <stdint.h>
void initVectors();

View file

@ -1,5 +1,6 @@
config["ENABLE_EXTRA_MEMORY"] = get_yes_no("Enable 512KB of memory on n3DS", True) config["ENABLE_EXTRA_MEMORY"] = get_yes_no("Enable 512KB of memory on n3DS", True)
add_driver(True, "framebuffer") add_driver(True, "framebuffer")
add_driver(False, "picafb") add_driver(False, "picafb")
add_driver(False, "vectorinit")
print("Enable complete Unicode font: NO (because of the size)") print("Enable complete Unicode font: NO (because of the size)")
config["ENABLE_FRAMEBUFFER_UNICODE"] = False config["ENABLE_FRAMEBUFFER_UNICODE"] = False

View file

@ -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;
}

View file

@ -0,0 +1,2 @@
#include <stdint.h>
void initVectors();

35
kernel/hw/pc/idt/idt.cpp Normal file
View file

@ -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));
}

20
kernel/hw/pc/idt/idt.hpp Normal file
View file

@ -0,0 +1,20 @@
#pragma once
#include <stdint.h>
/**
* 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();