summaryrefslogtreecommitdiff
path: root/src/kernel/int.c
diff options
context:
space:
mode:
authorBrett Weiland <brett_weiland@bpcspace.com>2021-08-24 14:09:29 -0500
committerBrett Weiland <brett_weiland@bpcspace.com>2021-08-24 14:09:29 -0500
commit9b22a6965579ea1867aea291d910c96f386b518b (patch)
treed06dbb9c4708f1cc713bcb115b32ff9bce4cf9b9 /src/kernel/int.c
parentbad4b0e9bdfee336bfc1c23761408279eaec1558 (diff)
major backup 8.24.21
Diffstat (limited to 'src/kernel/int.c')
-rw-r--r--src/kernel/int.c253
1 files changed, 253 insertions, 0 deletions
diff --git a/src/kernel/int.c b/src/kernel/int.c
new file mode 100644
index 0000000..34f1c78
--- /dev/null
+++ b/src/kernel/int.c
@@ -0,0 +1,253 @@
+#include <int.h>
+#include <acpi.h>
+#include <io.h>
+#include <paging.h>
+#include <printf.h>
+#include <isv.h>
+#include <kernel.h>
+#include <libc.h>
+#include <madt.h>
+#include <timer.h>
+#include <panic.h>
+
+#define SEGMENT_GDT 0
+#define SEGMENT_LDT 1
+
+
+
+//io commands
+#define ICW1_ICW4 0x01
+#define ICW1_INIT 0x10
+
+#define ICW4_8086 0x01
+
+
+// PIC
+#define PICM_COMMAND 0x20
+#define PICM_DATA 0x21
+
+#define PICS_COMMAND 0xa0
+#define PICS_DATA 0xa1
+
+#define KERNEL_IDT_DESC_GATE(addr) \
+ ((struct idt_descriptor) { \
+ .offset_1 = (uint16_t)((uint64_t)addr & 0xffff), \
+ .offset_2 = (uint16_t)((uint64_t)addr >> 16), \
+ .offset_3 = (uint32_t)((uint64_t)addr >> 32), \
+ .segment = 0x8, \
+ .ist = 0, \
+ .type = INT_GATE_64, \
+ .priv = 0, \
+ .reserved = 0, \
+ .reserved_1 = 0, \
+ .reserved_2 = 0, \
+ .present = 1 \
+})
+
+#define GDT_ADDR (uint64_t)PHYS_TO_VIRT(0x7e22)
+
+#define IOAPICR_VER 1
+
+struct idt_descriptor {
+ uint16_t offset_1;
+ uint16_t segment;
+ unsigned int ist:3; //interupt stack table offset
+ unsigned int reserved:5;
+ unsigned int type:4;
+ unsigned int reserved_1:1;
+ unsigned int priv:2;
+ unsigned int present:1;
+ uint16_t offset_2;
+ uint32_t offset_3;
+ uint32_t reserved_2;
+} __attribute__((packed));
+
+
+struct segment_descriptor {
+ unsigned int priv:2;
+ unsigned int type:1;
+ unsigned int index:13;
+} __attribute__((packed));
+
+struct idt_reg {
+ uint16_t size;
+ uint64_t offset;
+} __attribute__((packed));
+
+struct gdt_reg {
+ uint16_t size;
+ uint64_t offset;
+} __attribute__((packed));
+
+struct idt_descriptor *idt;
+
+static struct idt_reg idtr;
+struct gdt_reg gdtr = {
+ .size = 0x17,
+ .offset = GDT_ADDR
+};
+
+
+lapic_t lapic; //would make this static but it's needed by timer.c
+static struct ioapic_fixedlen ioapic;
+static uint64_t isr_bitmap[4]; //first 32 is for exceptions;
+
+
+void disable_pic() {
+ //remapping PIC
+ outb_wait(PICM_COMMAND, ICW1_INIT | ICW1_ICW4); //initilizing
+ outb_wait(PICS_COMMAND, ICW1_INIT | ICW1_ICW4);
+
+ outb_wait(PICM_DATA, 32); //IRQ offsets
+ outb_wait(PICS_DATA, 40);
+
+ outb_wait(PICM_DATA, 4); //notify master of slave
+ outb_wait(PICS_DATA, 2); //nofity slave of mediocore social ethical standards
+
+ outb_wait(PICM_DATA, ICW4_8086);
+ outb_wait(PICS_DATA, ICW4_8086);
+
+
+ //masking.
+ outb_wait(PICS_DATA, 0xff);
+ outb_wait(PICM_DATA, 0xff);
+}
+
+void write_ioapic(void *ioapic_addr, uint32_t reg, uint32_t value) {
+ uint32_t *ioapic_r = ioapic_addr;
+ ioapic_r[0] = reg & 0xff;
+ ioapic_r[4] = value;
+}
+
+uint32_t read_ioapic(void *ioapic_addr, uint32_t reg) {
+ uint32_t *ioapic_r = ioapic_addr;
+ ioapic_r[0] = reg & 0xff;
+ return ioapic_r[4];
+}
+
+void create_fixed_interrupt(unsigned int irq, struct apic_vt *redirect) {
+ irq = irq_to_gsi(irq); //make sure there's no redirection entries.
+
+ struct ioapic_t *ioapic_smi = (void *)0;
+ for(unsigned int i = 0; i < ioapic.count; i++) {
+ if((irq >= ioapic.ioapic[i].gsi_base) &&
+ (irq < (ioapic.ioapic[i].gsi_base + ioapic.ioapic[i].gsi_count))) {
+ ioapic_smi = ioapic.ioapic[i].address;
+ break;
+ }
+ }
+ if(!ioapic_smi) PANIC(KERNEL_PANIC_INVALID_IOAPIC_VEC);
+
+
+ write_ioapic(ioapic_smi, (0x10 + (irq * 2)), *(uint32_t *)redirect);
+ write_ioapic(ioapic_smi, ((0x10 + (irq * 2)) + 1), *(uint64_t *)redirect >> 32);
+}
+
+unsigned int alloc_idt(struct idt_entry *entry) {
+ unsigned int b, i;
+ for(b = 0; b < (sizeof(isr_bitmap) / 8); b++) {
+ for(i = 0; i < 64; i++) {
+ if(!((isr_bitmap[b] >> i) & 1)) {
+ isr_bitmap[b] |= (uint64_t)1 << i;
+ idt[(b * 64) + i] = (struct idt_descriptor) {
+ .offset_1 = (uint16_t)((uint64_t)entry->addr & 0xffff),
+ .offset_2 = (uint16_t)((uint64_t)entry->addr >> 16),
+ .offset_3 = (uint32_t)((uint64_t)entry->addr >> 32),
+ .segment = 0x8,
+ .ist = entry->ist,
+ .type = entry->type,
+ .priv = entry->priv,
+ .reserved = 0,
+ .reserved_1 = 0,
+ .reserved_2 = 0,
+ .present = 1
+ };
+ return i;
+ }
+ }
+ }
+ return 0;
+}
+
+void modify_idt(struct idt_entry *entry, unsigned int vector) {
+ idt[vector] = (struct idt_descriptor) {
+ .offset_1 = (uint16_t)((uint64_t)entry->addr & 0xffff),
+ .offset_2 = (uint16_t)((uint64_t)entry->addr >> 16),
+ .offset_3 = (uint32_t)((uint64_t)entry->addr >> 32),
+ .segment = 0x8,
+ .ist = entry->ist,
+ .type = entry->type,
+ .priv = entry->priv,
+ .reserved = 0,
+ .reserved_1 = 0,
+ .reserved_2 = 0,
+ .present = 1
+ };
+}
+
+void free_idt(unsigned int entry) {
+ isr_bitmap[entry / 64] ^= ((uint64_t)1 << (entry & 63));
+ idt[entry].present = 0;
+}
+
+inline void clear_int() {
+ lapic[44] = 0;
+}
+
+
+void init_exceptions() {
+ //for idt index explainations, see include/panic.h
+ //TODO maybe utalize add_idt_entry?
+ unsigned int e;
+ idt[0] = KERNEL_IDT_DESC_GATE(fatal_hwexception);
+ idt[8] = KERNEL_IDT_DESC_GATE(fatal_hwexception_errcode);
+ idt[16] = KERNEL_IDT_DESC_GATE(fatal_hwexception);
+ idt[17] = KERNEL_IDT_DESC_GATE(fatal_hwexception_errcode);
+ idt[30] = KERNEL_IDT_DESC_GATE(fatal_hwexception_errcode);
+ for(e = 5; e < 8; e++) idt[e] = KERNEL_IDT_DESC_GATE(fatal_hwexception);
+ for(e = 10; e < 15; e++) idt[e] = KERNEL_IDT_DESC_GATE(fatal_hwexception_errcode);
+ for(e = 18; e < 21; e++) idt[e] = KERNEL_IDT_DESC_GATE(fatal_hwexception);
+}
+//void new_idt
+
+
+void init_interrupts() {
+ init_madt();
+ debug_madt();
+ lapic = get_lapic();
+
+ get_ioapic(&ioapic);
+ for(unsigned int i = 0; i < ioapic.count; i++) {
+ ioapic.ioapic[i].gsi_count = ((read_ioapic(ioapic.ioapic[i].address, IOAPICR_VER) >> 16) & 0xff);
+ printf("Found ioapic %i at addr %p, gsi %i to %i\n", i, ioapic.ioapic[i].address,
+ ioapic.ioapic[0].gsi_base, ioapic.ioapic[0].gsi_base + ioapic.ioapic[0].gsi_count);
+ }
+
+ disable_pic();
+
+ idt = palloc(0x1000);
+ idtr.size = 0x1000;
+ idtr.offset = (uint64_t)idt;
+
+ bzero(&isr_bitmap, sizeof(isr_bitmap));
+ isr_bitmap[0] = (((uint64_t)1 << 32) - 1);
+
+ //set idt and new gdt
+ asm("lgdt [%0]\n"
+ "lidt [%1]\n":: "m"(gdtr), "m"(idtr));
+
+
+ //Spurrious Interrupt (permanent, required for APIC)
+ idt[SPURRIOUS_VECTOR] = KERNEL_IDT_DESC_GATE(spurrious_int);
+
+ //Spurrious interrupt on IDT
+ lapic[60] = 0x1ff; //page 395
+
+ //initlize exceptions
+ init_exceptions();
+
+
+ //initilize the timers
+ init_timer();
+ asm("sti\n");
+}