os-k/kaleid/kernel/cpu/idt.c

273 lines
9.2 KiB
C
Raw Normal View History

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
IRQList_t irqList = { 0 };
//
// Registers an isr with his IRQ to handle driver interrupts
//
2019-04-27 00:04:27 +02:00
void IdtRegisterIrq(void (*isr)(ISRFrame_t *regs), uchar irq, uchar flags)
{
2019-04-24 18:42:38 +02:00
uchar n = irqList.n;
2019-04-27 00:04:27 +02:00
KalAssert(idt[0].flags!=0); // IDT initialized
2019-04-24 21:08:44 +02:00
if ((n == 224)) // IRQs not filled
2019-04-24 18:42:38 +02:00
KeStartPanic("[IdtRegisterIrq] Cannot register IRQ %c function %p !",
irq,
isr
);
irqList.entry[n].isr = isr;
irqList.entry[n].irq = irq;
irqList.entry[n].flags = flags;
irqList.n++;
}
//
// 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;
// Set IDT Exception Gates
2019-04-23 17:06:03 +02:00
IdtSetGate(0, (ulong)isr0, codeSeg, 0x8E);
IdtSetGate(1, (ulong)isr1, codeSeg, 0x8E);
IdtSetGate(2, (ulong)isr2, codeSeg, 0x8E);
IdtSetGate(3, (ulong)isr3, codeSeg, 0x8E);
IdtSetGate(4, (ulong)isr4, codeSeg, 0x8E);
IdtSetGate(5, (ulong)isr5, codeSeg, 0x8E);
IdtSetGate(6, (ulong)isr6, codeSeg, 0x8E);
IdtSetGate(7, (ulong)isr7, codeSeg, 0x8E);
IdtSetGate(8, (ulong)isr8, codeSeg, 0x8E);
IdtSetGate(9, (ulong)isr9, codeSeg, 0x8E);
IdtSetGate(10, (ulong)isr10, codeSeg, 0x8E);
IdtSetGate(11, (ulong)isr11, codeSeg, 0x8E);
IdtSetGate(12, (ulong)isr12, codeSeg, 0x8E);
IdtSetGate(13, (ulong)isr13, codeSeg, 0x8E);
IdtSetGate(14, (ulong)isr14, codeSeg, 0x8E);
IdtSetGate(15, (ulong)isr15, codeSeg, 0x8E); // INTEL RESERVED
IdtSetGate(16, (ulong)isr16, codeSeg, 0x8E);
IdtSetGate(17, (ulong)isr17, codeSeg, 0x8E);
IdtSetGate(18, (ulong)isr18, codeSeg, 0x8E);
IdtSetGate(19, (ulong)isr19, codeSeg, 0x8E);
IdtSetGate(20, (ulong)isr20, codeSeg, 0x8E);
IdtSetGate(21, (ulong)isr21, codeSeg, 0x8E); // INTEL RESERVED
IdtSetGate(22, (ulong)isr22, codeSeg, 0x8E); // INTEL RESERVED
IdtSetGate(23, (ulong)isr23, codeSeg, 0x8E); // INTEL RESERVED
IdtSetGate(24, (ulong)isr24, codeSeg, 0x8E); // INTEL RESERVED
IdtSetGate(25, (ulong)isr25, codeSeg, 0x8E); // INTEL RESERVED
IdtSetGate(26, (ulong)isr26, codeSeg, 0x8E); // INTEL RESERVED
IdtSetGate(27, (ulong)isr27, codeSeg, 0x8E); // INTEL RESERVED
IdtSetGate(28, (ulong)isr28, codeSeg, 0x8E); // INTEL RESERVED
IdtSetGate(29, (ulong)isr29, codeSeg, 0x8E); // INTEL RESERVED
IdtSetGate(30, (ulong)isr30, codeSeg, 0x8E); // INTEL RESERVED
2019-04-24 21:08:44 +02:00
IdtSetGate(31, (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
IdtSetGate(32, (ulong)isr32, codeSeg, 0x8E);
IdtSetGate(33, (ulong)isr33, codeSeg, 0x8E);
IdtSetGate(34, (ulong)isr34, codeSeg, 0x8E);
IdtSetGate(35, (ulong)isr35, codeSeg, 0x8E);
IdtSetGate(36, (ulong)isr36, codeSeg, 0x8E);
IdtSetGate(37, (ulong)isr37, codeSeg, 0x8E);
IdtSetGate(38, (ulong)isr38, codeSeg, 0x8E);
IdtSetGate(39, (ulong)isr39, codeSeg, 0x8E);
IdtSetGate(40, (ulong)isr40, codeSeg, 0x8E);
IdtSetGate(41, (ulong)isr41, codeSeg, 0x8E);
IdtSetGate(42, (ulong)isr42, codeSeg, 0x8E);
IdtSetGate(43, (ulong)isr43, codeSeg, 0x8E);
IdtSetGate(44, (ulong)isr44, codeSeg, 0x8E);
IdtSetGate(45, (ulong)isr45, codeSeg, 0x8E);
IdtSetGate(46, (ulong)isr46, codeSeg, 0x8E);
IdtSetGate(47, (ulong)isr47, codeSeg, 0x8E);
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
//
// 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 18:42:38 +02:00
// Enable and initializes the PIC to work correctly
//
2019-04-24 18:42:38 +02:00
static void EnablePIC(void)
{
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);
}
//
// Ends the current interrupt handling
//
2019-04-24 23:00:12 +02:00
void IoSendEOItoPIC(uchar isr)
{
2019-04-24 21:08:44 +02:00
if(isr >= 8)
IoWriteByteOnPort(0xa0,0x20);
2019-04-24 21:08:44 +02:00
IoWriteByteOnPort(0x20,0x20);
}
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-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-04-27 00:38:47 +02:00
if ((regs->intNo >= 21) && (regs->intNo <= 31))
return; // INTEL RESERVED
if (regs->intNo == 15)
return; // INTEL RESERVED
2019-04-27 00:04:27 +02:00
if (regs->intNo < 32) {
IdtExceptionHandler(regs);
return;
}
for (int i = 0; i < irqList.n; i++) {
if (regs->intNo == irqList.entry[i].irq) {
irqList.entry[i].isr(regs);
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:38:47 +02:00
/* KeStartPanic("[ISR 0x%x] Unknown ISR Exception Abort\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, */
/* regs->ErrorCode, */
/* regs->rip, */
/* regs->cs, */
/* regs->rflags, */
/* regs->rsp, */
/* regs->ss */
/* ); */
2019-04-27 00:04:27 +02:00
}
//
// CPU Exception handler
//
2019-04-27 00:04:27 +02:00
void IdtExceptionHandler(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
char *exceptionMsg = "Unhandled ISR exception";
2019-04-27 00:04:27 +02:00
exceptionMsg = IsrExceptions[regs->intNo];
2019-04-23 17:06:03 +02:00
2019-04-26 10:36:40 +02:00
if (!recoverable) {
2019-04-27 00:04:27 +02:00
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,
exceptionMsg,
regs->ErrorCode,
regs->rip,
regs->cs,
regs->rflags,
regs->rsp,
regs->ss
);
2019-04-23 17:06:03 +02:00
} else {
2019-04-27 00:04:27 +02:00
bprintf(BStdOut, "[ISR 0x%x] %s\n", regs->intNo, exceptionMsg);
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
}