#include "inttypes.h" #include "string.h" #include "pvec.h" #include "console.h" #include "interrupts.h" #include "schedule.h" #include "fpu.h" #include "memory.h" #include "io.h" #include "gui.h" extern void isr0(); extern void isr1(); extern void isr2(); extern void isr3(); extern void isr4(); extern void isr5(); extern void isr6(); extern void isr7(); extern void isr8(); extern void isr9(); extern void isr10(); extern void isr11(); extern void isr12(); extern void isr13(); extern void isr14(); extern void isr15(); extern void isr16(); extern void isr17(); extern void isr18(); extern void isr19(); extern void isr20(); extern void isr21(); extern void isr22(); extern void isr23(); extern void isr24(); extern void isr25(); extern void isr26(); extern void isr27(); extern void isr28(); extern void isr29(); extern void isr30(); extern void isr31(); extern void irq0(); extern void irq1(); extern void irq2(); extern void irq3(); extern void irq4(); extern void irq5(); extern void irq6(); extern void irq7(); extern void irq8(); extern void irq9(); extern void irq10(); extern void irq11(); extern void irq12(); extern void irq13(); extern void irq14(); extern void irq15(); extern void irq16(); struct idt_entry { uint16_t base_lo; uint16_t sel; uint8_t always0; uint8_t flags; uint16_t base_hi; } __attribute__((packed)); extern void abort(); extern struct task_t *current_task; extern struct tss_t system_tss; extern void setIdt(struct idt_entry *, unsigned); struct idt_entry idt[256]; void idt_set_gate(uint8_t num, uint32_t base, uint16_t sel, uint8_t flags) { idt[num].base_lo = base & 0xffff; idt[num].sel = sel; idt[num].always0 = 0; idt[num].flags = flags; idt[num].base_hi = base >> 16 & 0xffff; } void init_idt() { memset((char *)idt, 0, sizeof(struct idt_entry) * 256); setIdt(idt, sizeof(struct idt_entry) * 256); } void init_isrs() { idt_set_gate(0, (uint32_t)isr0, 0x08, 0x8E); idt_set_gate(1, (uint32_t)isr1, 0x08, 0x8E); idt_set_gate(2, (uint32_t)isr2, 0x08, 0x8E); idt_set_gate(3, (uint32_t)isr3, 0x08, 0x8E); idt_set_gate(4, (uint32_t)isr4, 0x08, 0x8E); idt_set_gate(5, (uint32_t)isr5, 0x08, 0x8E); idt_set_gate(6, (uint32_t)isr6, 0x08, 0x8E); idt_set_gate(7, (uint32_t)isr7, 0x08, 0x8E); idt_set_gate(8, (uint32_t)isr8, 0x08, 0x8E); idt_set_gate(9, (uint32_t)isr9, 0x08, 0x8E); idt_set_gate(10, (uint32_t)isr10, 0x08, 0x8E); idt_set_gate(11, (uint32_t)isr11, 0x08, 0x8E); idt_set_gate(12, (uint32_t)isr12, 0x08, 0x8E); idt_set_gate(13, (uint32_t)isr13, 0x08, 0x8E); idt_set_gate(14, (uint32_t)isr14, 0x08, 0x8E); idt_set_gate(15, (uint32_t)isr15, 0x08, 0x8E); idt_set_gate(16, (uint32_t)isr16, 0x08, 0x8E); idt_set_gate(17, (uint32_t)isr17, 0x08, 0x8E); idt_set_gate(18, (uint32_t)isr18, 0x08, 0x8E); idt_set_gate(19, (uint32_t)isr19, 0x08, 0x8E); idt_set_gate(20, (uint32_t)isr20, 0x08, 0x8E); idt_set_gate(21, (uint32_t)isr21, 0x08, 0x8E); idt_set_gate(22, (uint32_t)isr22, 0x08, 0x8E); idt_set_gate(23, (uint32_t)isr23, 0x08, 0x8E); idt_set_gate(24, (uint32_t)isr24, 0x08, 0x8E); idt_set_gate(25, (uint32_t)isr25, 0x08, 0x8E); idt_set_gate(26, (uint32_t)isr26, 0x08, 0x8E); idt_set_gate(27, (uint32_t)isr27, 0x08, 0x8E); idt_set_gate(28, (uint32_t)isr28, 0x08, 0x8E); idt_set_gate(29, (uint32_t)isr29, 0x08, 0x8E); idt_set_gate(30, (uint32_t)isr30, 0x08, 0x8E); idt_set_gate(31, (uint32_t)isr31, 0x08, 0x8E); } extern uint32_t read_cr2(); void print_regs(struct regs *r) { kprintf("EIP: %p CS: %x\n", r->eip, r->cs); kprintf("EAX: %p, EBX: %p, ECX: %p, EDX: %p\n", r->eax, r->ebx, r->ecx, r->edx); kprintf("USER ESP: %p ERROR CODE: %p\n", r->useresp, r->err_code); kprintf("EDI: %p ESI:%p EBP:%p ESP: %p\n", r->edi, r->esi, r->ebp, r->esp); kprintf("GS %x, FS %x, ES %x, DS %x\n", r->gs, r->fs, r->es, r->ds); kprintf("INT NO: %d EFLAGS %x\n", r->int_no, r->eflags); if (current_task != NULL) { kprintf("PID: %d CR3 %p USR PAGES AT %p CNT %d\n", current_task->pid, current_task->cr3, current_task->user_pages_at, current_task->user_pages_cnt); kprintf("KSTACK: 0x%p USTACK: 0x%p TASK: %s\n", current_task->kstack, current_task->ustack, current_task->name); } // int i; /* struct task_t *task; int i, j; for (i=0;iuser_pages_cnt;i++) { task = current_task->next_task; while (task != NULL) { for (j=0;juser_pages_cnt;j++) { if (current_task->user_pages[i] == task->user_pages[j]) { kprintf("MATCH!\n"); } } task = task->next_task; } } */ } int fault_handler(struct regs *r) { if (r->int_no == 14) { // page fault uint32_t fault_address = read_cr2(); if (fault_address >= 0xd0000000 && fault_address < 0xe0000000) { if (!mem_map_krnl_page(fault_address & 0xFFFFF000)) { kprintf("Kernel Page Fault: %p\n", fault_address); print_regs(r); gui_flip(); while (1) ; } else { return 0; } } else if (fault_address >= 0x31000000 && fault_address < 0x32000000) { kprintf("Kernel Stack Page Fault: %p\n", fault_address); print_regs(r); gui_flip(); while (1) ; } else if (fault_address >= 0x40000000 && fault_address < 0xd0000000) { if (!mem_map_user_page(fault_address & 0xFFFFF000)) { kprintf("User Page Fault: %p\n", fault_address); print_regs(r); if (r->cs == 0x1b) { current_task->state = TASK_FINISHED; schedule(r); } gui_flip(); while (1) ; } else { return 0; } } else { if (r->cs == 0x1b) { kprintf("User Page Fault: %p\n", fault_address); print_regs(r); current_task->state = TASK_FINISHED; schedule(r); } kprintf("Kernel Page Fault: %p\n", fault_address); print_regs(r); gui_flip(); abort(); } } if (r->int_no == 6 || r->int_no == 7) { fpu_isr(r); return 0; } kprintf("Kernel Crash, fault no: %d\n", r->int_no); while (1) ; } // IRQS // static uint8_t master_mask = 0xFB; // static uint8_t slave_mask = 0xFF; struct isr_t { uint8_t enabled; uint8_t shared; uint8_t handlers; handler_t *handler; }; static struct isr_t irq_handlers[17]; void irq_clear_mask(uint8_t irq) { uint16_t port; uint8_t value; if (irq < 8) { port = 0x21; } else { port = 0xA1; irq -= 8; } value = inportb(port) & ~(1 << irq); outportb(port, value); } int irq_install_handler(int irq, handler_t handler, uint8_t shared) { handler_t *tmp; if (irq_handlers[irq].enabled != 0) { if (!shared || !irq_handlers[irq].shared) { return 0; } } if (!irq_handlers[irq].handlers) { irq_handlers[irq].handler = (handler_t *)dbmalloc(sizeof(handler_t), "irq install handler 1"); if (!irq_handlers[irq].handler) { return 0; } } else { tmp = (handler_t *)dbrealloc(irq_handlers[irq].handler, sizeof(handler_t) * (irq_handlers[irq].handlers + 1), "irq install handler 2"); if (!tmp) { return 0; } irq_handlers[irq].handler = tmp; } irq_handlers[irq].enabled = 1; irq_handlers[irq].shared = shared; irq_handlers[irq].handler[irq_handlers[irq].handlers] = handler; irq_handlers[irq].handlers++; if (irq > 7) { irq_clear_mask(2); } irq_clear_mask((uint8_t)irq); return 1; } void irq_uninstall_handler(int irq, handler_t handler) { handler_t *tmp; int i, j; for (i = 0; i < irq_handlers[irq].handlers; i++) { if (irq_handlers[irq].handler[i] == handler) { for (j = i; j < irq_handlers[irq].handlers - 1; j++) { irq_handlers[irq].handler[j] = irq_handlers[irq].handler[j + 1]; } tmp = (handler_t *)dbrealloc(irq_handlers[irq].handler, sizeof(handler_t) * (irq_handlers[irq].handlers - 1), "irq_uninstall handler 1"); if (!tmp) { abort(); } irq_handlers[irq].handler = tmp; break; } } irq_handlers[irq].handlers--; } static void io_wait2(void) { int i; for (i = 0; i < 5; i++) ; } void irq_remap(void) { uint8_t a1, a2; a1 = inportb(0x21); a2 = inportb(0xA1); outportb(0x20, 0x11); io_wait2(); outportb(0xA0, 0x11); io_wait2(); outportb(0x21, 0x20); io_wait2(); outportb(0xA1, 0x28); io_wait2(); outportb(0x21, 0x04); io_wait2(); outportb(0xA1, 0x02); io_wait2(); outportb(0x21, 0x01); io_wait2(); outportb(0xA1, 0x01); io_wait2(); outportb(0x21, a1); io_wait2(); outportb(0xA1, a2); io_wait2(); // outportb(0x21, 0xff); // outportb(0xA1, 0xff); } #define PIC1_CMD 0x20 #define PIC1_DATA 0x21 #define PIC2_CMD 0xA0 #define PIC2_DATA 0xA1 #define PIC_READ_IRR 0x0a /* OCW3 irq ready next CMD read */ #define PIC_READ_ISR 0x0b /* OCW3 irq service next CMD read */ /* Helper func */ static uint16_t __pic_get_irq_reg(int ocw3) { /* OCW3 to PIC CMD to get the register values. PIC2 is chained, and * represents IRQs 8-15. PIC1 is IRQs 0-7, with 2 being the chain */ outportb(PIC1_CMD, ocw3); outportb(PIC2_CMD, ocw3); return (inportb(PIC2_CMD) << 8) | inportb(PIC1_CMD); } /* Returns the combined value of the cascaded PICs irq request register */ uint16_t pic_get_irr(void) { return __pic_get_irq_reg(PIC_READ_IRR); } /* Returns the combined value of the cascaded PICs in-service register */ uint16_t pic_get_isr(void) { return __pic_get_irq_reg(PIC_READ_ISR); } void init_irqs(void) { int i; irq_remap(); idt_set_gate(32, (uint32_t)irq0, 0x08, 0x8E); idt_set_gate(33, (uint32_t)irq1, 0x08, 0x8E); idt_set_gate(34, (uint32_t)irq2, 0x08, 0x8E); idt_set_gate(35, (uint32_t)irq3, 0x08, 0x8E); idt_set_gate(36, (uint32_t)irq4, 0x08, 0x8E); idt_set_gate(37, (uint32_t)irq5, 0x08, 0x8E); idt_set_gate(38, (uint32_t)irq6, 0x08, 0x8E); idt_set_gate(39, (uint32_t)irq7, 0x08, 0x8E); idt_set_gate(40, (uint32_t)irq8, 0x08, 0x8E); idt_set_gate(41, (uint32_t)irq9, 0x08, 0x8E); idt_set_gate(42, (uint32_t)irq10, 0x08, 0x8E); idt_set_gate(43, (uint32_t)irq11, 0x08, 0x8E); idt_set_gate(44, (uint32_t)irq12, 0x08, 0x8E); idt_set_gate(45, (uint32_t)irq13, 0x08, 0x8E); idt_set_gate(46, (uint32_t)irq14, 0x08, 0x8E); idt_set_gate(47, (uint32_t)irq15, 0x08, 0x8E); idt_set_gate(48, (uint32_t)irq16, 0x08, 0xEE); // syscall for (i = 0; i < 17; i++) { irq_handlers[i].enabled = 0; } } int irq_handler(struct regs *r) { if (current_task != NULL) { current_task->eflags = r->eflags; } // kprintf("intterupt %d\n", r->int_no - 32); if (r->int_no - 32 == 7) { // is this a spurious interrupt? if (!(pic_get_isr() & (1 << 7))) { // kprintf("Spurious Interrupt 7\n"); return 0; } } if (r->int_no - 32 == 15) { // is this a spurious interrupt? if (!(pic_get_isr() & (1 << 15))) { outportb(0x20, 0x20); // kprintf("Spurious Interrupt 15\n"); return 0; } } if (irq_handlers[r->int_no - 32].enabled) { for (int i = 0; i < irq_handlers[r->int_no - 32].handlers; i++) { handler_t handler; handler = irq_handlers[r->int_no - 32].handler[i]; if (handler) { handler(r); } } } if (r->int_no - 32 >= 8) { outportb(0xA0, 0x20); } outportb(0x20, 0x20); return 0; }