mirror of
https://gitlab.com/sortix/sortix.git
synced 2023-02-13 20:55:38 -05:00
Refactored interrupt system and got rid of old not-mine code.
This commit is contained in:
parent
4e05eb33d8
commit
3859e1f566
11 changed files with 162 additions and 153 deletions
|
@ -47,7 +47,7 @@ CPPFLAGS=-I.. -I. $(CPUDEFINES) $(CPUFLAGS) -std=gnu++0x -Wall -Wextra -nostdlib
|
|||
OBJS=$(CPUOBJS) \
|
||||
kernel.o \
|
||||
descriptor_tables.o \
|
||||
isr.o \
|
||||
interrupt.o \
|
||||
time.o \
|
||||
log.o \
|
||||
panic.o \
|
||||
|
|
|
@ -23,10 +23,8 @@
|
|||
******************************************************************************/
|
||||
|
||||
#include "platform.h"
|
||||
#include "iirqhandler.h"
|
||||
#include <libmaxsi/memory.h>
|
||||
#include "descriptor_tables.h"
|
||||
#include "isr.h"
|
||||
#include "panic.h"
|
||||
|
||||
using namespace Maxsi;
|
||||
|
|
123
sortix/interrupt.cpp
Normal file
123
sortix/interrupt.cpp
Normal file
|
@ -0,0 +1,123 @@
|
|||
/******************************************************************************
|
||||
|
||||
COPYRIGHT(C) JONAS 'SORTIE' TERMANSEN 2011.
|
||||
|
||||
This file is part of Sortix.
|
||||
|
||||
Sortix 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 (at your option) any later
|
||||
version.
|
||||
|
||||
Sortix 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 Sortix. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
interrupt.cpp
|
||||
High level interrupt service routines and interrupt request handlers.
|
||||
|
||||
******************************************************************************/
|
||||
|
||||
#include "platform.h"
|
||||
#include "log.h"
|
||||
#include "interrupt.h"
|
||||
#include "panic.h"
|
||||
|
||||
#include "process.h" // Hack for SIGSEGV
|
||||
#include "sound.h" // Hack for SIGSEGV
|
||||
|
||||
namespace Sortix
|
||||
{
|
||||
namespace Interrupt
|
||||
{
|
||||
size_t numknownexceptions = 19;
|
||||
const char* exceptions[] =
|
||||
{ "Divide by zero", "Debug", "Non maskable interrupt", "Breakpoint",
|
||||
"Into detected overflow", "Out of bounds", "Invalid opcode",
|
||||
"No coprocessor", "Double fault", "Coprocessor segment overrun",
|
||||
"Bad TSS", "Segment not present", "Stack fault",
|
||||
"General protection fault", "Page fault", "Unknown interrupt",
|
||||
"Coprocessor fault", "Alignment check", "Machine check" };
|
||||
|
||||
Handler interrupthandlers[256];
|
||||
|
||||
void RegisterHandler(uint8_t n, Interrupt::Handler handler)
|
||||
{
|
||||
interrupthandlers[n] = handler;
|
||||
}
|
||||
|
||||
// This gets called from our ASM interrupt handler stub.
|
||||
extern "C" void ISRHandler(Sortix::CPU::InterruptRegisters* regs)
|
||||
{
|
||||
#ifdef PLATFORM_X86
|
||||
if ( regs->int_no < 32 )
|
||||
{
|
||||
const char* message = ( regs->int_no < numknownexceptions )
|
||||
? exceptions[regs->int_no] : "Unknown";
|
||||
|
||||
// Halt and catch fire if we are the kernel.
|
||||
if ( (regs->cs & (0x4-1)) == 0 )
|
||||
{
|
||||
PanicF("Unhandled CPU Exception id %zu '%s' at eip=0x%zx "
|
||||
"(cr2=0x%p, err_code=0x%p)", regs->int_no, message,
|
||||
regs->eip, regs->cr2, regs->err_code);
|
||||
}
|
||||
|
||||
Log::Print("The current program has crashed and was terminated:\n");
|
||||
Log::PrintF("%s exception at eip=0x%zx (cr2=0x%p, err_code=0x%p)\n",
|
||||
message, regs->eip, regs->cr2, regs->err_code);
|
||||
|
||||
Sound::Mute();
|
||||
const char* programname = "sh";
|
||||
regs->ebx = (uint32_t) programname;
|
||||
SysExecute(regs);
|
||||
return;
|
||||
}
|
||||
|
||||
if ( interrupthandlers[regs->int_no] != NULL )
|
||||
{
|
||||
interrupthandlers[regs->int_no](regs);
|
||||
}
|
||||
#else
|
||||
#warning "ISR handlers are not supported on this arch"
|
||||
while(true);
|
||||
#endif
|
||||
}
|
||||
|
||||
// This gets called from our ASM interrupt handler stub.
|
||||
extern "C" void IRQHandler(Sortix::CPU::InterruptRegisters* regs)
|
||||
{
|
||||
#ifdef PLATFORM_X86
|
||||
// TODO! IRQ 7 and 15 might be spurious and might need to be ignored.
|
||||
// See http://wiki.osdev.org/PIC for details (section Spurious IRQs).
|
||||
if ( regs->int_no == 32 + 7 || regs->int_no == 32 + 15 ) { return; }
|
||||
|
||||
if ( regs->int_no < 32 || 48 < regs->int_no )
|
||||
{
|
||||
PanicF("IRQ eax=%u, int_no=%u, err_code=%u, eip=%u!",
|
||||
regs->eax, regs->int_no, regs->err_code, regs->eip);
|
||||
}
|
||||
|
||||
// Send an EOI (end of interrupt) signal to the PICs.
|
||||
|
||||
// Send reset signal to slave if this interrupt involved the slave.
|
||||
if (regs->int_no >= 40) { X86::OutPortB(0xA0, 0x20); }
|
||||
|
||||
// Send reset signal to master.
|
||||
X86::OutPortB(0x20, 0x20);
|
||||
|
||||
if ( interrupthandlers[regs->int_no] != NULL )
|
||||
{
|
||||
interrupthandlers[regs->int_no](regs);
|
||||
}
|
||||
#else
|
||||
#warning "IRQ handlers are not supported on this arch"
|
||||
while(true);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
|
@ -17,21 +17,39 @@
|
|||
You should have received a copy of the GNU General Public License along
|
||||
with Sortix. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
iirqhandler.h
|
||||
An interface for classes able to handle IRQs.
|
||||
|
||||
TODO: This is stupid. Get rid of this header and put the declaration
|
||||
someplace more intelligent.
|
||||
interrupt.h
|
||||
High level interrupt service routines and interrupt request handlers.
|
||||
|
||||
******************************************************************************/
|
||||
|
||||
#ifndef SORTIX_IIRQHANDLER_H
|
||||
#define SORTIX_IIRQHANDLER_H
|
||||
#ifndef SORTIX_ISR_H
|
||||
#define SORTIX_ISR_H
|
||||
|
||||
namespace Sortix
|
||||
{
|
||||
typedef void (*InterruptHandler)(CPU::InterruptRegisters* Registers);
|
||||
namespace Interrupt
|
||||
{
|
||||
const unsigned IRQ0 = 32;
|
||||
const unsigned IRQ1 = 33;
|
||||
const unsigned IRQ2 = 34;
|
||||
const unsigned IRQ3 = 35;
|
||||
const unsigned IRQ4 = 36;
|
||||
const unsigned IRQ5 = 37;
|
||||
const unsigned IRQ6 = 38;
|
||||
const unsigned IRQ7 = 39;
|
||||
const unsigned IRQ8 = 30;
|
||||
const unsigned IRQ9 = 41;
|
||||
const unsigned IRQ10 = 42;
|
||||
const unsigned IRQ11 = 43;
|
||||
const unsigned IRQ12 = 44;
|
||||
const unsigned IRQ13 = 45;
|
||||
const unsigned IRQ14 = 46;
|
||||
const unsigned IRQ15 = 47;
|
||||
|
||||
typedef void (*Handler)(CPU::InterruptRegisters* Registers);
|
||||
|
||||
void RegisterHandler(uint8_t n, Handler handler);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
100
sortix/isr.cpp
100
sortix/isr.cpp
|
@ -1,100 +0,0 @@
|
|||
//
|
||||
// isr.c -- High level interrupt service routines and interrupt request handlers.
|
||||
// Part of this code is modified from Bran's kernel development tutorials.
|
||||
// Rewritten for JamesM's kernel development tutorials.
|
||||
//
|
||||
|
||||
#include "platform.h"
|
||||
#include "iirqhandler.h"
|
||||
#include "log.h"
|
||||
#include "isr.h"
|
||||
#include "panic.h"
|
||||
|
||||
#include "process.h" // Hack for SIGSEGV
|
||||
#include "sound.h" // Hack for SIGSEGV
|
||||
|
||||
using namespace Sortix;
|
||||
|
||||
size_t numknownexceptions = 19;
|
||||
const char* exceptions[] = { "Divide by zero", "Debug", "Non maskable interrupt", "Breakpoint",
|
||||
"Into detected overflow", "Out of bounds", "Invalid opcode",
|
||||
"No coprocessor", "Double fault", "Coprocessor segment overrun",
|
||||
"Bad TSS", "Segment not present", "Stack fault",
|
||||
"General protection fault", "Page fault", "Unknown interrupt",
|
||||
"Coprocessor fault", "Alignment check", "Machine check" };
|
||||
|
||||
Sortix::InterruptHandler interrupt_handlers[256];
|
||||
|
||||
void register_interrupt_handler(uint8_t n, Sortix::InterruptHandler handler)
|
||||
{
|
||||
interrupt_handlers[n] = handler;
|
||||
}
|
||||
|
||||
// This gets called from our ASM interrupt handler stub.
|
||||
extern "C" void isr_handler(Sortix::CPU::InterruptRegisters* Regs)
|
||||
{
|
||||
#ifdef PLATFORM_X86
|
||||
if ( Regs->int_no < 32 )
|
||||
{
|
||||
const char* message = ( Regs->int_no < numknownexceptions )
|
||||
? exceptions[Regs->int_no] : "Unknown";
|
||||
|
||||
// Halt and catch fire if we are the kernel.
|
||||
if ( (Regs->cs & (0x4-1)) == 0 )
|
||||
{
|
||||
PanicF("Unhandled CPU Exception id %zu '%s' at eip=0x%zx "
|
||||
"(cr2=0x%p, err_code=0x%p)", Regs->int_no, message,
|
||||
Regs->eip, Regs->cr2, Regs->err_code);
|
||||
}
|
||||
|
||||
Log::Print("The current program has crashed and was terminated:\n");
|
||||
Log::PrintF("%s exception at eip=0x%zx (cr2=0x%p, err_code=0x%p)\n",
|
||||
message, Regs->eip, Regs->cr2, Regs->err_code);
|
||||
|
||||
Sound::Mute();
|
||||
const char* programname = "sh";
|
||||
Regs->ebx = (uint32_t) programname;
|
||||
SysExecute(Regs);
|
||||
return;
|
||||
}
|
||||
|
||||
if ( interrupt_handlers[Regs->int_no] != NULL )
|
||||
{
|
||||
interrupt_handlers[Regs->int_no](Regs);
|
||||
}
|
||||
#else
|
||||
#warning "ISR handlers are not supported on this arch"
|
||||
while(true);
|
||||
#endif
|
||||
}
|
||||
|
||||
// This gets called from our ASM interrupt handler stub.
|
||||
extern "C" void irq_handler(Sortix::CPU::InterruptRegisters* Regs)
|
||||
{
|
||||
#ifdef PLATFORM_X86
|
||||
if ( Regs->int_no != 32 && Regs->int_no != 33 )
|
||||
{
|
||||
//Sortix::Log::PrintF("IRQ eax=%u, int_no=%u, err_code=%u, eip=0x%x!\n", Regs->eax, Regs->int_no, Regs->err_code, Regs->eip);
|
||||
}
|
||||
|
||||
// TODO! IRQ 7 and 15 might be spurious and might need to be ignored.
|
||||
// See http://wiki.osdev.org/PIC for details (section Spurious IRQs).
|
||||
if ( Regs->int_no == 32 + 7 || Regs->int_no == 32 + 15 ) { return; }
|
||||
|
||||
if ( Regs->int_no < 32 || 48 < Regs->int_no ) { Sortix::PanicF("IRQ eax=%u, int_no=%u, err_code=%u, eip=%u!", Regs->eax, Regs->int_no, Regs->err_code, Regs->eip); }
|
||||
|
||||
|
||||
// Send an EOI (end of interrupt) signal to the PICs.
|
||||
if (Regs->int_no >= 40) { Sortix::X86::OutPortB(0xA0, 0x20); } // Send reset signal to slave if this interrupt involved the slave.
|
||||
Sortix::X86::OutPortB(0x20, 0x20); // Send reset signal to master.
|
||||
|
||||
if ( interrupt_handlers[Regs->int_no] != NULL )
|
||||
{
|
||||
interrupt_handlers[Regs->int_no](Regs);
|
||||
}
|
||||
#else
|
||||
#warning "IRQ handlers are not supported on this arch"
|
||||
while(true);
|
||||
#endif
|
||||
}
|
||||
|
26
sortix/isr.h
26
sortix/isr.h
|
@ -1,26 +0,0 @@
|
|||
//
|
||||
// isr.h -- Interface and structures for high level interrupt service routines.
|
||||
// Part of this code is modified from Bran's kernel development tutorials.
|
||||
// Rewritten for JamesM's kernel development tutorials.
|
||||
//
|
||||
|
||||
// A few defines to make life a little easier
|
||||
#define IRQ0 32
|
||||
#define IRQ1 33
|
||||
#define IRQ2 34
|
||||
#define IRQ3 35
|
||||
#define IRQ4 36
|
||||
#define IRQ5 37
|
||||
#define IRQ6 38
|
||||
#define IRQ7 39
|
||||
#define IRQ8 40
|
||||
#define IRQ9 41
|
||||
#define IRQ10 42
|
||||
#define IRQ11 43
|
||||
#define IRQ12 44
|
||||
#define IRQ13 45
|
||||
#define IRQ14 46
|
||||
#define IRQ15 47
|
||||
|
||||
void register_interrupt_handler(uint8_t n, Sortix::InterruptHandler handler);
|
||||
|
|
@ -29,7 +29,6 @@
|
|||
#include "log.h"
|
||||
#include "panic.h"
|
||||
#include "descriptor_tables.h"
|
||||
#include "iirqhandler.h"
|
||||
#include "time.h"
|
||||
#include "keyboard.h"
|
||||
#include "multiboot.h"
|
||||
|
|
|
@ -25,11 +25,10 @@
|
|||
#include "platform.h"
|
||||
#include <libmaxsi/memory.h>
|
||||
#include <libmaxsi/keyboard.h>
|
||||
#include "iirqhandler.h"
|
||||
#include "log.h"
|
||||
#include "panic.h"
|
||||
#include "keyboard.h"
|
||||
#include "isr.h"
|
||||
#include "interrupt.h"
|
||||
#include "process.h"
|
||||
#include "scheduler.h"
|
||||
|
||||
|
@ -634,7 +633,7 @@ namespace Sortix
|
|||
LEDs = 0;
|
||||
|
||||
// Register our keystroke callback.
|
||||
register_interrupt_handler(IRQ1, OnIRQ1);
|
||||
Interrupt::RegisterHandler(Interrupt::IRQ1, OnIRQ1);
|
||||
|
||||
// If any scancodes were already pending, our interrupt handler
|
||||
// will never be called. Let's just discard anything pending.
|
||||
|
|
|
@ -25,8 +25,7 @@
|
|||
#include "platform.h"
|
||||
#include "syscall.h"
|
||||
#include "scheduler.h"
|
||||
#include "iirqhandler.h"
|
||||
#include "isr.h"
|
||||
#include "interrupt.h"
|
||||
#include "log.h"
|
||||
#include "panic.h"
|
||||
#include "vga.h"
|
||||
|
@ -69,7 +68,7 @@ namespace Sortix
|
|||
|
||||
void Init()
|
||||
{
|
||||
register_interrupt_handler(0x80, &OnCall);
|
||||
Interrupt::RegisterHandler(0x80, &OnCall);
|
||||
}
|
||||
|
||||
void OnCall(CPU::InterruptRegisters* registers)
|
||||
|
|
|
@ -25,8 +25,7 @@
|
|||
|
||||
#include "platform.h"
|
||||
#include "time.h"
|
||||
#include "iirqhandler.h"
|
||||
#include "isr.h"
|
||||
#include "interrupt.h"
|
||||
#include "scheduler.h"
|
||||
#include "log.h"
|
||||
|
||||
|
@ -81,8 +80,8 @@ namespace Sortix
|
|||
Miliseconds = 0;
|
||||
|
||||
// First, register our timer callback.
|
||||
register_interrupt_handler(IRQ0, &OnIRQ0);
|
||||
register_interrupt_handler(177, &OnInt177);
|
||||
Interrupt::RegisterHandler(Interrupt::IRQ0, &OnIRQ0);
|
||||
Interrupt::RegisterHandler(177, &OnInt177);
|
||||
|
||||
didUglyIRQ0Hack = false;
|
||||
|
||||
|
|
|
@ -87,7 +87,7 @@ IRQ 14, 46
|
|||
IRQ 15, 47
|
||||
|
||||
; In isr.c
|
||||
extern isr_handler
|
||||
extern ISRHandler
|
||||
|
||||
; This is our common ISR stub. It saves the processor state, sets
|
||||
; up for kernel mode segments, calls the C-level fault handler,
|
||||
|
@ -108,7 +108,7 @@ isr_common_stub:
|
|||
|
||||
push esp
|
||||
|
||||
call isr_handler
|
||||
call ISRHandler
|
||||
|
||||
add esp, 8
|
||||
pop ebx ; reload the original data segment descriptor
|
||||
|
@ -123,7 +123,7 @@ isr_common_stub:
|
|||
iret ; pops 5 things at once: CS, EIP, EFLAGS, SS, and ESP
|
||||
|
||||
; In isr.c
|
||||
extern irq_handler
|
||||
extern IRQHandler
|
||||
|
||||
; This is our common IRQ stub. It saves the processor state, sets
|
||||
; up for kernel mode segments, calls the C-level fault handler,
|
||||
|
@ -144,7 +144,7 @@ irq_common_stub:
|
|||
|
||||
push esp
|
||||
|
||||
call irq_handler
|
||||
call IRQHandler
|
||||
|
||||
add esp, 8
|
||||
pop ebx ; reload the original data segment descriptor
|
||||
|
|
Loading…
Add table
Reference in a new issue