#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"); }