From 9b22a6965579ea1867aea291d910c96f386b518b Mon Sep 17 00:00:00 2001 From: Brett Weiland Date: Tue, 24 Aug 2021 14:09:29 -0500 Subject: major backup 8.24.21 --- src/kernel/int.c | 253 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 253 insertions(+) create mode 100644 src/kernel/int.c (limited to 'src/kernel/int.c') 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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"); +} -- cgit v1.2.3