//----------------------------------------------------------------------------// // GNU GPL OS/K // // // // Desc: Interrupt related functions // // // // // // Copyright © 2018-2019 The OS/K Team // // // // This file is part of OS/K. // // // // OS/K is free software: you can redistribute it and/or modify // // it under the terms of the GNU General Public License as published by // // the Free Software Foundation, either version 3 of the License, or // // any later version. // // // // OS/K is distributed in the hope that it will be useful, // // but WITHOUT ANY WARRANTY//without even the implied warranty of // // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // // GNU General Public License for more details. // // // // You should have received a copy of the GNU General Public License // // along with OS/K. If not, see . // //----------------------------------------------------------------------------// #include #include #include #include #include IdtEntry_t idt[256] = { 0 }; IdtPtr_t idtPtr; ISRList_t isrList = { 0 }; char *ExceptionsChar[32] = { "Divide Error Fault", "Debug Exception Trap", "Non-maskable Interrupt", "Breakpoint Trap", "Overflow Trap", "Bound Range Exceeded Fault", "Invalid Opcode Fault", "Device Not Available or No Math Coprocessor Fault", "Double Fault Abort", "Coprocessor Segment Overrun Fault (Legacy)", "Invalid TSS Fault", "Segment Not Present Fault", "Stack Segment fault", "General Protection Fault", "Page Fault", "Intel Reserved", "x87 FPU Floating Point or Math Fault", "Alignment Check Fault", "Machine Check Abort", "SIMD Floating Point Fault", "Virtualization Exception Fault", "Intel Reserved", "Intel Reserved", "Intel Reserved", "Intel Reserved", "Intel Reserved", "Intel Reserved", "Intel Reserved", "Intel Reserved", "Intel Reserved", "Security Exception", "Intel Reserved" }; static void EnablePIC(void); #define interrupt(n) asm volatile ("int %0" : : "N" (n) : "cc", "memory") // // Registers an isr with his IRQ to handle driver interrupts // error_t IdtRegisterIsr(void (*isr)(ISRFrame_t *regs), uchar isrNo) { uchar n = isrList.n; int OverWriting = 0; KalAssert(idt[0].flags!=0); // IDT initialized if (n == 0) goto settingUp; for (int i = 0; i < n; i++) { if (isrNo == isrList.entry[i].isrNo) { n = i; OverWriting++; break; } } if ((n == 255)) // IRQs not filled return ENOMEM; settingUp: isrList.entry[n].isr = isr; isrList.entry[n].isrNo = isrNo; if (!OverWriting) isrList.n++; return EOK; } // // Installs the IDT in order to activate the interrupts handling // void IdtSetup(void) { // XXX detect the APIC with cpuid ! EnablePIC(); ushort codeSeg = (ushort)(ulong)BtLoaderInfo.codeSegment; // Set IDT ptr idtPtr.limit = (sizeof(IdtEntry_t) * 256) - 1; idtPtr.base = &idt; // Set IDT Exception Gates IdtSetGate(0x00, (ulong)isr0, codeSeg, 0x8E); IdtSetGate(0x01, (ulong)isr1, codeSeg, 0x8E); IdtSetGate(0x02, (ulong)isr2, codeSeg, 0x8E); IdtSetGate(0x03, (ulong)isr3, codeSeg, 0x8E); IdtSetGate(0x04, (ulong)isr4, codeSeg, 0x8E); IdtSetGate(0x05, (ulong)isr5, codeSeg, 0x8E); IdtSetGate(0x06, (ulong)isr6, codeSeg, 0x8E); IdtSetGate(0x07, (ulong)isr7, codeSeg, 0x8E); IdtSetGate(0x08, (ulong)isr8, codeSeg, 0x8E); IdtSetGate(0x09, (ulong)isr9, codeSeg, 0x8E); IdtSetGate(0x0A, (ulong)isr10, codeSeg, 0x8E); IdtSetGate(0x0B, (ulong)isr11, codeSeg, 0x8E); IdtSetGate(0x0C, (ulong)isr12, codeSeg, 0x8E); IdtSetGate(0x0D, (ulong)isr13, codeSeg, 0x8E); IdtSetGate(0x0E, (ulong)isr14, codeSeg, 0x8E); IdtSetGate(0x0F, (ulong)isr15, codeSeg, 0x8E); // INTEL RESERVED IdtSetGate(0x10, (ulong)isr16, codeSeg, 0x8E); IdtSetGate(0x11, (ulong)isr17, codeSeg, 0x8E); IdtSetGate(0x12, (ulong)isr18, codeSeg, 0x8E); IdtSetGate(0x13, (ulong)isr19, codeSeg, 0x8E); IdtSetGate(0x14, (ulong)isr20, codeSeg, 0x8E); IdtSetGate(0x15, (ulong)isr21, codeSeg, 0x8E); // INTEL RESERVED IdtSetGate(0x16, (ulong)isr22, codeSeg, 0x8E); // INTEL RESERVED IdtSetGate(0x17, (ulong)isr23, codeSeg, 0x8E); // INTEL RESERVED IdtSetGate(0x18, (ulong)isr24, codeSeg, 0x8E); // INTEL RESERVED IdtSetGate(0x19, (ulong)isr25, codeSeg, 0x8E); // INTEL RESERVED IdtSetGate(0x1A, (ulong)isr26, codeSeg, 0x8E); // INTEL RESERVED IdtSetGate(0x1B, (ulong)isr27, codeSeg, 0x8E); // INTEL RESERVED IdtSetGate(0x1C, (ulong)isr28, codeSeg, 0x8E); // INTEL RESERVED IdtSetGate(0x1D, (ulong)isr29, codeSeg, 0x8E); // INTEL RESERVED IdtSetGate(0x1E, (ulong)isr30, codeSeg, 0x8E); // INTEL RESERVED IdtSetGate(0x1F, (ulong)isr31, codeSeg, 0x8E); // INTEL RESERVED // Set IDT IRQs Gates IdtSetGate(0x20, (ulong)isr32, codeSeg, 0x8E); IdtSetGate(0x21, (ulong)isr33, codeSeg, 0x8E); IdtSetGate(0x22, (ulong)isr34, codeSeg, 0x8E); IdtSetGate(0x23, (ulong)isr35, codeSeg, 0x8E); IdtSetGate(0x24, (ulong)isr36, codeSeg, 0x8E); IdtSetGate(0x25, (ulong)isr37, codeSeg, 0x8E); IdtSetGate(0x26, (ulong)isr38, codeSeg, 0x8E); IdtSetGate(0x27, (ulong)isr39, codeSeg, 0x8E); IdtSetGate(0x28, (ulong)isr40, codeSeg, 0x8E); IdtSetGate(0x29, (ulong)isr41, codeSeg, 0x8E); IdtSetGate(0x2A, (ulong)isr42, codeSeg, 0x8E); IdtSetGate(0x2B, (ulong)isr43, codeSeg, 0x8E); IdtSetGate(0x2C, (ulong)isr44, codeSeg, 0x8E); IdtSetGate(0x2D, (ulong)isr45, codeSeg, 0x8E); IdtSetGate(0x2E, (ulong)isr46, codeSeg, 0x8E); IdtSetGate(0x2F, (ulong)isr47, codeSeg, 0x8E); //Setup Early Exception handler for (uchar i = 0 ; i < 0x20 ; i++) { IdtRegisterIsr(IdtEarlyExceptionHandler, i); } // Load IDT IdtInit(); DebugLog("[IdtSetup] Initialized !\n"); } // // Set an interrupt gate // void IdtSetGate(uchar rank, ulong base, ushort selector, uchar flags) { // Set Base Address idt[rank].baseLow = base & 0xFFFF; idt[rank].baseMid = (base >> 16) & 0xFFFF; idt[rank].baseHigh = (base >> 32) & 0xFFFFFFFF; // Set Selector idt[rank].selector = selector; idt[rank].flags = flags; // Set Reserved Areas to Zero idt[rank].reservedIst = 0; idt[rank].reserved = 0; } // // Enable and initializes the PIC to work correctly // static void EnablePIC(void) { // Set ICW1 - begin init of the PIC IoWriteByteOnPort(0x20, 0x11); IoWriteByteOnPort(0xa0, 0x11); // Set ICW2 (IRQ base offsets) IoWriteByteOnPort(0x21, 0x20); //0x20 is the first free interrupt for IRQ0 IoWriteByteOnPort(0xa1, 0x28); // PIC2 is offseted to 0x28 // Set ICW3 IoWriteByteOnPort(0x21, 0x4); IoWriteByteOnPort(0xa1, 0x2); // Set ICW4 IoWriteByteOnPort(0x21, 0x1); IoWriteByteOnPort(0xa1, 0x1); // Set OCW1 (interrupt masks) IoWriteByteOnPort(0x21, 0xff); IoWriteByteOnPort(0xa1, 0xff); } // // Ends the current interrupt handling // void IoSendEOItoPIC(uchar isr) { if(isr >= 8) IoWriteByteOnPort(0xa0,0x20); IoWriteByteOnPort(0x20,0x20); } void IoEnableNMI(void) { IoWriteByteOnPort(0x70, IoReadByteFromPort(0x70) & 0x7F); } void IoDisableNMI(void) { IoWriteByteOnPort(0x70, IoReadByteFromPort(0x70) | 0x80); } // // The main ISR handler // void IsrHandler(ISRFrame_t *regs) { if ((!regs) || (!regs->rip)) KeStartPanic("[ISR ?] Unknown ISR Exception Abort\n"); if ((regs->intNo >= 0x15) && (regs->intNo <= 0x1F)) return; // INTEL RESERVED if (regs->intNo == 0x0F) return; // INTEL RESERVED for (int i = 0; i < isrList.n; i++) { if (regs->intNo == isrList.entry[i].isrNo) { isrList.entry[i].isr(regs); return; } } bprintf(BStdOut, "[ISR 0x%x] %s\n", regs->intNo, "Unknown ISR Exception"); BStdOut->flusher(BStdOut); IoSendEOItoPIC(regs->intNo); } // // Early CPU Exception handler // void IdtEarlyExceptionHandler(ISRFrame_t *regs) { int recoverable = 0; if (!recoverable) { KeStartPanic("[ISR 0x%x] Irrecoverable Kernel %s\n" " Error code : 0x%x\n" " RIP:\t\t%p\n" " CS:\t\t%p\n" " RFLAGS:\t%022b\n" " RSP:\t\t%p\n" " SS:\t\t%p\n", regs->intNo, ExceptionsChar[regs->intNo], regs->ErrorCode, regs->rip, regs->cs, regs->rflags, regs->rsp, regs->ss ); } else { bprintf(BStdOut, "[ISR 0x%x] %s\n", regs->intNo, ExceptionsChar[regs->intNo]); BStdOut->flusher(BStdOut); } }