2019-03-25 23:10:06 +01:00
|
|
|
//----------------------------------------------------------------------------//
|
2019-04-23 17:06:03 +02:00
|
|
|
// 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 <https://www.gnu.org/licenses/>. //
|
2019-03-25 23:10:06 +01:00
|
|
|
//----------------------------------------------------------------------------//
|
|
|
|
|
2019-04-09 17:16:13 +02:00
|
|
|
#include <kernel/base.h>
|
2019-04-24 11:40:14 +02:00
|
|
|
#include <kernel/idt.h>
|
2019-04-22 20:15:32 +02:00
|
|
|
#include <kernel/boot.h>
|
2019-04-22 22:32:21 +02:00
|
|
|
#include <kernel/iomisc.h>
|
2019-04-23 17:06:03 +02:00
|
|
|
#include <extras/buf.h>
|
2019-04-01 23:51:48 +02:00
|
|
|
|
2019-04-22 20:15:32 +02:00
|
|
|
IdtEntry_t idt[256] = { 0 };
|
|
|
|
IdtPtr_t idtPtr;
|
2019-03-25 23:10:06 +01:00
|
|
|
|
2019-05-06 22:04:22 +02:00
|
|
|
ISRList_t isrList = { 0 };
|
2019-04-24 00:05:03 +02:00
|
|
|
|
2019-05-06 22:04:22 +02:00
|
|
|
char *ExceptionsChar[32] = {
|
2019-05-01 14:17:16 +02:00
|
|
|
"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")
|
2019-04-24 00:05:03 +02:00
|
|
|
|
|
|
|
//
|
|
|
|
// Registers an isr with his IRQ to handle driver interrupts
|
|
|
|
//
|
2019-05-06 22:04:22 +02:00
|
|
|
error_t IdtRegisterIsr(void (*isr)(ISRFrame_t *regs), uchar isrNo)
|
2019-04-24 00:05:03 +02:00
|
|
|
{
|
2019-05-06 22:04:22 +02:00
|
|
|
uchar n = isrList.n;
|
|
|
|
int OverWriting = 0;
|
2019-04-24 18:42:38 +02:00
|
|
|
|
2019-04-27 00:04:27 +02:00
|
|
|
KalAssert(idt[0].flags!=0); // IDT initialized
|
2019-04-24 00:05:03 +02:00
|
|
|
|
2019-05-06 22:04:22 +02:00
|
|
|
if (n == 0) goto settingUp;
|
2019-04-24 18:42:38 +02:00
|
|
|
|
2019-05-06 22:04:22 +02:00
|
|
|
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;
|
2019-04-24 00:05:03 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// Installs the IDT in order to activate the interrupts handling
|
|
|
|
//
|
2019-04-24 11:40:14 +02:00
|
|
|
void IdtSetup(void)
|
2019-04-22 20:15:32 +02:00
|
|
|
{
|
2019-04-23 17:06:03 +02:00
|
|
|
// XXX detect the APIC with cpuid !
|
2019-04-24 18:42:38 +02:00
|
|
|
EnablePIC();
|
2019-04-01 23:51:48 +02:00
|
|
|
|
2019-04-22 20:15:32 +02:00
|
|
|
ushort codeSeg = (ushort)(ulong)BtLoaderInfo.codeSegment;
|
|
|
|
|
|
|
|
// Set IDT ptr
|
|
|
|
idtPtr.limit = (sizeof(IdtEntry_t) * 256) - 1;
|
|
|
|
idtPtr.base = &idt;
|
|
|
|
|
2019-04-24 00:05:03 +02:00
|
|
|
// Set IDT Exception Gates
|
2019-05-06 22:04:22 +02:00
|
|
|
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
|
2019-04-22 20:15:32 +02:00
|
|
|
|
2019-04-27 00:04:27 +02:00
|
|
|
// Set IDT IRQs Gates
|
2019-05-06 22:04:22 +02:00
|
|
|
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);
|
|
|
|
}
|
2019-04-24 00:05:03 +02:00
|
|
|
|
2019-04-22 20:15:32 +02:00
|
|
|
// Load IDT
|
2019-04-24 18:42:38 +02:00
|
|
|
IdtInit();
|
2019-04-22 22:32:21 +02:00
|
|
|
DebugLog("[IdtSetup] Initialized !\n");
|
2019-03-25 23:10:06 +01:00
|
|
|
}
|
2019-04-22 17:19:53 +02:00
|
|
|
|
2019-04-24 00:05:03 +02:00
|
|
|
//
|
|
|
|
// Set an interrupt gate
|
|
|
|
//
|
2019-04-23 17:06:03 +02:00
|
|
|
void IdtSetGate(uchar rank, ulong base, ushort selector, uchar flags)
|
2019-04-22 20:15:32 +02:00
|
|
|
{
|
|
|
|
// 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;
|
|
|
|
}
|
2019-04-22 22:32:21 +02:00
|
|
|
|
2019-04-24 00:05:03 +02:00
|
|
|
//
|
2019-04-24 18:42:38 +02:00
|
|
|
// Enable and initializes the PIC to work correctly
|
2019-04-24 00:05:03 +02:00
|
|
|
//
|
2019-04-24 18:42:38 +02:00
|
|
|
static void EnablePIC(void)
|
2019-04-24 00:05:03 +02:00
|
|
|
{
|
2019-04-24 18:42:38 +02:00
|
|
|
// Set ICW1 - begin init of the PIC
|
2019-04-22 22:32:21 +02:00
|
|
|
IoWriteByteOnPort(0x20, 0x11);
|
|
|
|
IoWriteByteOnPort(0xa0, 0x11);
|
|
|
|
// Set ICW2 (IRQ base offsets)
|
2019-04-29 23:52:53 +02:00
|
|
|
IoWriteByteOnPort(0x21, 0x20); //0x20 is the first free interrupt for IRQ0
|
|
|
|
IoWriteByteOnPort(0xa1, 0x28); // PIC2 is offseted to 0x28
|
2019-04-22 22:32:21 +02:00
|
|
|
// Set ICW3
|
2019-04-28 15:30:54 +02:00
|
|
|
IoWriteByteOnPort(0x21, 0x4);
|
|
|
|
IoWriteByteOnPort(0xa1, 0x2);
|
2019-04-22 22:32:21 +02:00
|
|
|
// Set ICW4
|
2019-04-24 18:42:38 +02:00
|
|
|
IoWriteByteOnPort(0x21, 0x1);
|
|
|
|
IoWriteByteOnPort(0xa1, 0x1);
|
2019-04-22 22:32:21 +02:00
|
|
|
// Set OCW1 (interrupt masks)
|
|
|
|
IoWriteByteOnPort(0x21, 0xff);
|
|
|
|
IoWriteByteOnPort(0xa1, 0xff);
|
|
|
|
}
|
|
|
|
|
2019-04-24 00:05:03 +02:00
|
|
|
//
|
|
|
|
// Ends the current interrupt handling
|
|
|
|
//
|
2019-04-24 23:00:12 +02:00
|
|
|
void IoSendEOItoPIC(uchar isr)
|
2019-04-24 00:05:03 +02:00
|
|
|
{
|
2019-04-24 21:08:44 +02:00
|
|
|
if(isr >= 8)
|
|
|
|
IoWriteByteOnPort(0xa0,0x20);
|
2019-04-24 00:05:03 +02:00
|
|
|
|
2019-04-24 21:08:44 +02:00
|
|
|
IoWriteByteOnPort(0x20,0x20);
|
2019-04-24 00:05:03 +02:00
|
|
|
}
|
|
|
|
|
2019-04-24 23:00:12 +02:00
|
|
|
void IoEnableNMI(void)
|
|
|
|
{
|
|
|
|
IoWriteByteOnPort(0x70, IoReadByteFromPort(0x70) & 0x7F);
|
|
|
|
}
|
|
|
|
|
|
|
|
void IoDisableNMI(void)
|
|
|
|
{
|
|
|
|
IoWriteByteOnPort(0x70, IoReadByteFromPort(0x70) | 0x80);
|
|
|
|
}
|
|
|
|
|
2019-04-24 00:05:03 +02:00
|
|
|
//
|
2019-04-27 00:04:27 +02:00
|
|
|
// The main ISR handler
|
|
|
|
//
|
|
|
|
void IsrHandler(ISRFrame_t *regs)
|
|
|
|
{
|
|
|
|
if ((!regs) || (!regs->rip))
|
|
|
|
KeStartPanic("[ISR ?] Unknown ISR Exception Abort\n");
|
|
|
|
|
2019-05-06 22:04:22 +02:00
|
|
|
if ((regs->intNo >= 0x15) && (regs->intNo <= 0x1F))
|
2019-04-27 00:38:47 +02:00
|
|
|
return; // INTEL RESERVED
|
2019-05-06 22:04:22 +02:00
|
|
|
if (regs->intNo == 0x0F)
|
2019-04-27 00:38:47 +02:00
|
|
|
return; // INTEL RESERVED
|
|
|
|
|
2019-05-06 22:04:22 +02:00
|
|
|
for (int i = 0; i < isrList.n; i++) {
|
|
|
|
if (regs->intNo == isrList.entry[i].isrNo) {
|
|
|
|
isrList.entry[i].isr(regs);
|
2019-04-27 00:04:27 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-04-27 00:38:47 +02:00
|
|
|
bprintf(BStdOut, "[ISR 0x%x] %s\n", regs->intNo, "Unknown ISR Exception");
|
2019-04-29 23:51:25 +02:00
|
|
|
BStdOut->flusher(BStdOut);
|
2019-04-28 15:30:54 +02:00
|
|
|
IoSendEOItoPIC(regs->intNo);
|
2019-04-27 00:04:27 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//
|
2019-05-06 22:04:22 +02:00
|
|
|
// Early CPU Exception handler
|
2019-04-24 00:05:03 +02:00
|
|
|
//
|
2019-05-06 22:04:22 +02:00
|
|
|
void IdtEarlyExceptionHandler(ISRFrame_t *regs)
|
2019-04-22 22:32:21 +02:00
|
|
|
{
|
2019-04-26 10:36:40 +02:00
|
|
|
int recoverable = 0;
|
2019-04-23 17:06:03 +02:00
|
|
|
|
2019-04-26 10:36:40 +02:00
|
|
|
if (!recoverable) {
|
2019-05-07 18:09:40 +02:00
|
|
|
KeStartPanic("[ISR 0x%x] Irrecoverable Kernel %s\n\n"
|
|
|
|
" Error code : %p\n\n"
|
|
|
|
" RIP: %p CS: %p RSP: %p\n"
|
|
|
|
" SS: %p RAX: %p RBX: %p\n"
|
|
|
|
" RCX: %p RDX: %p RSI: %p\n"
|
|
|
|
" RDI: %p RBP: %p R8: %p\n"
|
|
|
|
" R9: %p R10: %p R11: %p\n"
|
|
|
|
" R12: %p R13: %p R14: %p\n"
|
|
|
|
" R15: %p RFLAGS: %022b",
|
2019-04-27 00:04:27 +02:00
|
|
|
regs->intNo,
|
2019-05-06 22:04:22 +02:00
|
|
|
ExceptionsChar[regs->intNo],
|
2019-04-27 00:04:27 +02:00
|
|
|
regs->ErrorCode,
|
|
|
|
regs->rip,
|
|
|
|
regs->cs,
|
|
|
|
regs->rsp,
|
2019-05-07 18:09:40 +02:00
|
|
|
regs->ss,
|
|
|
|
regs->regs[0],
|
|
|
|
regs->regs[1],
|
|
|
|
regs->regs[2],
|
|
|
|
regs->regs[3],
|
|
|
|
regs->regs[4],
|
|
|
|
regs->regs[5],
|
|
|
|
regs->regs[6],
|
|
|
|
regs->regs[7],
|
|
|
|
regs->regs[8],
|
|
|
|
regs->regs[9],
|
|
|
|
regs->regs[10],
|
|
|
|
regs->regs[11],
|
|
|
|
regs->regs[12],
|
|
|
|
regs->regs[13],
|
|
|
|
regs->regs[14],
|
|
|
|
regs->rflags
|
2019-05-01 14:17:16 +02:00
|
|
|
);
|
2019-05-07 18:09:40 +02:00
|
|
|
|
2019-04-23 17:06:03 +02:00
|
|
|
} else {
|
2019-05-06 22:04:22 +02:00
|
|
|
bprintf(BStdOut, "[ISR 0x%x] %s\n", regs->intNo, ExceptionsChar[regs->intNo]);
|
2019-04-29 23:51:25 +02:00
|
|
|
BStdOut->flusher(BStdOut);
|
2019-04-23 17:06:03 +02:00
|
|
|
}
|
2019-04-22 22:32:21 +02:00
|
|
|
}
|