diff --git a/sortix/Makefile b/sortix/Makefile index cdc371ad..42666c86 100644 --- a/sortix/Makefile +++ b/sortix/Makefile @@ -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 \ diff --git a/sortix/descriptor_tables.cpp b/sortix/descriptor_tables.cpp index f94c88d4..575333fe 100644 --- a/sortix/descriptor_tables.cpp +++ b/sortix/descriptor_tables.cpp @@ -23,10 +23,8 @@ ******************************************************************************/ #include "platform.h" -#include "iirqhandler.h" #include #include "descriptor_tables.h" -#include "isr.h" #include "panic.h" using namespace Maxsi; diff --git a/sortix/interrupt.cpp b/sortix/interrupt.cpp new file mode 100644 index 00000000..f661d712 --- /dev/null +++ b/sortix/interrupt.cpp @@ -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 . + + 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 + } + } +} diff --git a/sortix/iirqhandler.h b/sortix/interrupt.h similarity index 54% rename from sortix/iirqhandler.h rename to sortix/interrupt.h index c974f36a..013849cf 100644 --- a/sortix/iirqhandler.h +++ b/sortix/interrupt.h @@ -17,21 +17,39 @@ You should have received a copy of the GNU General Public License along with Sortix. If not, see . - 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 - diff --git a/sortix/isr.cpp b/sortix/isr.cpp deleted file mode 100644 index efe4b046..00000000 --- a/sortix/isr.cpp +++ /dev/null @@ -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 - } - diff --git a/sortix/isr.h b/sortix/isr.h deleted file mode 100644 index cdfee4b7..00000000 --- a/sortix/isr.h +++ /dev/null @@ -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); - diff --git a/sortix/kernel.cpp b/sortix/kernel.cpp index 32da950a..8c4fa951 100644 --- a/sortix/kernel.cpp +++ b/sortix/kernel.cpp @@ -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" diff --git a/sortix/keyboard.cpp b/sortix/keyboard.cpp index 09b646e2..7fbbc34d 100644 --- a/sortix/keyboard.cpp +++ b/sortix/keyboard.cpp @@ -25,11 +25,10 @@ #include "platform.h" #include #include -#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. diff --git a/sortix/syscall.cpp b/sortix/syscall.cpp index 227fb7ee..d61f79ad 100644 --- a/sortix/syscall.cpp +++ b/sortix/syscall.cpp @@ -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) diff --git a/sortix/time.cpp b/sortix/time.cpp index a4f79b4b..40a42583 100644 --- a/sortix/time.cpp +++ b/sortix/time.cpp @@ -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; diff --git a/sortix/x86/interrupt.asm b/sortix/x86/interrupt.asm index 83179bc3..0a806e0c 100644 --- a/sortix/x86/interrupt.asm +++ b/sortix/x86/interrupt.asm @@ -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