Refactor i386 and x86_64 interrupt support.
This commit is contained in:
parent
d50e8f1bce
commit
a133a7717e
|
@ -45,6 +45,8 @@ ifdef X86FAMILY
|
||||||
$(CPU)/memorymanagement.o \
|
$(CPU)/memorymanagement.o \
|
||||||
x86-family/memorymanagement.o \
|
x86-family/memorymanagement.o \
|
||||||
$(CPU)/interrupt.o \
|
$(CPU)/interrupt.o \
|
||||||
|
x86-family/interrupt.o \
|
||||||
|
x86-family/pic.o \
|
||||||
x86-family/gdt.o \
|
x86-family/gdt.o \
|
||||||
x86-family/idt.o \
|
x86-family/idt.o \
|
||||||
$(CPU)/syscall.o \
|
$(CPU)/syscall.o \
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
|
|
||||||
Copyright(C) Jonas 'Sortie' Termansen 2011, 2012, 2013.
|
Copyright(C) Jonas 'Sortie' Termansen 2011, 2012, 2013, 2014.
|
||||||
|
|
||||||
This file is part of Sortix.
|
This file is part of Sortix.
|
||||||
|
|
||||||
|
@ -18,7 +18,7 @@
|
||||||
Sortix. If not, see <http://www.gnu.org/licenses/>.
|
Sortix. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
sortix/kernel/interrupt.h
|
sortix/kernel/interrupt.h
|
||||||
High level interrupt service routines and interrupt request handlers.
|
High level interrupt services.
|
||||||
|
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
|
|
||||||
|
@ -30,13 +30,17 @@
|
||||||
#include <sortix/kernel/decl.h>
|
#include <sortix/kernel/decl.h>
|
||||||
|
|
||||||
namespace Sortix {
|
namespace Sortix {
|
||||||
|
|
||||||
namespace CPU {
|
namespace CPU {
|
||||||
struct InterruptRegisters;
|
|
||||||
} // namespace CPU
|
|
||||||
|
|
||||||
|
struct InterruptRegisters;
|
||||||
|
|
||||||
|
} // namespace CPU
|
||||||
|
} // namespace Sortix
|
||||||
|
|
||||||
|
namespace Sortix {
|
||||||
namespace Interrupt {
|
namespace Interrupt {
|
||||||
|
|
||||||
|
#if defined(__i386__) || defined(__x86_64__)
|
||||||
const unsigned int IRQ0 = 32;
|
const unsigned int IRQ0 = 32;
|
||||||
const unsigned int IRQ1 = 33;
|
const unsigned int IRQ1 = 33;
|
||||||
const unsigned int IRQ2 = 34;
|
const unsigned int IRQ2 = 34;
|
||||||
|
@ -53,27 +57,60 @@ const unsigned int IRQ12 = 44;
|
||||||
const unsigned int IRQ13 = 45;
|
const unsigned int IRQ13 = 45;
|
||||||
const unsigned int IRQ14 = 46;
|
const unsigned int IRQ14 = 46;
|
||||||
const unsigned int IRQ15 = 47;
|
const unsigned int IRQ15 = 47;
|
||||||
|
#endif
|
||||||
|
|
||||||
extern "C" unsigned long asm_interrupts_are_enabled();
|
|
||||||
extern "C" unsigned long asm_is_cpu_interrupted;
|
extern "C" unsigned long asm_is_cpu_interrupted;
|
||||||
|
|
||||||
inline bool IsEnabled() { return asm_interrupts_are_enabled(); }
|
inline bool IsEnabled()
|
||||||
inline void Enable() { asm volatile("sti"); }
|
{
|
||||||
inline void Disable() { asm volatile("cli"); }
|
#if defined(__i386__) || defined(__x86_64__)
|
||||||
inline bool IsCPUInterrupted() { return asm_is_cpu_interrupted != 0; }
|
unsigned long is_enabled;
|
||||||
inline bool SetEnabled(bool isenabled)
|
asm("pushf\t\n"
|
||||||
|
"pop %0\t\n"
|
||||||
|
"and $0x000200, %0" : "=r"(is_enabled));
|
||||||
|
return is_enabled != 0;
|
||||||
|
#else
|
||||||
|
#warning "You need to implement checking if interrupts are on"
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void Enable()
|
||||||
|
{
|
||||||
|
#if defined(__i386__) || defined(__x86_64__)
|
||||||
|
asm volatile("sti");
|
||||||
|
#else
|
||||||
|
#warning "You need to implement enabling interrupts"
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void Disable()
|
||||||
|
{
|
||||||
|
#if defined(__i386__) || defined(__x86_64__)
|
||||||
|
asm volatile("cli");
|
||||||
|
#else
|
||||||
|
#warning "You need to implement disabling interrupts"
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool IsCPUInterrupted()
|
||||||
|
{
|
||||||
|
return asm_is_cpu_interrupted != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool SetEnabled(bool is_enabled)
|
||||||
{
|
{
|
||||||
bool wasenabled = IsEnabled();
|
bool wasenabled = IsEnabled();
|
||||||
if ( isenabled ) { Enable(); } else { Disable(); }
|
if ( is_enabled )
|
||||||
|
Enable();
|
||||||
|
else
|
||||||
|
Disable();
|
||||||
return wasenabled;
|
return wasenabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
typedef void (*Handler)(CPU::InterruptRegisters* regs, void* user);
|
typedef void (*Handler)(CPU::InterruptRegisters* regs, void* user);
|
||||||
void RegisterHandler(unsigned int index, Handler handler, void* user);
|
void RegisterHandler(unsigned int index, Handler handler, void* user);
|
||||||
|
|
||||||
typedef void (*RawHandler)(void);
|
|
||||||
void RegisterRawHandler(unsigned int index, RawHandler handler, bool userspace);
|
|
||||||
|
|
||||||
void Init();
|
void Init();
|
||||||
void InitWorker();
|
void InitWorker();
|
||||||
void WorkerThread(void* user);
|
void WorkerThread(void* user);
|
||||||
|
@ -84,57 +121,4 @@ bool ScheduleWork(WorkHandler handler, void* payload, size_t payloadsize);
|
||||||
} // namespace Interrupt
|
} // namespace Interrupt
|
||||||
} // namespace Sortix
|
} // namespace Sortix
|
||||||
|
|
||||||
extern "C" void isr0();
|
|
||||||
extern "C" void isr1();
|
|
||||||
extern "C" void isr2();
|
|
||||||
extern "C" void isr3();
|
|
||||||
extern "C" void isr4();
|
|
||||||
extern "C" void isr5();
|
|
||||||
extern "C" void isr6();
|
|
||||||
extern "C" void isr7();
|
|
||||||
extern "C" void isr8();
|
|
||||||
extern "C" void isr9();
|
|
||||||
extern "C" void isr10();
|
|
||||||
extern "C" void isr11();
|
|
||||||
extern "C" void isr12();
|
|
||||||
extern "C" void isr13();
|
|
||||||
extern "C" void isr14();
|
|
||||||
extern "C" void isr15();
|
|
||||||
extern "C" void isr16();
|
|
||||||
extern "C" void isr17();
|
|
||||||
extern "C" void isr18();
|
|
||||||
extern "C" void isr19();
|
|
||||||
extern "C" void isr20();
|
|
||||||
extern "C" void isr21();
|
|
||||||
extern "C" void isr22();
|
|
||||||
extern "C" void isr23();
|
|
||||||
extern "C" void isr24();
|
|
||||||
extern "C" void isr25();
|
|
||||||
extern "C" void isr26();
|
|
||||||
extern "C" void isr27();
|
|
||||||
extern "C" void isr28();
|
|
||||||
extern "C" void isr29();
|
|
||||||
extern "C" void isr30();
|
|
||||||
extern "C" void isr31();
|
|
||||||
extern "C" void isr128();
|
|
||||||
extern "C" void isr130();
|
|
||||||
extern "C" void isr131();
|
|
||||||
extern "C" void irq0();
|
|
||||||
extern "C" void irq1();
|
|
||||||
extern "C" void irq2();
|
|
||||||
extern "C" void irq3();
|
|
||||||
extern "C" void irq4();
|
|
||||||
extern "C" void irq5();
|
|
||||||
extern "C" void irq6();
|
|
||||||
extern "C" void irq7();
|
|
||||||
extern "C" void irq8();
|
|
||||||
extern "C" void irq9();
|
|
||||||
extern "C" void irq10();
|
|
||||||
extern "C" void irq11();
|
|
||||||
extern "C" void irq12();
|
|
||||||
extern "C" void irq13();
|
|
||||||
extern "C" void irq14();
|
|
||||||
extern "C" void irq15();
|
|
||||||
extern "C" void interrupt_handler_null();
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
|
|
||||||
Copyright(C) Jonas 'Sortie' Termansen 2011, 2012, 2013.
|
Copyright(C) Jonas 'Sortie' Termansen 2011, 2012, 2013, 2014.
|
||||||
|
|
||||||
This file is part of Sortix.
|
This file is part of Sortix.
|
||||||
|
|
||||||
|
@ -28,20 +28,26 @@
|
||||||
#include <sortix/kernel/decl.h>
|
#include <sortix/kernel/decl.h>
|
||||||
|
|
||||||
namespace Sortix {
|
namespace Sortix {
|
||||||
|
|
||||||
class Process;
|
class Process;
|
||||||
class Thread;
|
class Thread;
|
||||||
|
} // namespace Sortix
|
||||||
|
|
||||||
|
namespace Sortix {
|
||||||
namespace CPU {
|
namespace CPU {
|
||||||
struct InterruptRegisters;
|
struct InterruptRegisters;
|
||||||
} // namespace CPU
|
} // namespace CPU
|
||||||
|
} // namespace Sortix
|
||||||
|
|
||||||
|
namespace Sortix {
|
||||||
enum ThreadState { NONE, RUNNABLE, BLOCKING, DEAD };
|
enum ThreadState { NONE, RUNNABLE, BLOCKING, DEAD };
|
||||||
|
} // namespace Sortix
|
||||||
|
|
||||||
|
namespace Sortix {
|
||||||
namespace Scheduler {
|
namespace Scheduler {
|
||||||
|
|
||||||
void Init();
|
void Init();
|
||||||
void Switch(CPU::InterruptRegisters* regs);
|
void Switch(CPU::InterruptRegisters* regs);
|
||||||
|
#if defined(__i386__) || defined(__x86_64__)
|
||||||
inline static void Yield() { asm volatile ("int $129"); }
|
inline static void Yield() { asm volatile ("int $129"); }
|
||||||
__attribute__ ((noreturn))
|
__attribute__ ((noreturn))
|
||||||
inline static void ExitThread()
|
inline static void ExitThread()
|
||||||
|
@ -49,6 +55,7 @@ inline static void ExitThread()
|
||||||
asm volatile ("int $132");
|
asm volatile ("int $132");
|
||||||
__builtin_unreachable();
|
__builtin_unreachable();
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
void SetThreadState(Thread* thread, ThreadState state);
|
void SetThreadState(Thread* thread, ThreadState state);
|
||||||
ThreadState GetThreadState(Thread* thread);
|
ThreadState GetThreadState(Thread* thread);
|
||||||
void SetIdleThread(Thread* thread);
|
void SetIdleThread(Thread* thread);
|
||||||
|
@ -56,9 +63,10 @@ void SetDummyThreadOwner(Process* process);
|
||||||
void SetInitProcess(Process* init);
|
void SetInitProcess(Process* init);
|
||||||
Process* GetInitProcess();
|
Process* GetInitProcess();
|
||||||
Process* GetKernelProcess();
|
Process* GetKernelProcess();
|
||||||
|
void InterruptYieldCPU(CPU::InterruptRegisters* regs, void* user);
|
||||||
|
void ThreadExitCPU(CPU::InterruptRegisters* regs, void* user);
|
||||||
|
|
||||||
} // namespace Scheduler
|
} // namespace Scheduler
|
||||||
|
|
||||||
} // namespace Sortix
|
} // namespace Sortix
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
|
|
||||||
Copyright(C) Jonas 'Sortie' Termansen 2011, 2012, 2013.
|
Copyright(C) Jonas 'Sortie' Termansen 2011, 2012, 2013, 2014.
|
||||||
|
|
||||||
This file is part of Sortix.
|
This file is part of Sortix.
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
|
|
||||||
Copyright(C) Jonas 'Sortie' Termansen 2011, 2012, 2013.
|
Copyright(C) Jonas 'Sortie' Termansen 2011, 2012, 2013, 2014.
|
||||||
|
|
||||||
This file is part of Sortix.
|
This file is part of Sortix.
|
||||||
|
|
||||||
|
@ -38,6 +38,4 @@ void Register(size_t index, void* funcptr);
|
||||||
} // namespace Syscall
|
} // namespace Syscall
|
||||||
} // namespace Sortix
|
} // namespace Sortix
|
||||||
|
|
||||||
extern "C" void syscall_handler();
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
Sortix. If not, see <http://www.gnu.org/licenses/>.
|
Sortix. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
interrupt.cpp
|
interrupt.cpp
|
||||||
High level interrupt service routines and interrupt request handlers.
|
High level interrupt services.
|
||||||
|
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
|
|
||||||
|
@ -37,292 +37,9 @@
|
||||||
#include <sortix/kernel/syscall.h>
|
#include <sortix/kernel/syscall.h>
|
||||||
#include <sortix/kernel/thread.h>
|
#include <sortix/kernel/thread.h>
|
||||||
|
|
||||||
#include "x86-family/idt.h"
|
|
||||||
|
|
||||||
namespace Sortix {
|
namespace Sortix {
|
||||||
|
|
||||||
namespace Interrupt {
|
namespace Interrupt {
|
||||||
|
|
||||||
const uint16_t PIC_MASTER = 0x20;
|
|
||||||
const uint16_t PIC_SLAVE = 0xA0;
|
|
||||||
const uint16_t PIC_COMMAND = 0x00;
|
|
||||||
const uint16_t PIC_DATA = 0x01;
|
|
||||||
const uint8_t PIC_CMD_ENDINTR = 0x20;
|
|
||||||
const uint8_t PIC_ICW1_ICW4 = 0x01; // ICW4 (not) needed
|
|
||||||
const uint8_t PIC_ICW1_SINGLE = 0x02; // Single (cascade) mode
|
|
||||||
const uint8_t PIC_ICW1_INTERVAL4 = 0x04; // Call address interval 4 (8)
|
|
||||||
const uint8_t PIC_ICW1_LEVEL = 0x08; // Level triggered (edge) mode
|
|
||||||
const uint8_t PIC_CMD_INIT = 0x10;
|
|
||||||
const uint8_t PIC_MODE_8086 = 0x01; // 8086/88 (MCS-80/85) mode
|
|
||||||
const uint8_t PIC_MODE_AUTO = 0x02; // Auto (normal) EOI
|
|
||||||
const uint8_t PIC_MODE_BUF_SLAVE = 0x08; // Buffered mode/slave
|
|
||||||
const uint8_t PIC_MODE_BUF_MASTER = 0x0C; // Buffered mode/master
|
|
||||||
const uint8_t PIC_MODE_SFNM = 0x10; // Special fully nested (not)
|
|
||||||
|
|
||||||
extern "C" { unsigned long asm_is_cpu_interrupted = 0; }
|
|
||||||
const bool DEBUG_EXCEPTION = true;
|
|
||||||
const bool DEBUG_IRQ = false;
|
|
||||||
const bool DEBUG_ISR = false;
|
|
||||||
const bool CALLTRACE_KERNEL = false;
|
|
||||||
const bool CALLTRACE_USER = false;
|
|
||||||
const bool RUN_DEBUGGER_ON_CRASH = false;
|
|
||||||
|
|
||||||
const size_t NUM_KNOWN_EXCEPTIONS = 20;
|
|
||||||
const char* exceptions[] =
|
|
||||||
{
|
|
||||||
"Divide by zero", /* 0, 0x0 */
|
|
||||||
"Debug", /* 1, 0x1 */
|
|
||||||
"Non maskable interrupt", /* 2, 0x2 */
|
|
||||||
"Breakpoint", /* 3, 0x3 */
|
|
||||||
"Into detected overflow", /* 4, 0x4 */
|
|
||||||
"Out of bounds", /* 5, 0x5 */
|
|
||||||
"Invalid opcode", /* 6, 0x6 */
|
|
||||||
"No coprocessor", /* 7, 0x7 */
|
|
||||||
"Double fault", /* 8, 0x8 */
|
|
||||||
"Coprocessor segment overrun", /* 9, 0x9 */
|
|
||||||
"Bad TSS", /* 10, 0xA */
|
|
||||||
"Segment not present", /* 11, 0xB */
|
|
||||||
"Stack fault", /* 12, 0xC */
|
|
||||||
"General protection fault", /* 13, 0xD */
|
|
||||||
"Page fault", /* 14, 0xE */
|
|
||||||
"Unknown interrupt", /* 15, 0xF */
|
|
||||||
"Coprocessor fault", /* 16, 0x10 */
|
|
||||||
"Alignment check", /* 17, 0x11 */
|
|
||||||
"Machine check", /* 18, 0x12 */
|
|
||||||
"SIMD Floating-Point", /* 19, 0x13 */
|
|
||||||
};
|
|
||||||
|
|
||||||
const unsigned int NUM_INTERRUPTS = 256UL;
|
|
||||||
static Handler interrupt_handlers[NUM_INTERRUPTS];
|
|
||||||
static void* interrupt_handler_params[NUM_INTERRUPTS];
|
|
||||||
|
|
||||||
extern "C" void ReprogramPIC()
|
|
||||||
{
|
|
||||||
uint8_t master_mask = 0;
|
|
||||||
uint8_t slave_mask = 0;
|
|
||||||
CPU::OutPortB(PIC_MASTER + PIC_COMMAND, PIC_CMD_INIT | PIC_ICW1_ICW4);
|
|
||||||
CPU::OutPortB(PIC_SLAVE + PIC_COMMAND, PIC_CMD_INIT | PIC_ICW1_ICW4);
|
|
||||||
CPU::OutPortB(PIC_MASTER + PIC_DATA, IRQ0);
|
|
||||||
CPU::OutPortB(PIC_SLAVE + PIC_DATA, IRQ8);
|
|
||||||
CPU::OutPortB(PIC_MASTER + PIC_DATA, 0x04); // Slave PIC at IRQ2
|
|
||||||
CPU::OutPortB(PIC_SLAVE + PIC_DATA, 0x02); // Cascade Identity
|
|
||||||
CPU::OutPortB(PIC_MASTER + PIC_DATA, PIC_MODE_8086);
|
|
||||||
CPU::OutPortB(PIC_SLAVE + PIC_DATA, PIC_MODE_8086);
|
|
||||||
CPU::OutPortB(PIC_MASTER + PIC_DATA, master_mask);
|
|
||||||
CPU::OutPortB(PIC_SLAVE + PIC_DATA, slave_mask);
|
|
||||||
}
|
|
||||||
|
|
||||||
extern "C" void DeprogramPIC()
|
|
||||||
{
|
|
||||||
uint8_t master_mask = 0;
|
|
||||||
uint8_t slave_mask = 0;
|
|
||||||
CPU::OutPortB(PIC_MASTER + PIC_COMMAND, PIC_CMD_INIT | PIC_ICW1_ICW4);
|
|
||||||
CPU::OutPortB(PIC_SLAVE + PIC_COMMAND, PIC_CMD_INIT | PIC_ICW1_ICW4);
|
|
||||||
CPU::OutPortB(PIC_MASTER + PIC_DATA, 0x08);
|
|
||||||
CPU::OutPortB(PIC_SLAVE + PIC_DATA, 0x70);
|
|
||||||
CPU::OutPortB(PIC_MASTER + PIC_DATA, 0x04); // Slave PIC at IRQ2
|
|
||||||
CPU::OutPortB(PIC_SLAVE + PIC_DATA, 0x02); // Cascade Identity
|
|
||||||
CPU::OutPortB(PIC_MASTER + PIC_DATA, PIC_MODE_8086);
|
|
||||||
CPU::OutPortB(PIC_SLAVE + PIC_DATA, PIC_MODE_8086);
|
|
||||||
CPU::OutPortB(PIC_MASTER + PIC_DATA, master_mask);
|
|
||||||
CPU::OutPortB(PIC_SLAVE + PIC_DATA, slave_mask);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Init()
|
|
||||||
{
|
|
||||||
IDT::Init();
|
|
||||||
|
|
||||||
for ( unsigned int i = 0; i < NUM_INTERRUPTS; i++ )
|
|
||||||
{
|
|
||||||
interrupt_handlers[i] = NULL;
|
|
||||||
interrupt_handler_params[i] = NULL;
|
|
||||||
RegisterRawHandler(i, interrupt_handler_null, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remap the IRQ table on the PICs.
|
|
||||||
ReprogramPIC();
|
|
||||||
|
|
||||||
RegisterRawHandler(0, isr0, false);
|
|
||||||
RegisterRawHandler(1, isr1, false);
|
|
||||||
RegisterRawHandler(2, isr2, false);
|
|
||||||
RegisterRawHandler(3, isr3, false);
|
|
||||||
RegisterRawHandler(4, isr4, false);
|
|
||||||
RegisterRawHandler(5, isr5, false);
|
|
||||||
RegisterRawHandler(6, isr6, false);
|
|
||||||
RegisterRawHandler(7, isr7, false);
|
|
||||||
RegisterRawHandler(8, isr8, false);
|
|
||||||
RegisterRawHandler(9, isr9, false);
|
|
||||||
RegisterRawHandler(10, isr10, false);
|
|
||||||
RegisterRawHandler(11, isr11, false);
|
|
||||||
RegisterRawHandler(12, isr12, false);
|
|
||||||
RegisterRawHandler(13, isr13, false);
|
|
||||||
RegisterRawHandler(14, isr14, false);
|
|
||||||
RegisterRawHandler(15, isr15, false);
|
|
||||||
RegisterRawHandler(16, isr16, false);
|
|
||||||
RegisterRawHandler(17, isr17, false);
|
|
||||||
RegisterRawHandler(18, isr18, false);
|
|
||||||
RegisterRawHandler(19, isr19, false);
|
|
||||||
RegisterRawHandler(20, isr20, false);
|
|
||||||
RegisterRawHandler(21, isr21, false);
|
|
||||||
RegisterRawHandler(22, isr22, false);
|
|
||||||
RegisterRawHandler(23, isr23, false);
|
|
||||||
RegisterRawHandler(24, isr24, false);
|
|
||||||
RegisterRawHandler(25, isr25, false);
|
|
||||||
RegisterRawHandler(26, isr26, false);
|
|
||||||
RegisterRawHandler(27, isr27, false);
|
|
||||||
RegisterRawHandler(28, isr28, false);
|
|
||||||
RegisterRawHandler(29, isr29, false);
|
|
||||||
RegisterRawHandler(30, isr30, false);
|
|
||||||
RegisterRawHandler(31, isr31, false);
|
|
||||||
RegisterRawHandler(32, irq0, false);
|
|
||||||
RegisterRawHandler(33, irq1, false);
|
|
||||||
RegisterRawHandler(34, irq2, false);
|
|
||||||
RegisterRawHandler(35, irq3, false);
|
|
||||||
RegisterRawHandler(36, irq4, false);
|
|
||||||
RegisterRawHandler(37, irq5, false);
|
|
||||||
RegisterRawHandler(38, irq6, false);
|
|
||||||
RegisterRawHandler(39, irq7, false);
|
|
||||||
RegisterRawHandler(40, irq8, false);
|
|
||||||
RegisterRawHandler(41, irq9, false);
|
|
||||||
RegisterRawHandler(42, irq10, false);
|
|
||||||
RegisterRawHandler(43, irq11, false);
|
|
||||||
RegisterRawHandler(44, irq12, false);
|
|
||||||
RegisterRawHandler(45, irq13, false);
|
|
||||||
RegisterRawHandler(46, irq14, false);
|
|
||||||
RegisterRawHandler(47, irq15, false);
|
|
||||||
|
|
||||||
// TODO: Let the syscall.cpp code register this.
|
|
||||||
RegisterRawHandler(128, syscall_handler, true);
|
|
||||||
|
|
||||||
Interrupt::Enable();
|
|
||||||
}
|
|
||||||
|
|
||||||
void RegisterHandler(unsigned int index, Interrupt::Handler handler, void* user)
|
|
||||||
{
|
|
||||||
interrupt_handlers[index] = handler;
|
|
||||||
interrupt_handler_params[index] = user;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: This function contains magic IDT-related values!
|
|
||||||
void RegisterRawHandler(unsigned int index, RawHandler handler, bool userspace)
|
|
||||||
{
|
|
||||||
addr_t handler_entry = (addr_t) handler;
|
|
||||||
uint16_t sel = KCS;
|
|
||||||
uint8_t flags = 0x8E;
|
|
||||||
if ( userspace )
|
|
||||||
flags |= 0x60;
|
|
||||||
IDT::SetEntry(index, handler_entry, sel, flags);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CrashHandler(CPU::InterruptRegisters* regs)
|
|
||||||
{
|
|
||||||
CurrentThread()->SaveRegisters(regs);
|
|
||||||
|
|
||||||
const char* message = regs->int_no < NUM_KNOWN_EXCEPTIONS
|
|
||||||
? exceptions[regs->int_no] : "Unknown";
|
|
||||||
|
|
||||||
if ( DEBUG_EXCEPTION )
|
|
||||||
{
|
|
||||||
regs->LogRegisters();
|
|
||||||
Log::Print("\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined(__x86_64__)
|
|
||||||
addr_t ip = regs->rip;
|
|
||||||
#elif defined(__i386__)
|
|
||||||
addr_t ip = regs->eip;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Halt and catch fire if we are the kernel.
|
|
||||||
unsigned code_mode = regs->cs & 0x3;
|
|
||||||
bool is_in_kernel = !code_mode;
|
|
||||||
bool is_in_user = !is_in_kernel;
|
|
||||||
|
|
||||||
if ( (is_in_kernel && CALLTRACE_KERNEL) || (is_in_user && CALLTRACE_USER) )
|
|
||||||
#if defined(__x86_64__)
|
|
||||||
Calltrace::Perform(regs->rbp);
|
|
||||||
#elif defined(__i386__)
|
|
||||||
Calltrace::Perform(regs->ebp);
|
|
||||||
#else
|
|
||||||
#error Please provide a calltrace implementation for your CPU.
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if ( RUN_DEBUGGER_ON_CRASH )
|
|
||||||
Debugger::Run();
|
|
||||||
|
|
||||||
if ( is_in_kernel )
|
|
||||||
{
|
|
||||||
PanicF("Unhandled CPU Exception id %zu '%s' at ip=0x%zx "
|
|
||||||
"(cr2=0x%p, err_code=0x%p)", regs->int_no, message,
|
|
||||||
ip, regs->cr2, regs->err_code);
|
|
||||||
}
|
|
||||||
|
|
||||||
Interrupt::Enable();
|
|
||||||
|
|
||||||
Log::PrintF("The current program (pid %ji %s) has crashed and was terminated:\n",
|
|
||||||
(intmax_t) CurrentProcess()->pid, CurrentProcess()->program_image_path);
|
|
||||||
Log::PrintF("%s exception at ip=0x%zx (cr2=0x%p, err_code=0x%p)\n",
|
|
||||||
message, ip, regs->cr2, regs->err_code);
|
|
||||||
|
|
||||||
// Exit the process with the right error code.
|
|
||||||
// TODO: Sent a SIGINT, SIGBUS, or whatever instead.
|
|
||||||
CurrentProcess()->Exit(139);
|
|
||||||
|
|
||||||
Interrupt::Disable();
|
|
||||||
Signal::Dispatch(regs);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ISRHandler(CPU::InterruptRegisters* regs)
|
|
||||||
{
|
|
||||||
unsigned int int_no = regs->int_no;
|
|
||||||
|
|
||||||
if ( DEBUG_ISR )
|
|
||||||
{
|
|
||||||
Log::PrintF("ISR%u ", int_no);
|
|
||||||
regs->LogRegisters();
|
|
||||||
Log::Print("\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Run the desired interrupt handler.
|
|
||||||
if ( int_no < 32 && int_no != 7 )
|
|
||||||
CrashHandler(regs);
|
|
||||||
else if ( interrupt_handlers[regs->int_no] != NULL )
|
|
||||||
interrupt_handlers[int_no](regs, interrupt_handler_params[int_no]);
|
|
||||||
}
|
|
||||||
|
|
||||||
void IRQHandler(CPU::InterruptRegisters* regs)
|
|
||||||
{
|
|
||||||
// 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 ( DEBUG_IRQ )
|
|
||||||
{
|
|
||||||
Log::PrintF("IRQ%u ", regs->int_no-32);
|
|
||||||
regs->LogRegisters();
|
|
||||||
Log::Print("\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int int_no = regs->int_no;
|
|
||||||
|
|
||||||
// Send an EOI (end of interrupt) signal to the PICs.
|
|
||||||
if ( IRQ8 <= int_no )
|
|
||||||
CPU::OutPortB(PIC_SLAVE, PIC_CMD_ENDINTR);
|
|
||||||
CPU::OutPortB(PIC_MASTER, PIC_CMD_ENDINTR);
|
|
||||||
|
|
||||||
if ( interrupt_handlers[int_no] )
|
|
||||||
interrupt_handlers[int_no](regs, interrupt_handler_params[int_no]);
|
|
||||||
}
|
|
||||||
|
|
||||||
extern "C" void interrupt_handler(CPU::InterruptRegisters* regs)
|
|
||||||
{
|
|
||||||
if ( 32 <= regs->int_no && regs->int_no < 48 )
|
|
||||||
IRQHandler(regs);
|
|
||||||
else
|
|
||||||
ISRHandler(regs);
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: This implementation is a bit hacky and can be optimized.
|
// TODO: This implementation is a bit hacky and can be optimized.
|
||||||
|
|
||||||
uint8_t* queue;
|
uint8_t* queue;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
|
|
||||||
Copyright(C) Jonas 'Sortie' Termansen 2011, 2012, 2013.
|
Copyright(C) Jonas 'Sortie' Termansen 2011, 2012, 2013, 2014.
|
||||||
|
|
||||||
This file is part of Sortix.
|
This file is part of Sortix.
|
||||||
|
|
||||||
|
@ -187,12 +187,12 @@ void LogEndSwitch(Thread* current, const CPU::InterruptRegisters* regs)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void InterruptYieldCPU(CPU::InterruptRegisters* regs, void* /*user*/)
|
void InterruptYieldCPU(CPU::InterruptRegisters* regs, void* /*user*/)
|
||||||
{
|
{
|
||||||
Switch(regs);
|
Switch(regs);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ThreadExitCPU(CPU::InterruptRegisters* regs, void* /*user*/)
|
void ThreadExitCPU(CPU::InterruptRegisters* regs, void* /*user*/)
|
||||||
{
|
{
|
||||||
// Can't use floating point instructions from now.
|
// Can't use floating point instructions from now.
|
||||||
Float::NofityTaskExit(currentthread);
|
Float::NofityTaskExit(currentthread);
|
||||||
|
@ -298,9 +298,6 @@ static int sys_usleep(size_t usecs)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" void yield_cpu_handler();
|
|
||||||
extern "C" void thread_exit_handler();
|
|
||||||
|
|
||||||
void Init()
|
void Init()
|
||||||
{
|
{
|
||||||
premagic = postmagic = SCHED_MAGIC;
|
premagic = postmagic = SCHED_MAGIC;
|
||||||
|
@ -317,13 +314,6 @@ void Init()
|
||||||
firstsleepingthread = NULL;
|
firstsleepingthread = NULL;
|
||||||
idlethread = NULL;
|
idlethread = NULL;
|
||||||
|
|
||||||
// Register our raw handler with user-space access. It calls our real
|
|
||||||
// handler after common interrupt preparation stuff has occured.
|
|
||||||
Interrupt::RegisterRawHandler(129, yield_cpu_handler, true);
|
|
||||||
Interrupt::RegisterHandler(129, InterruptYieldCPU, NULL);
|
|
||||||
Interrupt::RegisterRawHandler(132, thread_exit_handler, true);
|
|
||||||
Interrupt::RegisterHandler(132, ThreadExitCPU, NULL);
|
|
||||||
|
|
||||||
Syscall::Register(SYSCALL_SLEEP, (void*) sys_sleep);
|
Syscall::Register(SYSCALL_SLEEP, (void*) sys_sleep);
|
||||||
Syscall::Register(SYSCALL_USLEEP, (void*) sys_usleep);
|
Syscall::Register(SYSCALL_USLEEP, (void*) sys_usleep);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
|
|
||||||
Copyright(C) Jonas 'Sortie' Termansen 2011, 2012.
|
Copyright(C) Jonas 'Sortie' Termansen 2011, 2012, 2013, 2014.
|
||||||
|
|
||||||
This file is part of Sortix.
|
This file is part of Sortix.
|
||||||
|
|
||||||
|
@ -127,10 +127,6 @@ void Return(CPU::InterruptRegisters* regs, void* /*user*/)
|
||||||
|
|
||||||
void Init()
|
void Init()
|
||||||
{
|
{
|
||||||
Interrupt::RegisterRawHandler(130, isr130, true);
|
|
||||||
Interrupt::RegisterHandler(130, Dispatch, NULL);
|
|
||||||
Interrupt::RegisterRawHandler(131, isr131, true);
|
|
||||||
Interrupt::RegisterHandler(131, Return, NULL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Signal
|
} // namespace Signal
|
||||||
|
|
|
@ -27,371 +27,318 @@
|
||||||
.global isr0
|
.global isr0
|
||||||
.type isr0, @function
|
.type isr0, @function
|
||||||
isr0:
|
isr0:
|
||||||
cli
|
|
||||||
pushq $0 # err_code
|
pushq $0 # err_code
|
||||||
pushq $0 # int_no
|
pushq $0 # int_no
|
||||||
jmp interrupt_handler_prepare
|
jmp interrupt_handler_prepare
|
||||||
.global isr1
|
.global isr1
|
||||||
.type isr1, @function
|
.type isr1, @function
|
||||||
isr1:
|
isr1:
|
||||||
cli
|
|
||||||
pushq $0 # err_code
|
pushq $0 # err_code
|
||||||
pushq $1 # int_no
|
pushq $1 # int_no
|
||||||
jmp interrupt_handler_prepare
|
jmp interrupt_handler_prepare
|
||||||
.global isr2
|
.global isr2
|
||||||
.type isr2, @function
|
.type isr2, @function
|
||||||
isr2:
|
isr2:
|
||||||
cli
|
|
||||||
pushq $0 # err_code
|
pushq $0 # err_code
|
||||||
pushq $2 # int_no
|
pushq $2 # int_no
|
||||||
jmp interrupt_handler_prepare
|
jmp interrupt_handler_prepare
|
||||||
.global isr3
|
.global isr3
|
||||||
.type isr3, @function
|
.type isr3, @function
|
||||||
isr3:
|
isr3:
|
||||||
cli
|
|
||||||
pushq $0 # err_code
|
pushq $0 # err_code
|
||||||
pushq $3 # int_no
|
pushq $3 # int_no
|
||||||
jmp interrupt_handler_prepare
|
jmp interrupt_handler_prepare
|
||||||
.global isr4
|
.global isr4
|
||||||
.type isr4, @function
|
.type isr4, @function
|
||||||
isr4:
|
isr4:
|
||||||
cli
|
|
||||||
pushq $0 # err_code
|
pushq $0 # err_code
|
||||||
pushq $4 # int_no
|
pushq $4 # int_no
|
||||||
jmp interrupt_handler_prepare
|
jmp interrupt_handler_prepare
|
||||||
.global isr5
|
.global isr5
|
||||||
.type isr5, @function
|
.type isr5, @function
|
||||||
isr5:
|
isr5:
|
||||||
cli
|
|
||||||
pushq $0 # err_code
|
pushq $0 # err_code
|
||||||
pushq $5 # int_no
|
pushq $5 # int_no
|
||||||
jmp interrupt_handler_prepare
|
jmp interrupt_handler_prepare
|
||||||
.global isr6
|
.global isr6
|
||||||
.type isr6, @function
|
.type isr6, @function
|
||||||
isr6:
|
isr6:
|
||||||
cli
|
|
||||||
pushq $0 # err_code
|
pushq $0 # err_code
|
||||||
pushq $6 # int_no
|
pushq $6 # int_no
|
||||||
jmp interrupt_handler_prepare
|
jmp interrupt_handler_prepare
|
||||||
.global isr7
|
.global isr7
|
||||||
.type isr7, @function
|
.type isr7, @function
|
||||||
isr7:
|
isr7:
|
||||||
cli
|
|
||||||
pushq $0 # err_code
|
pushq $0 # err_code
|
||||||
pushq $7 # int_no
|
pushq $7 # int_no
|
||||||
jmp interrupt_handler_prepare
|
jmp interrupt_handler_prepare
|
||||||
.global isr8
|
.global isr8
|
||||||
.type isr8, @function
|
.type isr8, @function
|
||||||
isr8:
|
isr8:
|
||||||
cli
|
|
||||||
# pushq $0 # err_code pushed by CPU
|
# pushq $0 # err_code pushed by CPU
|
||||||
pushq $8 # int_no
|
pushq $8 # int_no
|
||||||
jmp interrupt_handler_prepare
|
jmp interrupt_handler_prepare
|
||||||
.global isr9
|
.global isr9
|
||||||
.type isr9, @function
|
.type isr9, @function
|
||||||
isr9:
|
isr9:
|
||||||
cli
|
|
||||||
pushq $0 # err_code
|
pushq $0 # err_code
|
||||||
pushq $9 # int_no
|
pushq $9 # int_no
|
||||||
jmp interrupt_handler_prepare
|
jmp interrupt_handler_prepare
|
||||||
.global isr10
|
.global isr10
|
||||||
.type isr10, @function
|
.type isr10, @function
|
||||||
isr10:
|
isr10:
|
||||||
cli
|
|
||||||
# pushq $0 # err_code pushed by CPU
|
# pushq $0 # err_code pushed by CPU
|
||||||
pushq $10 # int_no
|
pushq $10 # int_no
|
||||||
jmp interrupt_handler_prepare
|
jmp interrupt_handler_prepare
|
||||||
.global isr11
|
.global isr11
|
||||||
.type isr11, @function
|
.type isr11, @function
|
||||||
isr11:
|
isr11:
|
||||||
cli
|
|
||||||
# pushq $0 # err_code pushed by CPU
|
# pushq $0 # err_code pushed by CPU
|
||||||
pushq $11 # int_no
|
pushq $11 # int_no
|
||||||
jmp interrupt_handler_prepare
|
jmp interrupt_handler_prepare
|
||||||
.global isr12
|
.global isr12
|
||||||
.type isr12, @function
|
.type isr12, @function
|
||||||
isr12:
|
isr12:
|
||||||
cli
|
|
||||||
# pushq $0 # err_code pushed by CPU
|
# pushq $0 # err_code pushed by CPU
|
||||||
pushq $12 # int_no
|
pushq $12 # int_no
|
||||||
jmp interrupt_handler_prepare
|
jmp interrupt_handler_prepare
|
||||||
.global isr13
|
.global isr13
|
||||||
.type isr13, @function
|
.type isr13, @function
|
||||||
isr13:
|
isr13:
|
||||||
cli
|
|
||||||
# pushq $0 # err_code pushed by CPU
|
# pushq $0 # err_code pushed by CPU
|
||||||
pushq $13 # int_no
|
pushq $13 # int_no
|
||||||
jmp interrupt_handler_prepare
|
jmp interrupt_handler_prepare
|
||||||
.global isr14
|
.global isr14
|
||||||
.type isr14, @function
|
.type isr14, @function
|
||||||
isr14:
|
isr14:
|
||||||
cli
|
|
||||||
# pushq $0 # err_code pushed by CPU
|
# pushq $0 # err_code pushed by CPU
|
||||||
pushq $14 # int_no
|
pushq $14 # int_no
|
||||||
jmp interrupt_handler_prepare
|
jmp interrupt_handler_prepare
|
||||||
.global isr15
|
.global isr15
|
||||||
.type isr15, @function
|
.type isr15, @function
|
||||||
isr15:
|
isr15:
|
||||||
cli
|
|
||||||
pushq $0 # err_code
|
pushq $0 # err_code
|
||||||
pushq $15 # int_no
|
pushq $15 # int_no
|
||||||
jmp interrupt_handler_prepare
|
jmp interrupt_handler_prepare
|
||||||
.global isr16
|
.global isr16
|
||||||
.type isr16, @function
|
.type isr16, @function
|
||||||
isr16:
|
isr16:
|
||||||
cli
|
|
||||||
pushq $0 # err_code
|
pushq $0 # err_code
|
||||||
pushq $16 # int_no
|
pushq $16 # int_no
|
||||||
jmp interrupt_handler_prepare
|
jmp interrupt_handler_prepare
|
||||||
.global isr17
|
.global isr17
|
||||||
.type isr17, @function
|
.type isr17, @function
|
||||||
isr17:
|
isr17:
|
||||||
cli
|
|
||||||
pushq $0 # err_code
|
pushq $0 # err_code
|
||||||
pushq $17 # int_no
|
pushq $17 # int_no
|
||||||
jmp interrupt_handler_prepare
|
jmp interrupt_handler_prepare
|
||||||
.global isr18
|
.global isr18
|
||||||
.type isr18, @function
|
.type isr18, @function
|
||||||
isr18:
|
isr18:
|
||||||
cli
|
|
||||||
pushq $0 # err_code
|
pushq $0 # err_code
|
||||||
pushq $18 # int_no
|
pushq $18 # int_no
|
||||||
jmp interrupt_handler_prepare
|
jmp interrupt_handler_prepare
|
||||||
.global isr19
|
.global isr19
|
||||||
.type isr19, @function
|
.type isr19, @function
|
||||||
isr19:
|
isr19:
|
||||||
cli
|
|
||||||
pushq $0 # err_code
|
pushq $0 # err_code
|
||||||
pushq $19 # int_no
|
pushq $19 # int_no
|
||||||
jmp interrupt_handler_prepare
|
jmp interrupt_handler_prepare
|
||||||
.global isr20
|
.global isr20
|
||||||
.type isr20, @function
|
.type isr20, @function
|
||||||
isr20:
|
isr20:
|
||||||
cli
|
|
||||||
pushq $0 # err_code
|
pushq $0 # err_code
|
||||||
pushq $20 # int_no
|
pushq $20 # int_no
|
||||||
jmp interrupt_handler_prepare
|
jmp interrupt_handler_prepare
|
||||||
.global isr21
|
.global isr21
|
||||||
.type isr21, @function
|
.type isr21, @function
|
||||||
isr21:
|
isr21:
|
||||||
cli
|
|
||||||
pushq $0 # err_code
|
pushq $0 # err_code
|
||||||
pushq $21 # int_no
|
pushq $21 # int_no
|
||||||
jmp interrupt_handler_prepare
|
jmp interrupt_handler_prepare
|
||||||
.global isr22
|
.global isr22
|
||||||
.type isr22, @function
|
.type isr22, @function
|
||||||
isr22:
|
isr22:
|
||||||
cli
|
|
||||||
pushq $0 # err_code
|
pushq $0 # err_code
|
||||||
pushq $22 # int_no
|
pushq $22 # int_no
|
||||||
jmp interrupt_handler_prepare
|
jmp interrupt_handler_prepare
|
||||||
.global isr23
|
.global isr23
|
||||||
.type isr23, @function
|
.type isr23, @function
|
||||||
isr23:
|
isr23:
|
||||||
cli
|
|
||||||
pushq $0 # err_code
|
pushq $0 # err_code
|
||||||
pushq $23 # int_no
|
pushq $23 # int_no
|
||||||
jmp interrupt_handler_prepare
|
jmp interrupt_handler_prepare
|
||||||
.global isr24
|
.global isr24
|
||||||
.type isr24, @function
|
.type isr24, @function
|
||||||
isr24:
|
isr24:
|
||||||
cli
|
|
||||||
pushq $0 # err_code
|
pushq $0 # err_code
|
||||||
pushq $24 # int_no
|
pushq $24 # int_no
|
||||||
jmp interrupt_handler_prepare
|
jmp interrupt_handler_prepare
|
||||||
.global isr25
|
.global isr25
|
||||||
.type isr25, @function
|
.type isr25, @function
|
||||||
isr25:
|
isr25:
|
||||||
cli
|
|
||||||
pushq $0 # err_code
|
pushq $0 # err_code
|
||||||
pushq $25 # int_no
|
pushq $25 # int_no
|
||||||
jmp interrupt_handler_prepare
|
jmp interrupt_handler_prepare
|
||||||
.global isr26
|
.global isr26
|
||||||
.type isr26, @function
|
.type isr26, @function
|
||||||
isr26:
|
isr26:
|
||||||
cli
|
|
||||||
pushq $0 # err_code
|
pushq $0 # err_code
|
||||||
pushq $26 # int_no
|
pushq $26 # int_no
|
||||||
jmp interrupt_handler_prepare
|
jmp interrupt_handler_prepare
|
||||||
.global isr27
|
.global isr27
|
||||||
.type isr27, @function
|
.type isr27, @function
|
||||||
isr27:
|
isr27:
|
||||||
cli
|
|
||||||
pushq $0 # err_code
|
pushq $0 # err_code
|
||||||
pushq $27 # int_no
|
pushq $27 # int_no
|
||||||
jmp interrupt_handler_prepare
|
jmp interrupt_handler_prepare
|
||||||
.global isr28
|
.global isr28
|
||||||
.type isr28, @function
|
.type isr28, @function
|
||||||
isr28:
|
isr28:
|
||||||
cli
|
|
||||||
pushq $0 # err_code
|
pushq $0 # err_code
|
||||||
pushq $28 # int_no
|
pushq $28 # int_no
|
||||||
jmp interrupt_handler_prepare
|
jmp interrupt_handler_prepare
|
||||||
.global isr29
|
.global isr29
|
||||||
.type isr29, @function
|
.type isr29, @function
|
||||||
isr29:
|
isr29:
|
||||||
cli
|
|
||||||
pushq $0 # err_code
|
pushq $0 # err_code
|
||||||
pushq $29 # int_no
|
pushq $29 # int_no
|
||||||
jmp interrupt_handler_prepare
|
jmp interrupt_handler_prepare
|
||||||
.global isr30
|
.global isr30
|
||||||
.type isr30, @function
|
.type isr30, @function
|
||||||
isr30:
|
isr30:
|
||||||
cli
|
|
||||||
pushq $0 # err_code
|
pushq $0 # err_code
|
||||||
pushq $30 # int_no
|
pushq $30 # int_no
|
||||||
jmp interrupt_handler_prepare
|
jmp interrupt_handler_prepare
|
||||||
.global isr31
|
.global isr31
|
||||||
.type isr31, @function
|
.type isr31, @function
|
||||||
isr31:
|
isr31:
|
||||||
cli
|
|
||||||
pushq $0 # err_code
|
pushq $0 # err_code
|
||||||
pushq $31 # int_no
|
pushq $31 # int_no
|
||||||
jmp interrupt_handler_prepare
|
jmp interrupt_handler_prepare
|
||||||
.global isr128
|
.global isr128
|
||||||
.type isr128, @function
|
.type isr128, @function
|
||||||
isr128:
|
isr128:
|
||||||
cli
|
|
||||||
pushq $0 # err_code
|
pushq $0 # err_code
|
||||||
pushq $128 # int_no
|
pushq $128 # int_no
|
||||||
jmp interrupt_handler_prepare
|
jmp interrupt_handler_prepare
|
||||||
.global isr130
|
.global isr130
|
||||||
.type isr130, @function
|
.type isr130, @function
|
||||||
isr130:
|
isr130:
|
||||||
cli
|
|
||||||
pushq $0 # err_code
|
pushq $0 # err_code
|
||||||
pushq $130 # int_no
|
pushq $130 # int_no
|
||||||
jmp interrupt_handler_prepare
|
jmp interrupt_handler_prepare
|
||||||
.global isr131
|
.global isr131
|
||||||
.type isr131, @function
|
.type isr131, @function
|
||||||
isr131:
|
isr131:
|
||||||
cli
|
|
||||||
pushq $0 # err_code
|
pushq $0 # err_code
|
||||||
pushq $131 # int_no
|
pushq $131 # int_no
|
||||||
jmp interrupt_handler_prepare
|
jmp interrupt_handler_prepare
|
||||||
.global irq0
|
.global irq0
|
||||||
.type irq0, @function
|
.type irq0, @function
|
||||||
irq0:
|
irq0:
|
||||||
cli
|
|
||||||
pushq $0 # err_code
|
pushq $0 # err_code
|
||||||
pushq $32 # int_no
|
pushq $32 # int_no
|
||||||
jmp interrupt_handler_prepare
|
jmp interrupt_handler_prepare
|
||||||
.global irq1
|
.global irq1
|
||||||
.type irq1, @function
|
.type irq1, @function
|
||||||
irq1:
|
irq1:
|
||||||
cli
|
|
||||||
pushq $0 # err_code
|
pushq $0 # err_code
|
||||||
pushq $33 # int_no
|
pushq $33 # int_no
|
||||||
jmp interrupt_handler_prepare
|
jmp interrupt_handler_prepare
|
||||||
.global irq2
|
.global irq2
|
||||||
.type irq2, @function
|
.type irq2, @function
|
||||||
irq2:
|
irq2:
|
||||||
cli
|
|
||||||
pushq $0 # err_code
|
pushq $0 # err_code
|
||||||
pushq $34 # int_no
|
pushq $34 # int_no
|
||||||
jmp interrupt_handler_prepare
|
jmp interrupt_handler_prepare
|
||||||
.global irq3
|
.global irq3
|
||||||
.type irq3, @function
|
.type irq3, @function
|
||||||
irq3:
|
irq3:
|
||||||
cli
|
|
||||||
pushq $0 # err_code
|
pushq $0 # err_code
|
||||||
pushq $35 # int_no
|
pushq $35 # int_no
|
||||||
jmp interrupt_handler_prepare
|
jmp interrupt_handler_prepare
|
||||||
.global irq4
|
.global irq4
|
||||||
.type irq4, @function
|
.type irq4, @function
|
||||||
irq4:
|
irq4:
|
||||||
cli
|
|
||||||
pushq $0 # err_code
|
pushq $0 # err_code
|
||||||
pushq $36 # int_no
|
pushq $36 # int_no
|
||||||
jmp interrupt_handler_prepare
|
jmp interrupt_handler_prepare
|
||||||
.global irq5
|
.global irq5
|
||||||
.type irq5, @function
|
.type irq5, @function
|
||||||
irq5:
|
irq5:
|
||||||
cli
|
|
||||||
pushq $0 # err_code
|
pushq $0 # err_code
|
||||||
pushq $37 # int_no
|
pushq $37 # int_no
|
||||||
jmp interrupt_handler_prepare
|
jmp interrupt_handler_prepare
|
||||||
.global irq6
|
.global irq6
|
||||||
.type irq6, @function
|
.type irq6, @function
|
||||||
irq6:
|
irq6:
|
||||||
cli
|
|
||||||
pushq $0 # err_code
|
pushq $0 # err_code
|
||||||
pushq $38 # int_no
|
pushq $38 # int_no
|
||||||
jmp interrupt_handler_prepare
|
jmp interrupt_handler_prepare
|
||||||
.global irq7
|
.global irq7
|
||||||
.type irq7, @function
|
.type irq7, @function
|
||||||
irq7:
|
irq7:
|
||||||
cli
|
|
||||||
pushq $0 # err_code
|
pushq $0 # err_code
|
||||||
pushq $39 # int_no
|
pushq $39 # int_no
|
||||||
jmp interrupt_handler_prepare
|
jmp interrupt_handler_prepare
|
||||||
.global irq8
|
.global irq8
|
||||||
.type irq8, @function
|
.type irq8, @function
|
||||||
irq8:
|
irq8:
|
||||||
cli
|
|
||||||
pushq $0 # err_code
|
pushq $0 # err_code
|
||||||
pushq $40 # int_no
|
pushq $40 # int_no
|
||||||
jmp interrupt_handler_prepare
|
jmp interrupt_handler_prepare
|
||||||
.global irq9
|
.global irq9
|
||||||
.type irq9, @function
|
.type irq9, @function
|
||||||
irq9:
|
irq9:
|
||||||
cli
|
|
||||||
pushq $0 # err_code
|
pushq $0 # err_code
|
||||||
pushq $41 # int_no
|
pushq $41 # int_no
|
||||||
jmp interrupt_handler_prepare
|
jmp interrupt_handler_prepare
|
||||||
.global irq10
|
.global irq10
|
||||||
.type irq10, @function
|
.type irq10, @function
|
||||||
irq10:
|
irq10:
|
||||||
cli
|
|
||||||
pushq $0 # err_code
|
pushq $0 # err_code
|
||||||
pushq $42 # int_no
|
pushq $42 # int_no
|
||||||
jmp interrupt_handler_prepare
|
jmp interrupt_handler_prepare
|
||||||
.global irq11
|
.global irq11
|
||||||
.type irq11, @function
|
.type irq11, @function
|
||||||
irq11:
|
irq11:
|
||||||
cli
|
|
||||||
pushq $0 # err_code
|
pushq $0 # err_code
|
||||||
pushq $43 # int_no
|
pushq $43 # int_no
|
||||||
jmp interrupt_handler_prepare
|
jmp interrupt_handler_prepare
|
||||||
.global irq12
|
.global irq12
|
||||||
.type irq12, @function
|
.type irq12, @function
|
||||||
irq12:
|
irq12:
|
||||||
cli
|
|
||||||
pushq $0 # err_code
|
pushq $0 # err_code
|
||||||
pushq $44 # int_no
|
pushq $44 # int_no
|
||||||
jmp interrupt_handler_prepare
|
jmp interrupt_handler_prepare
|
||||||
.global irq13
|
.global irq13
|
||||||
.type irq13, @function
|
.type irq13, @function
|
||||||
irq13:
|
irq13:
|
||||||
cli
|
|
||||||
pushq $0 # err_code
|
pushq $0 # err_code
|
||||||
pushq $45 # int_no
|
pushq $45 # int_no
|
||||||
jmp interrupt_handler_prepare
|
jmp interrupt_handler_prepare
|
||||||
.global irq14
|
.global irq14
|
||||||
.type irq14, @function
|
.type irq14, @function
|
||||||
irq14:
|
irq14:
|
||||||
cli
|
|
||||||
pushq $0 # err_code
|
pushq $0 # err_code
|
||||||
pushq $46 # int_no
|
pushq $46 # int_no
|
||||||
jmp interrupt_handler_prepare
|
jmp interrupt_handler_prepare
|
||||||
.global irq15
|
.global irq15
|
||||||
.type irq15, @function
|
.type irq15, @function
|
||||||
irq15:
|
irq15:
|
||||||
cli
|
|
||||||
pushq $0 # err_code
|
pushq $0 # err_code
|
||||||
pushq $47 # int_no
|
pushq $47 # int_no
|
||||||
jmp interrupt_handler_prepare
|
jmp interrupt_handler_prepare
|
||||||
.global yield_cpu_handler
|
.global yield_cpu_handler
|
||||||
.type yield_cpu_handler, @function
|
.type yield_cpu_handler, @function
|
||||||
yield_cpu_handler:
|
yield_cpu_handler:
|
||||||
cli
|
|
||||||
pushq $0 # err_code
|
pushq $0 # err_code
|
||||||
pushq $129 # int_no
|
pushq $129 # int_no
|
||||||
jmp interrupt_handler_prepare
|
jmp interrupt_handler_prepare
|
||||||
.global thread_exit_handler
|
.global thread_exit_handler
|
||||||
.type thread_exit_handler, @function
|
.type thread_exit_handler, @function
|
||||||
thread_exit_handler:
|
thread_exit_handler:
|
||||||
cli
|
|
||||||
pushq $0 # err_code
|
pushq $0 # err_code
|
||||||
pushq $132 # int_no
|
pushq $132 # int_no
|
||||||
jmp interrupt_handler_prepare
|
jmp interrupt_handler_prepare
|
||||||
|
@ -494,15 +441,6 @@ interrupt_handler_null:
|
||||||
iretq
|
iretq
|
||||||
.size interrupt_handler_null, . - interrupt_handler_null
|
.size interrupt_handler_null, . - interrupt_handler_null
|
||||||
|
|
||||||
.global asm_interrupts_are_enabled
|
|
||||||
.type asm_interrupts_are_enabled, @function
|
|
||||||
asm_interrupts_are_enabled:
|
|
||||||
pushfq
|
|
||||||
popq %rax
|
|
||||||
andq $0x000200, %rax # FLAGS_INTERRUPT
|
|
||||||
retq
|
|
||||||
.size asm_interrupts_are_enabled, . - asm_interrupts_are_enabled
|
|
||||||
|
|
||||||
.global load_registers
|
.global load_registers
|
||||||
.type load_registers, @function
|
.type load_registers, @function
|
||||||
load_registers:
|
load_registers:
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
|
|
||||||
Copyright(C) Jonas 'Sortie' Termansen 2011, 2012, 2013.
|
Copyright(C) Jonas 'Sortie' Termansen 2011, 2012, 2013, 2014.
|
||||||
|
|
||||||
This file is part of Sortix.
|
This file is part of Sortix.
|
||||||
|
|
||||||
|
@ -27,11 +27,6 @@
|
||||||
.section .text
|
.section .text
|
||||||
.type syscall_handler, @function
|
.type syscall_handler, @function
|
||||||
syscall_handler:
|
syscall_handler:
|
||||||
# The processor disabled interrupts during the int $0x80 instruction,
|
|
||||||
# however Sortix system calls runs with interrupts enabled such that they
|
|
||||||
# can be pre-empted.
|
|
||||||
sti
|
|
||||||
|
|
||||||
movl $0, global_errno # Reset errno
|
movl $0, global_errno # Reset errno
|
||||||
|
|
||||||
pushq %rbp
|
pushq %rbp
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
|
|
||||||
Copyright(C) Jonas 'Sortie' Termansen 2011, 2012, 2013.
|
Copyright(C) Jonas 'Sortie' Termansen 2011, 2012, 2013, 2014.
|
||||||
|
|
||||||
This file is part of Sortix.
|
This file is part of Sortix.
|
||||||
|
|
||||||
|
@ -30,52 +30,49 @@
|
||||||
namespace Sortix {
|
namespace Sortix {
|
||||||
namespace IDT {
|
namespace IDT {
|
||||||
|
|
||||||
struct idt_entry
|
|
||||||
{
|
|
||||||
uint16_t handler_low;
|
|
||||||
uint16_t sel;
|
|
||||||
uint8_t reserved0;
|
|
||||||
uint8_t flags;
|
|
||||||
uint16_t handler_high;
|
|
||||||
#if defined(__x86_64__)
|
|
||||||
uint32_t handler_highest;
|
|
||||||
uint32_t reserved1;
|
|
||||||
#endif
|
|
||||||
};
|
|
||||||
|
|
||||||
struct idt_ptr
|
|
||||||
{
|
|
||||||
uint16_t limit;
|
|
||||||
#if defined(__x86_64__)
|
|
||||||
uint64_t idt_ptr;
|
|
||||||
#else
|
|
||||||
uint32_t idt_ptr;
|
|
||||||
#endif
|
|
||||||
} __attribute__((packed));
|
|
||||||
|
|
||||||
static struct idt_entry idt_entries[256];
|
static struct idt_entry idt_entries[256];
|
||||||
|
|
||||||
void Init()
|
void Init()
|
||||||
{
|
{
|
||||||
volatile struct idt_ptr ptr;
|
|
||||||
ptr.limit = sizeof(idt_entries) - 1;
|
|
||||||
ptr.idt_ptr = (unsigned long) &idt_entries;
|
|
||||||
asm volatile ("lidt (%0)" : : "r"(&ptr));
|
|
||||||
memset(&idt_entries, 0, sizeof(idt_entries));
|
memset(&idt_entries, 0, sizeof(idt_entries));
|
||||||
|
Set(idt_entries, 256);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetEntry(uint8_t num, uintptr_t handler, uint16_t sel, uint8_t flags)
|
void Set(struct idt_entry* table, size_t length)
|
||||||
{
|
{
|
||||||
idt_entries[num].flags = flags;
|
size_t limit = sizeof(idt_entry) * length - 1;
|
||||||
idt_entries[num].reserved0 = 0;
|
|
||||||
idt_entries[num].sel = sel;
|
|
||||||
idt_entries[num].handler_low = handler >> 0 & 0xFFFF;
|
|
||||||
idt_entries[num].handler_high = handler >> 16 & 0xFFFF;
|
|
||||||
#if defined(__x86_64__)
|
#if defined(__x86_64__)
|
||||||
idt_entries[num].handler_highest = handler >> 32 & 0xFFFFFFFFU;
|
asm volatile ("subq $10, %%rsp\n\t"
|
||||||
idt_entries[num].reserved1 = 0;
|
"movw %w0, 0(%%rsp)\n\t"
|
||||||
|
"movq %1, 2(%%rsp)\n\t"
|
||||||
|
"lidt (%%rsp)\n\t"
|
||||||
|
"addq $10, %%rsp" : : "rN"(limit), "r"(table));
|
||||||
|
#else
|
||||||
|
asm volatile ("subl $6, %%esp\n\t"
|
||||||
|
"movw %w0, 0(%%esp)\n\t"
|
||||||
|
"movl %1, 2(%%esp)\n\t"
|
||||||
|
"lidt (%%esp)\n\t"
|
||||||
|
"addl $6, %%esp" : : "rN"(limit), "r"(table));
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SetEntry(struct idt_entry* entry, uintptr_t handler, uint16_t selector, uint8_t flags, uint8_t ist)
|
||||||
|
{
|
||||||
|
entry->flags = flags;
|
||||||
|
entry->ist = ist;
|
||||||
|
entry->selector = selector;
|
||||||
|
entry->handler_low = handler >> 0 & 0xFFFF;
|
||||||
|
entry->handler_high = handler >> 16 & 0xFFFF;
|
||||||
|
#if defined(__x86_64__)
|
||||||
|
entry->handler_highest = handler >> 32 & 0xFFFFFFFFU;
|
||||||
|
entry->reserved1 = 0;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetEntry(uint8_t num, uintptr_t handler, uint16_t selector, uint8_t flags, uint8_t ist)
|
||||||
|
{
|
||||||
|
SetEntry(idt_entries + num, handler, selector, flags, ist);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace IDT
|
} // namespace IDT
|
||||||
} // namespace Sortix
|
} // namespace Sortix
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
|
|
||||||
Copyright(C) Jonas 'Sortie' Termansen 2011, 2012, 2013.
|
Copyright(C) Jonas 'Sortie' Termansen 2011, 2012, 2013, 2014.
|
||||||
|
|
||||||
This file is part of Sortix.
|
This file is part of Sortix.
|
||||||
|
|
||||||
|
@ -25,12 +25,36 @@
|
||||||
#ifndef SORTIX_X86_FAMILY_IDT_H
|
#ifndef SORTIX_X86_FAMILY_IDT_H
|
||||||
#define SORTIX_X86_FAMILY_IDT_H
|
#define SORTIX_X86_FAMILY_IDT_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
namespace Sortix {
|
namespace Sortix {
|
||||||
namespace IDT {
|
namespace IDT {
|
||||||
|
|
||||||
void Init();
|
struct idt_entry
|
||||||
void SetEntry(uint8_t num, uintptr_t handler, uint16_t sel, uint8_t flags);
|
{
|
||||||
void Flush();
|
uint16_t handler_low;
|
||||||
|
uint16_t selector;
|
||||||
|
uint8_t ist;
|
||||||
|
uint8_t flags;
|
||||||
|
uint16_t handler_high;
|
||||||
|
#if defined(__x86_64__)
|
||||||
|
uint32_t handler_highest;
|
||||||
|
uint32_t reserved1;
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
static const uint8_t FLAG_PRESENT = 1 << 7;
|
||||||
|
static const uint8_t FLAG_DPL_SHIFT = 5;
|
||||||
|
static const uint8_t FLAG_DPL_BITS = 2;
|
||||||
|
static const uint8_t FLAG_TYPE_SHIFT = 0;
|
||||||
|
static const uint8_t FLAG_TYPE_BITS = 4;
|
||||||
|
|
||||||
|
static const uint8_t TYPE_INTERRUPT = 0xE;
|
||||||
|
static const uint8_t TYPE_TRAP = 0xF;
|
||||||
|
|
||||||
|
void Set(struct idt_entry* table, size_t length);
|
||||||
|
void SetEntry(struct idt_entry* entry, uintptr_t handler, uint16_t selector,
|
||||||
|
uint8_t flags, uint8_t ist);
|
||||||
|
|
||||||
} // namespace IDT
|
} // namespace IDT
|
||||||
} // namespace Sortix
|
} // namespace Sortix
|
||||||
|
|
|
@ -0,0 +1,355 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
|
||||||
|
Copyright(C) Jonas 'Sortie' Termansen 2011, 2012, 2013, 2014.
|
||||||
|
|
||||||
|
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/>.
|
||||||
|
|
||||||
|
x86-family/interrupt.cpp
|
||||||
|
Interrupt support for i386 and x86_64 systems.
|
||||||
|
|
||||||
|
*******************************************************************************/
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <sortix/kernel/calltrace.h>
|
||||||
|
#include <sortix/kernel/cpu.h>
|
||||||
|
#include <sortix/kernel/debugger.h>
|
||||||
|
#include <sortix/kernel/interrupt.h>
|
||||||
|
#include <sortix/kernel/kernel.h>
|
||||||
|
#include <sortix/kernel/process.h>
|
||||||
|
#include <sortix/kernel/scheduler.h>
|
||||||
|
#include <sortix/kernel/signal.h>
|
||||||
|
#include <sortix/kernel/syscall.h>
|
||||||
|
#include <sortix/kernel/thread.h>
|
||||||
|
|
||||||
|
#include "idt.h"
|
||||||
|
#include "pic.h"
|
||||||
|
|
||||||
|
extern "C" void isr0();
|
||||||
|
extern "C" void isr1();
|
||||||
|
extern "C" void isr2();
|
||||||
|
extern "C" void isr3();
|
||||||
|
extern "C" void isr4();
|
||||||
|
extern "C" void isr5();
|
||||||
|
extern "C" void isr6();
|
||||||
|
extern "C" void isr7();
|
||||||
|
extern "C" void isr8();
|
||||||
|
extern "C" void isr9();
|
||||||
|
extern "C" void isr10();
|
||||||
|
extern "C" void isr11();
|
||||||
|
extern "C" void isr12();
|
||||||
|
extern "C" void isr13();
|
||||||
|
extern "C" void isr14();
|
||||||
|
extern "C" void isr15();
|
||||||
|
extern "C" void isr16();
|
||||||
|
extern "C" void isr17();
|
||||||
|
extern "C" void isr18();
|
||||||
|
extern "C" void isr19();
|
||||||
|
extern "C" void isr20();
|
||||||
|
extern "C" void isr21();
|
||||||
|
extern "C" void isr22();
|
||||||
|
extern "C" void isr23();
|
||||||
|
extern "C" void isr24();
|
||||||
|
extern "C" void isr25();
|
||||||
|
extern "C" void isr26();
|
||||||
|
extern "C" void isr27();
|
||||||
|
extern "C" void isr28();
|
||||||
|
extern "C" void isr29();
|
||||||
|
extern "C" void isr30();
|
||||||
|
extern "C" void isr31();
|
||||||
|
extern "C" void isr128();
|
||||||
|
extern "C" void isr130();
|
||||||
|
extern "C" void isr131();
|
||||||
|
extern "C" void irq0();
|
||||||
|
extern "C" void irq1();
|
||||||
|
extern "C" void irq2();
|
||||||
|
extern "C" void irq3();
|
||||||
|
extern "C" void irq4();
|
||||||
|
extern "C" void irq5();
|
||||||
|
extern "C" void irq6();
|
||||||
|
extern "C" void irq7();
|
||||||
|
extern "C" void irq8();
|
||||||
|
extern "C" void irq9();
|
||||||
|
extern "C" void irq10();
|
||||||
|
extern "C" void irq11();
|
||||||
|
extern "C" void irq12();
|
||||||
|
extern "C" void irq13();
|
||||||
|
extern "C" void irq14();
|
||||||
|
extern "C" void irq15();
|
||||||
|
extern "C" void interrupt_handler_null();
|
||||||
|
extern "C" void syscall_handler();
|
||||||
|
extern "C" void yield_cpu_handler();
|
||||||
|
extern "C" void thread_exit_handler();
|
||||||
|
|
||||||
|
namespace Sortix {
|
||||||
|
namespace Interrupt {
|
||||||
|
|
||||||
|
extern "C" { unsigned long asm_is_cpu_interrupted = 0; }
|
||||||
|
|
||||||
|
const bool CALLTRACE_KERNEL = false;
|
||||||
|
const bool CALLTRACE_USER = false;
|
||||||
|
const bool RUN_DEBUGGER_ON_KERNEL_CRASH = false;
|
||||||
|
const bool RUN_DEBUGGER_ON_USER_CRASH = false;
|
||||||
|
|
||||||
|
const size_t NUM_KNOWN_EXCEPTIONS = 20;
|
||||||
|
const char* exception_names[] =
|
||||||
|
{
|
||||||
|
"Divide by zero", /* 0, 0x0 */
|
||||||
|
"Debug", /* 1, 0x1 */
|
||||||
|
"Non maskable interrupt", /* 2, 0x2 */
|
||||||
|
"Breakpoint", /* 3, 0x3 */
|
||||||
|
"Into detected overflow", /* 4, 0x4 */
|
||||||
|
"Out of bounds", /* 5, 0x5 */
|
||||||
|
"Invalid opcode", /* 6, 0x6 */
|
||||||
|
"No coprocessor", /* 7, 0x7 */
|
||||||
|
"Double fault", /* 8, 0x8 */
|
||||||
|
"Coprocessor segment overrun", /* 9, 0x9 */
|
||||||
|
"Bad TSS", /* 10, 0xA */
|
||||||
|
"Segment not present", /* 11, 0xB */
|
||||||
|
"Stack fault", /* 12, 0xC */
|
||||||
|
"General protection fault", /* 13, 0xD */
|
||||||
|
"Page fault", /* 14, 0xE */
|
||||||
|
"Unknown interrupt", /* 15, 0xF */
|
||||||
|
"Coprocessor fault", /* 16, 0x10 */
|
||||||
|
"Alignment check", /* 17, 0x11 */
|
||||||
|
"Machine check", /* 18, 0x12 */
|
||||||
|
"SIMD Floating-Point", /* 19, 0x13 */
|
||||||
|
};
|
||||||
|
|
||||||
|
const unsigned int NUM_INTERRUPTS = 256U;
|
||||||
|
|
||||||
|
static struct IDT::idt_entry interrupt_table[NUM_INTERRUPTS];
|
||||||
|
static Handler interrupt_handlers[NUM_INTERRUPTS];
|
||||||
|
static void* interrupt_handler_context[NUM_INTERRUPTS];
|
||||||
|
|
||||||
|
void RegisterHandler(unsigned int index,
|
||||||
|
Interrupt::Handler handler,
|
||||||
|
void* context)
|
||||||
|
{
|
||||||
|
assert(index < NUM_INTERRUPTS);
|
||||||
|
interrupt_handlers[index] = handler;
|
||||||
|
interrupt_handler_context[index] = context;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void RegisterRawHandler(unsigned int index,
|
||||||
|
void (*handler)(void),
|
||||||
|
bool userspace,
|
||||||
|
bool preemptive)
|
||||||
|
{
|
||||||
|
assert(index < NUM_INTERRUPTS);
|
||||||
|
addr_t handler_entry = (addr_t) handler;
|
||||||
|
uint16_t selector = KCS;
|
||||||
|
uint8_t rpl = userspace ? URPL : KRPL;
|
||||||
|
uint8_t type = preemptive ? IDT::TYPE_TRAP : IDT::TYPE_INTERRUPT;
|
||||||
|
uint8_t ist = 0;
|
||||||
|
uint8_t flags = IDT::FLAG_PRESENT
|
||||||
|
| type << IDT::FLAG_TYPE_SHIFT
|
||||||
|
| rpl << IDT::FLAG_DPL_SHIFT;
|
||||||
|
IDT::SetEntry(&interrupt_table[index], handler_entry, selector, flags, ist);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Init()
|
||||||
|
{
|
||||||
|
// Initialize the interrupt table entries to the null interrupt handler.
|
||||||
|
memset(&interrupt_table, 0, sizeof(interrupt_table));
|
||||||
|
for ( unsigned int i = 0; i < NUM_INTERRUPTS; i++ )
|
||||||
|
{
|
||||||
|
interrupt_handlers[i] = NULL;
|
||||||
|
interrupt_handler_context[i] = NULL;
|
||||||
|
RegisterRawHandler(i, interrupt_handler_null, false, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remap the IRQ table on the PICs.
|
||||||
|
PIC::ReprogramPIC();
|
||||||
|
|
||||||
|
RegisterRawHandler(0, isr0, false, false);
|
||||||
|
RegisterRawHandler(1, isr1, false, false);
|
||||||
|
RegisterRawHandler(2, isr2, false, false);
|
||||||
|
RegisterRawHandler(3, isr3, false, false);
|
||||||
|
RegisterRawHandler(4, isr4, false, false);
|
||||||
|
RegisterRawHandler(5, isr5, false, false);
|
||||||
|
RegisterRawHandler(6, isr6, false, false);
|
||||||
|
RegisterRawHandler(7, isr7, false, false);
|
||||||
|
RegisterRawHandler(8, isr8, false, false);
|
||||||
|
RegisterRawHandler(9, isr9, false, false);
|
||||||
|
RegisterRawHandler(10, isr10, false, false);
|
||||||
|
RegisterRawHandler(11, isr11, false, false);
|
||||||
|
RegisterRawHandler(12, isr12, false, false);
|
||||||
|
RegisterRawHandler(13, isr13, false, false);
|
||||||
|
RegisterRawHandler(14, isr14, false, false);
|
||||||
|
RegisterRawHandler(15, isr15, false, false);
|
||||||
|
RegisterRawHandler(16, isr16, false, false);
|
||||||
|
RegisterRawHandler(17, isr17, false, false);
|
||||||
|
RegisterRawHandler(18, isr18, false, false);
|
||||||
|
RegisterRawHandler(19, isr19, false, false);
|
||||||
|
RegisterRawHandler(20, isr20, false, false);
|
||||||
|
RegisterRawHandler(21, isr21, false, false);
|
||||||
|
RegisterRawHandler(22, isr22, false, false);
|
||||||
|
RegisterRawHandler(23, isr23, false, false);
|
||||||
|
RegisterRawHandler(24, isr24, false, false);
|
||||||
|
RegisterRawHandler(25, isr25, false, false);
|
||||||
|
RegisterRawHandler(26, isr26, false, false);
|
||||||
|
RegisterRawHandler(27, isr27, false, false);
|
||||||
|
RegisterRawHandler(28, isr28, false, false);
|
||||||
|
RegisterRawHandler(29, isr29, false, false);
|
||||||
|
RegisterRawHandler(30, isr30, false, false);
|
||||||
|
RegisterRawHandler(31, isr31, false, false);
|
||||||
|
RegisterRawHandler(32, irq0, false, false);
|
||||||
|
RegisterRawHandler(33, irq1, false, false);
|
||||||
|
RegisterRawHandler(34, irq2, false, false);
|
||||||
|
RegisterRawHandler(35, irq3, false, false);
|
||||||
|
RegisterRawHandler(36, irq4, false, false);
|
||||||
|
RegisterRawHandler(37, irq5, false, false);
|
||||||
|
RegisterRawHandler(38, irq6, false, false);
|
||||||
|
RegisterRawHandler(39, irq7, false, false);
|
||||||
|
RegisterRawHandler(40, irq8, false, false);
|
||||||
|
RegisterRawHandler(41, irq9, false, false);
|
||||||
|
RegisterRawHandler(42, irq10, false, false);
|
||||||
|
RegisterRawHandler(43, irq11, false, false);
|
||||||
|
RegisterRawHandler(44, irq12, false, false);
|
||||||
|
RegisterRawHandler(45, irq13, false, false);
|
||||||
|
RegisterRawHandler(46, irq14, false, false);
|
||||||
|
RegisterRawHandler(47, irq15, false, false);
|
||||||
|
RegisterRawHandler(128, syscall_handler, true, true);
|
||||||
|
RegisterRawHandler(129, yield_cpu_handler, true, false);
|
||||||
|
RegisterRawHandler(130, isr130, true, false);
|
||||||
|
RegisterRawHandler(131, isr131, true, false);
|
||||||
|
RegisterRawHandler(132, thread_exit_handler, true, false);
|
||||||
|
|
||||||
|
RegisterHandler(129, Scheduler::InterruptYieldCPU, NULL);
|
||||||
|
RegisterHandler(130, Signal::Dispatch, NULL);
|
||||||
|
RegisterHandler(131, Signal::Return, NULL);
|
||||||
|
RegisterHandler(132, Scheduler::ThreadExitCPU, NULL);
|
||||||
|
|
||||||
|
IDT::Set(interrupt_table, NUM_INTERRUPTS);
|
||||||
|
|
||||||
|
Interrupt::Enable();
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* ExceptionName(const CPU::InterruptRegisters* regs)
|
||||||
|
{
|
||||||
|
if ( regs->int_no < NUM_KNOWN_EXCEPTIONS )
|
||||||
|
return exception_names[regs->int_no];
|
||||||
|
return "Unknown";
|
||||||
|
}
|
||||||
|
|
||||||
|
uintptr_t ExceptionLocation(const CPU::InterruptRegisters* regs)
|
||||||
|
{
|
||||||
|
#if defined(__x86_64__)
|
||||||
|
return regs->rip;
|
||||||
|
#elif defined(__i386__)
|
||||||
|
return regs->eip;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void CrashCalltrace(const CPU::InterruptRegisters* regs)
|
||||||
|
{
|
||||||
|
#if defined(__x86_64__)
|
||||||
|
Calltrace::Perform(regs->rbp);
|
||||||
|
#elif defined(__i386__)
|
||||||
|
Calltrace::Perform(regs->ebp);
|
||||||
|
#else
|
||||||
|
#warning "Please provide a calltrace implementation for your CPU."
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__((noreturn))
|
||||||
|
void KernelCrashHandler(CPU::InterruptRegisters* regs)
|
||||||
|
{
|
||||||
|
CurrentThread()->SaveRegisters(regs);
|
||||||
|
|
||||||
|
// Walk and print the stack frames if this is a debug build.
|
||||||
|
if ( CALLTRACE_KERNEL )
|
||||||
|
CrashCalltrace(regs);
|
||||||
|
|
||||||
|
// Possibly switch to the kernel debugger in event of a crash.
|
||||||
|
if ( RUN_DEBUGGER_ON_KERNEL_CRASH )
|
||||||
|
Debugger::Run();
|
||||||
|
|
||||||
|
// Panic the kernel with a diagnostic message.
|
||||||
|
PanicF("Unhandled CPU Exception id %zu `%s' at ip=0x%zx (cr2=0x%zx, "
|
||||||
|
"err_code=0x%zx)", regs->int_no, ExceptionName(regs),
|
||||||
|
ExceptionLocation(regs), regs->cr2, regs->err_code);
|
||||||
|
}
|
||||||
|
|
||||||
|
void UserCrashHandler(CPU::InterruptRegisters* regs)
|
||||||
|
{
|
||||||
|
CurrentThread()->SaveRegisters(regs);
|
||||||
|
|
||||||
|
// Execute this crash handler with preemption on.
|
||||||
|
Interrupt::Enable();
|
||||||
|
|
||||||
|
// Walk and print the stack frames if this is a debug build.
|
||||||
|
if ( CALLTRACE_USER )
|
||||||
|
CrashCalltrace(regs);
|
||||||
|
|
||||||
|
// Possibly switch to the kernel debugger in event of a crash.
|
||||||
|
if ( RUN_DEBUGGER_ON_USER_CRASH )
|
||||||
|
Debugger::Run();
|
||||||
|
|
||||||
|
// Issue a diagnostic message to the kernel log concerning the crash.
|
||||||
|
Log::PrintF("The current process (pid %ji `%s') crashed and was terminated:\n",
|
||||||
|
(intmax_t) CurrentProcess()->pid, CurrentProcess()->program_image_path);
|
||||||
|
Log::PrintF("%s exception at ip=0x%zx (cr2=0x%zx, err_code=0x%zx)\n",
|
||||||
|
ExceptionName(regs), ExceptionLocation(regs), regs->cr2,
|
||||||
|
regs->err_code);
|
||||||
|
|
||||||
|
// Exit the process with the right error code.
|
||||||
|
// TODO: Send a SIGINT, SIGBUS, or whatever instead.
|
||||||
|
CurrentProcess()->Exit(139);
|
||||||
|
|
||||||
|
// TODO: Is it strictly needed or even desirable to disable preemption here?
|
||||||
|
Interrupt::Disable();
|
||||||
|
|
||||||
|
// Deliver signals to this thread so it can exit correctly.
|
||||||
|
Signal::Dispatch(regs);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" void interrupt_handler(CPU::InterruptRegisters* regs)
|
||||||
|
{
|
||||||
|
unsigned int int_no = regs->int_no;
|
||||||
|
|
||||||
|
// IRQ 7 and 15 might be spurious and might need to be ignored.
|
||||||
|
if ( int_no == IRQ7 && !(PIC::ReadISR() & (1 << 7)) )
|
||||||
|
return;
|
||||||
|
if ( int_no == IRQ15 && !(PIC::ReadISR() & (1 << 15)) )
|
||||||
|
{
|
||||||
|
PIC::SendMasterEOI();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool is_in_kernel = (regs->cs & 0x3) == KRPL;
|
||||||
|
bool is_in_user = !is_in_kernel;
|
||||||
|
bool is_crash = int_no < 32 && int_no != 7;
|
||||||
|
|
||||||
|
// Invoke the appropriate interrupt handler.
|
||||||
|
if ( is_crash && is_in_kernel )
|
||||||
|
KernelCrashHandler(regs);
|
||||||
|
else if ( is_crash && is_in_user )
|
||||||
|
UserCrashHandler(regs);
|
||||||
|
else if ( interrupt_handlers[int_no] )
|
||||||
|
interrupt_handlers[int_no](regs, interrupt_handler_context[int_no]);
|
||||||
|
|
||||||
|
// Send an end of interrupt signal to the PICs if we got an IRQ.
|
||||||
|
if ( IRQ0 <= int_no && int_no <= IRQ15 )
|
||||||
|
PIC::SendEOI(int_no - IRQ0);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Interrupt
|
||||||
|
} // namespace Sortix
|
|
@ -0,0 +1,122 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
|
||||||
|
Copyright(C) Jonas 'Sortie' Termansen 2011, 2012, 2013, 2014.
|
||||||
|
|
||||||
|
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/>.
|
||||||
|
|
||||||
|
x86-family/pic.cpp
|
||||||
|
Driver for the Programmable Interrupt Controller.
|
||||||
|
|
||||||
|
*******************************************************************************/
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include <sortix/kernel/cpu.h>
|
||||||
|
#include <sortix/kernel/kernel.h>
|
||||||
|
#include <sortix/kernel/interrupt.h>
|
||||||
|
|
||||||
|
#include "pic.h"
|
||||||
|
|
||||||
|
namespace Sortix {
|
||||||
|
namespace PIC {
|
||||||
|
|
||||||
|
const uint16_t PIC_MASTER = 0x20;
|
||||||
|
const uint16_t PIC_SLAVE = 0xA0;
|
||||||
|
const uint16_t PIC_COMMAND = 0x00;
|
||||||
|
const uint16_t PIC_DATA = 0x01;
|
||||||
|
const uint8_t PIC_CMD_ENDINTR = 0x20;
|
||||||
|
const uint8_t PIC_ICW1_ICW4 = 0x01; // ICW4 (not) needed
|
||||||
|
const uint8_t PIC_ICW1_SINGLE = 0x02; // Single (cascade) mode
|
||||||
|
const uint8_t PIC_ICW1_INTERVAL4 = 0x04; // Call address interval 4 (8)
|
||||||
|
const uint8_t PIC_ICW1_LEVEL = 0x08; // Level triggered (edge) mode
|
||||||
|
const uint8_t PIC_CMD_INIT = 0x10;
|
||||||
|
const uint8_t PIC_MODE_8086 = 0x01; // 8086/88 (MCS-80/85) mode
|
||||||
|
const uint8_t PIC_MODE_AUTO = 0x02; // Auto (normal) EOI
|
||||||
|
const uint8_t PIC_MODE_BUF_SLAVE = 0x08; // Buffered mode/slave
|
||||||
|
const uint8_t PIC_MODE_BUF_MASTER = 0x0C; // Buffered mode/master
|
||||||
|
const uint8_t PIC_MODE_SFNM = 0x10; // Special fully nested (not)
|
||||||
|
const uint8_t PIC_READ_IRR = 0x0A;
|
||||||
|
const uint8_t PIC_READ_ISR = 0x0B;
|
||||||
|
|
||||||
|
static uint16_t ReadRegister(uint8_t ocw3)
|
||||||
|
{
|
||||||
|
CPU::OutPortB(PIC_MASTER + PIC_COMMAND, ocw3);
|
||||||
|
CPU::OutPortB(PIC_SLAVE + PIC_COMMAND, ocw3);
|
||||||
|
return CPU::InPortB(PIC_MASTER + PIC_COMMAND) << 0 |
|
||||||
|
CPU::InPortB(PIC_SLAVE + PIC_COMMAND) << 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t ReadIRR()
|
||||||
|
{
|
||||||
|
return ReadRegister(PIC_READ_IRR);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t ReadISR()
|
||||||
|
{
|
||||||
|
return ReadRegister(PIC_READ_ISR);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" void ReprogramPIC()
|
||||||
|
{
|
||||||
|
uint8_t master_mask = 0;
|
||||||
|
uint8_t slave_mask = 0;
|
||||||
|
CPU::OutPortB(PIC_MASTER + PIC_COMMAND, PIC_CMD_INIT | PIC_ICW1_ICW4);
|
||||||
|
CPU::OutPortB(PIC_SLAVE + PIC_COMMAND, PIC_CMD_INIT | PIC_ICW1_ICW4);
|
||||||
|
CPU::OutPortB(PIC_MASTER + PIC_DATA, Interrupt::IRQ0);
|
||||||
|
CPU::OutPortB(PIC_SLAVE + PIC_DATA, Interrupt::IRQ8);
|
||||||
|
CPU::OutPortB(PIC_MASTER + PIC_DATA, 0x04); // Slave PIC at IRQ2
|
||||||
|
CPU::OutPortB(PIC_SLAVE + PIC_DATA, 0x02); // Cascade Identity
|
||||||
|
CPU::OutPortB(PIC_MASTER + PIC_DATA, PIC_MODE_8086);
|
||||||
|
CPU::OutPortB(PIC_SLAVE + PIC_DATA, PIC_MODE_8086);
|
||||||
|
CPU::OutPortB(PIC_MASTER + PIC_DATA, master_mask);
|
||||||
|
CPU::OutPortB(PIC_SLAVE + PIC_DATA, slave_mask);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" void DeprogramPIC()
|
||||||
|
{
|
||||||
|
uint8_t master_mask = 0;
|
||||||
|
uint8_t slave_mask = 0;
|
||||||
|
CPU::OutPortB(PIC_MASTER + PIC_COMMAND, PIC_CMD_INIT | PIC_ICW1_ICW4);
|
||||||
|
CPU::OutPortB(PIC_SLAVE + PIC_COMMAND, PIC_CMD_INIT | PIC_ICW1_ICW4);
|
||||||
|
CPU::OutPortB(PIC_MASTER + PIC_DATA, 0x08);
|
||||||
|
CPU::OutPortB(PIC_SLAVE + PIC_DATA, 0x70);
|
||||||
|
CPU::OutPortB(PIC_MASTER + PIC_DATA, 0x04); // Slave PIC at IRQ2
|
||||||
|
CPU::OutPortB(PIC_SLAVE + PIC_DATA, 0x02); // Cascade Identity
|
||||||
|
CPU::OutPortB(PIC_MASTER + PIC_DATA, PIC_MODE_8086);
|
||||||
|
CPU::OutPortB(PIC_SLAVE + PIC_DATA, PIC_MODE_8086);
|
||||||
|
CPU::OutPortB(PIC_MASTER + PIC_DATA, master_mask);
|
||||||
|
CPU::OutPortB(PIC_SLAVE + PIC_DATA, slave_mask);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SendMasterEOI()
|
||||||
|
{
|
||||||
|
CPU::OutPortB(PIC_MASTER, PIC_CMD_ENDINTR);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SendSlaveEOI()
|
||||||
|
{
|
||||||
|
CPU::OutPortB(PIC_SLAVE, PIC_CMD_ENDINTR);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SendEOI(unsigned int irq)
|
||||||
|
{
|
||||||
|
if ( 8 <= irq )
|
||||||
|
SendSlaveEOI();
|
||||||
|
SendMasterEOI();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace PIC
|
||||||
|
} // namespace Sortix
|
|
@ -0,0 +1,43 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
|
||||||
|
Copyright(C) Jonas 'Sortie' Termansen 2011, 2012, 2013, 2014.
|
||||||
|
|
||||||
|
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/>.
|
||||||
|
|
||||||
|
x86-family/pic.h
|
||||||
|
Driver for the Programmable Interrupt Controller.
|
||||||
|
|
||||||
|
*******************************************************************************/
|
||||||
|
|
||||||
|
#ifndef SORTIX_X86_FAMILY_PIC_H
|
||||||
|
#define SORTIX_X86_FAMILY_PIC_H
|
||||||
|
|
||||||
|
namespace Sortix {
|
||||||
|
namespace PIC {
|
||||||
|
|
||||||
|
uint16_t ReadIRR();
|
||||||
|
uint16_t ReadISR();
|
||||||
|
bool IsSpuriousIRQ(unsigned int irq);
|
||||||
|
extern "C" void ReprogramPIC();
|
||||||
|
extern "C" void DeprogramPIC();
|
||||||
|
void SendMasterEOI();
|
||||||
|
void SendSlaveEOI();
|
||||||
|
void SendEOI(unsigned int irq);
|
||||||
|
|
||||||
|
} // namespace PIC
|
||||||
|
} // namespace Sortix
|
||||||
|
|
||||||
|
#endif
|
|
@ -27,371 +27,318 @@
|
||||||
.global isr0
|
.global isr0
|
||||||
.type isr0, @function
|
.type isr0, @function
|
||||||
isr0:
|
isr0:
|
||||||
cli
|
|
||||||
pushl $0 # err_code
|
pushl $0 # err_code
|
||||||
pushl $0 # int_no
|
pushl $0 # int_no
|
||||||
jmp interrupt_handler_prepare
|
jmp interrupt_handler_prepare
|
||||||
.global isr1
|
.global isr1
|
||||||
.type isr1, @function
|
.type isr1, @function
|
||||||
isr1:
|
isr1:
|
||||||
cli
|
|
||||||
pushl $0 # err_code
|
pushl $0 # err_code
|
||||||
pushl $1 # int_no
|
pushl $1 # int_no
|
||||||
jmp interrupt_handler_prepare
|
jmp interrupt_handler_prepare
|
||||||
.global isr2
|
.global isr2
|
||||||
.type isr2, @function
|
.type isr2, @function
|
||||||
isr2:
|
isr2:
|
||||||
cli
|
|
||||||
pushl $0 # err_code
|
pushl $0 # err_code
|
||||||
pushl $2 # int_no
|
pushl $2 # int_no
|
||||||
jmp interrupt_handler_prepare
|
jmp interrupt_handler_prepare
|
||||||
.global isr3
|
.global isr3
|
||||||
.type isr3, @function
|
.type isr3, @function
|
||||||
isr3:
|
isr3:
|
||||||
cli
|
|
||||||
pushl $0 # err_code
|
pushl $0 # err_code
|
||||||
pushl $3 # int_no
|
pushl $3 # int_no
|
||||||
jmp interrupt_handler_prepare
|
jmp interrupt_handler_prepare
|
||||||
.global isr4
|
.global isr4
|
||||||
.type isr4, @function
|
.type isr4, @function
|
||||||
isr4:
|
isr4:
|
||||||
cli
|
|
||||||
pushl $0 # err_code
|
pushl $0 # err_code
|
||||||
pushl $4 # int_no
|
pushl $4 # int_no
|
||||||
jmp interrupt_handler_prepare
|
jmp interrupt_handler_prepare
|
||||||
.global isr5
|
.global isr5
|
||||||
.type isr5, @function
|
.type isr5, @function
|
||||||
isr5:
|
isr5:
|
||||||
cli
|
|
||||||
pushl $0 # err_code
|
pushl $0 # err_code
|
||||||
pushl $5 # int_no
|
pushl $5 # int_no
|
||||||
jmp interrupt_handler_prepare
|
jmp interrupt_handler_prepare
|
||||||
.global isr6
|
.global isr6
|
||||||
.type isr6, @function
|
.type isr6, @function
|
||||||
isr6:
|
isr6:
|
||||||
cli
|
|
||||||
pushl $0 # err_code
|
pushl $0 # err_code
|
||||||
pushl $6 # int_no
|
pushl $6 # int_no
|
||||||
jmp interrupt_handler_prepare
|
jmp interrupt_handler_prepare
|
||||||
.global isr7
|
.global isr7
|
||||||
.type isr7, @function
|
.type isr7, @function
|
||||||
isr7:
|
isr7:
|
||||||
cli
|
|
||||||
pushl $0 # err_code
|
pushl $0 # err_code
|
||||||
pushl $7 # int_no
|
pushl $7 # int_no
|
||||||
jmp interrupt_handler_prepare
|
jmp interrupt_handler_prepare
|
||||||
.global isr8
|
.global isr8
|
||||||
.type isr8, @function
|
.type isr8, @function
|
||||||
isr8:
|
isr8:
|
||||||
cli
|
|
||||||
# pushl $0 # err_code pushed by CPU
|
# pushl $0 # err_code pushed by CPU
|
||||||
pushl $8 # int_no
|
pushl $8 # int_no
|
||||||
jmp interrupt_handler_prepare
|
jmp interrupt_handler_prepare
|
||||||
.global isr9
|
.global isr9
|
||||||
.type isr9, @function
|
.type isr9, @function
|
||||||
isr9:
|
isr9:
|
||||||
cli
|
|
||||||
pushl $0 # err_code
|
pushl $0 # err_code
|
||||||
pushl $9 # int_no
|
pushl $9 # int_no
|
||||||
jmp interrupt_handler_prepare
|
jmp interrupt_handler_prepare
|
||||||
.global isr10
|
.global isr10
|
||||||
.type isr10, @function
|
.type isr10, @function
|
||||||
isr10:
|
isr10:
|
||||||
cli
|
|
||||||
# pushl $0 # err_code pushed by CPU
|
# pushl $0 # err_code pushed by CPU
|
||||||
pushl $10 # int_no
|
pushl $10 # int_no
|
||||||
jmp interrupt_handler_prepare
|
jmp interrupt_handler_prepare
|
||||||
.global isr11
|
.global isr11
|
||||||
.type isr11, @function
|
.type isr11, @function
|
||||||
isr11:
|
isr11:
|
||||||
cli
|
|
||||||
# pushl $0 # err_code pushed by CPU
|
# pushl $0 # err_code pushed by CPU
|
||||||
pushl $11 # int_no
|
pushl $11 # int_no
|
||||||
jmp interrupt_handler_prepare
|
jmp interrupt_handler_prepare
|
||||||
.global isr12
|
.global isr12
|
||||||
.type isr12, @function
|
.type isr12, @function
|
||||||
isr12:
|
isr12:
|
||||||
cli
|
|
||||||
# pushl $0 # err_code pushed by CPU
|
# pushl $0 # err_code pushed by CPU
|
||||||
pushl $12 # int_no
|
pushl $12 # int_no
|
||||||
jmp interrupt_handler_prepare
|
jmp interrupt_handler_prepare
|
||||||
.global isr13
|
.global isr13
|
||||||
.type isr13, @function
|
.type isr13, @function
|
||||||
isr13:
|
isr13:
|
||||||
cli
|
|
||||||
# pushl $0 # err_code pushed by CPU
|
# pushl $0 # err_code pushed by CPU
|
||||||
pushl $13 # int_no
|
pushl $13 # int_no
|
||||||
jmp interrupt_handler_prepare
|
jmp interrupt_handler_prepare
|
||||||
.global isr14
|
.global isr14
|
||||||
.type isr14, @function
|
.type isr14, @function
|
||||||
isr14:
|
isr14:
|
||||||
cli
|
|
||||||
# pushl $0 # err_code pushed by CPU
|
# pushl $0 # err_code pushed by CPU
|
||||||
pushl $14 # int_no
|
pushl $14 # int_no
|
||||||
jmp interrupt_handler_prepare
|
jmp interrupt_handler_prepare
|
||||||
.global isr15
|
.global isr15
|
||||||
.type isr15, @function
|
.type isr15, @function
|
||||||
isr15:
|
isr15:
|
||||||
cli
|
|
||||||
pushl $0 # err_code
|
pushl $0 # err_code
|
||||||
pushl $15 # int_no
|
pushl $15 # int_no
|
||||||
jmp interrupt_handler_prepare
|
jmp interrupt_handler_prepare
|
||||||
.global isr16
|
.global isr16
|
||||||
.type isr16, @function
|
.type isr16, @function
|
||||||
isr16:
|
isr16:
|
||||||
cli
|
|
||||||
pushl $0 # err_code
|
pushl $0 # err_code
|
||||||
pushl $16 # int_no
|
pushl $16 # int_no
|
||||||
jmp interrupt_handler_prepare
|
jmp interrupt_handler_prepare
|
||||||
.global isr17
|
.global isr17
|
||||||
.type isr17, @function
|
.type isr17, @function
|
||||||
isr17:
|
isr17:
|
||||||
cli
|
|
||||||
pushl $0 # err_code
|
pushl $0 # err_code
|
||||||
pushl $17 # int_no
|
pushl $17 # int_no
|
||||||
jmp interrupt_handler_prepare
|
jmp interrupt_handler_prepare
|
||||||
.global isr18
|
.global isr18
|
||||||
.type isr18, @function
|
.type isr18, @function
|
||||||
isr18:
|
isr18:
|
||||||
cli
|
|
||||||
pushl $0 # err_code
|
pushl $0 # err_code
|
||||||
pushl $18 # int_no
|
pushl $18 # int_no
|
||||||
jmp interrupt_handler_prepare
|
jmp interrupt_handler_prepare
|
||||||
.global isr19
|
.global isr19
|
||||||
.type isr19, @function
|
.type isr19, @function
|
||||||
isr19:
|
isr19:
|
||||||
cli
|
|
||||||
pushl $0 # err_code
|
pushl $0 # err_code
|
||||||
pushl $19 # int_no
|
pushl $19 # int_no
|
||||||
jmp interrupt_handler_prepare
|
jmp interrupt_handler_prepare
|
||||||
.global isr20
|
.global isr20
|
||||||
.type isr20, @function
|
.type isr20, @function
|
||||||
isr20:
|
isr20:
|
||||||
cli
|
|
||||||
pushl $0 # err_code
|
pushl $0 # err_code
|
||||||
pushl $20 # int_no
|
pushl $20 # int_no
|
||||||
jmp interrupt_handler_prepare
|
jmp interrupt_handler_prepare
|
||||||
.global isr21
|
.global isr21
|
||||||
.type isr21, @function
|
.type isr21, @function
|
||||||
isr21:
|
isr21:
|
||||||
cli
|
|
||||||
pushl $0 # err_code
|
pushl $0 # err_code
|
||||||
pushl $21 # int_no
|
pushl $21 # int_no
|
||||||
jmp interrupt_handler_prepare
|
jmp interrupt_handler_prepare
|
||||||
.global isr22
|
.global isr22
|
||||||
.type isr22, @function
|
.type isr22, @function
|
||||||
isr22:
|
isr22:
|
||||||
cli
|
|
||||||
pushl $0 # err_code
|
pushl $0 # err_code
|
||||||
pushl $22 # int_no
|
pushl $22 # int_no
|
||||||
jmp interrupt_handler_prepare
|
jmp interrupt_handler_prepare
|
||||||
.global isr23
|
.global isr23
|
||||||
.type isr23, @function
|
.type isr23, @function
|
||||||
isr23:
|
isr23:
|
||||||
cli
|
|
||||||
pushl $0 # err_code
|
pushl $0 # err_code
|
||||||
pushl $23 # int_no
|
pushl $23 # int_no
|
||||||
jmp interrupt_handler_prepare
|
jmp interrupt_handler_prepare
|
||||||
.global isr24
|
.global isr24
|
||||||
.type isr24, @function
|
.type isr24, @function
|
||||||
isr24:
|
isr24:
|
||||||
cli
|
|
||||||
pushl $0 # err_code
|
pushl $0 # err_code
|
||||||
pushl $24 # int_no
|
pushl $24 # int_no
|
||||||
jmp interrupt_handler_prepare
|
jmp interrupt_handler_prepare
|
||||||
.global isr25
|
.global isr25
|
||||||
.type isr25, @function
|
.type isr25, @function
|
||||||
isr25:
|
isr25:
|
||||||
cli
|
|
||||||
pushl $0 # err_code
|
pushl $0 # err_code
|
||||||
pushl $25 # int_no
|
pushl $25 # int_no
|
||||||
jmp interrupt_handler_prepare
|
jmp interrupt_handler_prepare
|
||||||
.global isr26
|
.global isr26
|
||||||
.type isr26, @function
|
.type isr26, @function
|
||||||
isr26:
|
isr26:
|
||||||
cli
|
|
||||||
pushl $0 # err_code
|
pushl $0 # err_code
|
||||||
pushl $26 # int_no
|
pushl $26 # int_no
|
||||||
jmp interrupt_handler_prepare
|
jmp interrupt_handler_prepare
|
||||||
.global isr27
|
.global isr27
|
||||||
.type isr27, @function
|
.type isr27, @function
|
||||||
isr27:
|
isr27:
|
||||||
cli
|
|
||||||
pushl $0 # err_code
|
pushl $0 # err_code
|
||||||
pushl $27 # int_no
|
pushl $27 # int_no
|
||||||
jmp interrupt_handler_prepare
|
jmp interrupt_handler_prepare
|
||||||
.global isr28
|
.global isr28
|
||||||
.type isr28, @function
|
.type isr28, @function
|
||||||
isr28:
|
isr28:
|
||||||
cli
|
|
||||||
pushl $0 # err_code
|
pushl $0 # err_code
|
||||||
pushl $28 # int_no
|
pushl $28 # int_no
|
||||||
jmp interrupt_handler_prepare
|
jmp interrupt_handler_prepare
|
||||||
.global isr29
|
.global isr29
|
||||||
.type isr29, @function
|
.type isr29, @function
|
||||||
isr29:
|
isr29:
|
||||||
cli
|
|
||||||
pushl $0 # err_code
|
pushl $0 # err_code
|
||||||
pushl $29 # int_no
|
pushl $29 # int_no
|
||||||
jmp interrupt_handler_prepare
|
jmp interrupt_handler_prepare
|
||||||
.global isr30
|
.global isr30
|
||||||
.type isr30, @function
|
.type isr30, @function
|
||||||
isr30:
|
isr30:
|
||||||
cli
|
|
||||||
pushl $0 # err_code
|
pushl $0 # err_code
|
||||||
pushl $30 # int_no
|
pushl $30 # int_no
|
||||||
jmp interrupt_handler_prepare
|
jmp interrupt_handler_prepare
|
||||||
.global isr31
|
.global isr31
|
||||||
.type isr31, @function
|
.type isr31, @function
|
||||||
isr31:
|
isr31:
|
||||||
cli
|
|
||||||
pushl $0 # err_code
|
pushl $0 # err_code
|
||||||
pushl $31 # int_no
|
pushl $31 # int_no
|
||||||
jmp interrupt_handler_prepare
|
jmp interrupt_handler_prepare
|
||||||
.global isr128
|
.global isr128
|
||||||
.type isr128, @function
|
.type isr128, @function
|
||||||
isr128:
|
isr128:
|
||||||
cli
|
|
||||||
pushl $0 # err_code
|
pushl $0 # err_code
|
||||||
pushl $128 # int_no
|
pushl $128 # int_no
|
||||||
jmp interrupt_handler_prepare
|
jmp interrupt_handler_prepare
|
||||||
.global isr130
|
.global isr130
|
||||||
.type isr130, @function
|
.type isr130, @function
|
||||||
isr130:
|
isr130:
|
||||||
cli
|
|
||||||
pushl $0 # err_code
|
pushl $0 # err_code
|
||||||
pushl $130 # int_no
|
pushl $130 # int_no
|
||||||
jmp interrupt_handler_prepare
|
jmp interrupt_handler_prepare
|
||||||
.global isr131
|
.global isr131
|
||||||
.type isr131, @function
|
.type isr131, @function
|
||||||
isr131:
|
isr131:
|
||||||
cli
|
|
||||||
pushl $0 # err_code
|
pushl $0 # err_code
|
||||||
pushl $131 # int_no
|
pushl $131 # int_no
|
||||||
jmp interrupt_handler_prepare
|
jmp interrupt_handler_prepare
|
||||||
.global irq0
|
.global irq0
|
||||||
.type irq0, @function
|
.type irq0, @function
|
||||||
irq0:
|
irq0:
|
||||||
cli
|
|
||||||
pushl $0 # err_code
|
pushl $0 # err_code
|
||||||
pushl $32 # int_no
|
pushl $32 # int_no
|
||||||
jmp interrupt_handler_prepare
|
jmp interrupt_handler_prepare
|
||||||
.global irq1
|
.global irq1
|
||||||
.type irq1, @function
|
.type irq1, @function
|
||||||
irq1:
|
irq1:
|
||||||
cli
|
|
||||||
pushl $0 # err_code
|
pushl $0 # err_code
|
||||||
pushl $33 # int_no
|
pushl $33 # int_no
|
||||||
jmp interrupt_handler_prepare
|
jmp interrupt_handler_prepare
|
||||||
.global irq2
|
.global irq2
|
||||||
.type irq2, @function
|
.type irq2, @function
|
||||||
irq2:
|
irq2:
|
||||||
cli
|
|
||||||
pushl $0 # err_code
|
pushl $0 # err_code
|
||||||
pushl $34 # int_no
|
pushl $34 # int_no
|
||||||
jmp interrupt_handler_prepare
|
jmp interrupt_handler_prepare
|
||||||
.global irq3
|
.global irq3
|
||||||
.type irq3, @function
|
.type irq3, @function
|
||||||
irq3:
|
irq3:
|
||||||
cli
|
|
||||||
pushl $0 # err_code
|
pushl $0 # err_code
|
||||||
pushl $35 # int_no
|
pushl $35 # int_no
|
||||||
jmp interrupt_handler_prepare
|
jmp interrupt_handler_prepare
|
||||||
.global irq4
|
.global irq4
|
||||||
.type irq4, @function
|
.type irq4, @function
|
||||||
irq4:
|
irq4:
|
||||||
cli
|
|
||||||
pushl $0 # err_code
|
pushl $0 # err_code
|
||||||
pushl $36 # int_no
|
pushl $36 # int_no
|
||||||
jmp interrupt_handler_prepare
|
jmp interrupt_handler_prepare
|
||||||
.global irq5
|
.global irq5
|
||||||
.type irq5, @function
|
.type irq5, @function
|
||||||
irq5:
|
irq5:
|
||||||
cli
|
|
||||||
pushl $0 # err_code
|
pushl $0 # err_code
|
||||||
pushl $37 # int_no
|
pushl $37 # int_no
|
||||||
jmp interrupt_handler_prepare
|
jmp interrupt_handler_prepare
|
||||||
.global irq6
|
.global irq6
|
||||||
.type irq6, @function
|
.type irq6, @function
|
||||||
irq6:
|
irq6:
|
||||||
cli
|
|
||||||
pushl $0 # err_code
|
pushl $0 # err_code
|
||||||
pushl $38 # int_no
|
pushl $38 # int_no
|
||||||
jmp interrupt_handler_prepare
|
jmp interrupt_handler_prepare
|
||||||
.global irq7
|
.global irq7
|
||||||
.type irq7, @function
|
.type irq7, @function
|
||||||
irq7:
|
irq7:
|
||||||
cli
|
|
||||||
pushl $0 # err_code
|
pushl $0 # err_code
|
||||||
pushl $39 # int_no
|
pushl $39 # int_no
|
||||||
jmp interrupt_handler_prepare
|
jmp interrupt_handler_prepare
|
||||||
.global irq8
|
.global irq8
|
||||||
.type irq8, @function
|
.type irq8, @function
|
||||||
irq8:
|
irq8:
|
||||||
cli
|
|
||||||
pushl $0 # err_code
|
pushl $0 # err_code
|
||||||
pushl $40 # int_no
|
pushl $40 # int_no
|
||||||
jmp interrupt_handler_prepare
|
jmp interrupt_handler_prepare
|
||||||
.global irq9
|
.global irq9
|
||||||
.type irq9, @function
|
.type irq9, @function
|
||||||
irq9:
|
irq9:
|
||||||
cli
|
|
||||||
pushl $0 # err_code
|
pushl $0 # err_code
|
||||||
pushl $41 # int_no
|
pushl $41 # int_no
|
||||||
jmp interrupt_handler_prepare
|
jmp interrupt_handler_prepare
|
||||||
.global irq10
|
.global irq10
|
||||||
.type irq10, @function
|
.type irq10, @function
|
||||||
irq10:
|
irq10:
|
||||||
cli
|
|
||||||
pushl $0 # err_code
|
pushl $0 # err_code
|
||||||
pushl $42 # int_no
|
pushl $42 # int_no
|
||||||
jmp interrupt_handler_prepare
|
jmp interrupt_handler_prepare
|
||||||
.global irq11
|
.global irq11
|
||||||
.type irq11, @function
|
.type irq11, @function
|
||||||
irq11:
|
irq11:
|
||||||
cli
|
|
||||||
pushl $0 # err_code
|
pushl $0 # err_code
|
||||||
pushl $43 # int_no
|
pushl $43 # int_no
|
||||||
jmp interrupt_handler_prepare
|
jmp interrupt_handler_prepare
|
||||||
.global irq12
|
.global irq12
|
||||||
.type irq12, @function
|
.type irq12, @function
|
||||||
irq12:
|
irq12:
|
||||||
cli
|
|
||||||
pushl $0 # err_code
|
pushl $0 # err_code
|
||||||
pushl $44 # int_no
|
pushl $44 # int_no
|
||||||
jmp interrupt_handler_prepare
|
jmp interrupt_handler_prepare
|
||||||
.global irq13
|
.global irq13
|
||||||
.type irq13, @function
|
.type irq13, @function
|
||||||
irq13:
|
irq13:
|
||||||
cli
|
|
||||||
pushl $0 # err_code
|
pushl $0 # err_code
|
||||||
pushl $45 # int_no
|
pushl $45 # int_no
|
||||||
jmp interrupt_handler_prepare
|
jmp interrupt_handler_prepare
|
||||||
.global irq14
|
.global irq14
|
||||||
.type irq14, @function
|
.type irq14, @function
|
||||||
irq14:
|
irq14:
|
||||||
cli
|
|
||||||
pushl $0 # err_code
|
pushl $0 # err_code
|
||||||
pushl $46 # int_no
|
pushl $46 # int_no
|
||||||
jmp interrupt_handler_prepare
|
jmp interrupt_handler_prepare
|
||||||
.global irq15
|
.global irq15
|
||||||
.type irq15, @function
|
.type irq15, @function
|
||||||
irq15:
|
irq15:
|
||||||
cli
|
|
||||||
pushl $0 # err_code
|
pushl $0 # err_code
|
||||||
pushl $47 # int_no
|
pushl $47 # int_no
|
||||||
jmp interrupt_handler_prepare
|
jmp interrupt_handler_prepare
|
||||||
.global yield_cpu_handler
|
.global yield_cpu_handler
|
||||||
.type yield_cpu_handler, @function
|
.type yield_cpu_handler, @function
|
||||||
yield_cpu_handler:
|
yield_cpu_handler:
|
||||||
cli
|
|
||||||
pushl $0 # err_code
|
pushl $0 # err_code
|
||||||
pushl $129 # int_no
|
pushl $129 # int_no
|
||||||
jmp interrupt_handler_prepare
|
jmp interrupt_handler_prepare
|
||||||
.global thread_exit_handler
|
.global thread_exit_handler
|
||||||
.type thread_exit_handler, @function
|
.type thread_exit_handler, @function
|
||||||
thread_exit_handler:
|
thread_exit_handler:
|
||||||
cli
|
|
||||||
pushl $0 # err_code
|
pushl $0 # err_code
|
||||||
pushl $132 # int_no
|
pushl $132 # int_no
|
||||||
jmp interrupt_handler_prepare
|
jmp interrupt_handler_prepare
|
||||||
|
@ -580,15 +527,6 @@ interrupt_handler_null:
|
||||||
iret
|
iret
|
||||||
.size interrupt_handler_null, . - interrupt_handler_null
|
.size interrupt_handler_null, . - interrupt_handler_null
|
||||||
|
|
||||||
.global asm_interrupts_are_enabled
|
|
||||||
.type asm_interrupts_are_enabled, @function
|
|
||||||
asm_interrupts_are_enabled:
|
|
||||||
pushfl
|
|
||||||
popl %eax
|
|
||||||
andl $0x000200, %eax # FLAGS_INTERRUPT
|
|
||||||
retl
|
|
||||||
.size asm_interrupts_are_enabled, . - asm_interrupts_are_enabled
|
|
||||||
|
|
||||||
.global load_registers
|
.global load_registers
|
||||||
.type load_registers, @function
|
.type load_registers, @function
|
||||||
load_registers:
|
load_registers:
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
|
|
||||||
Copyright(C) Jonas 'Sortie' Termansen 2011, 2012, 2013.
|
Copyright(C) Jonas 'Sortie' Termansen 2011, 2012, 2013, 2014.
|
||||||
|
|
||||||
This file is part of Sortix.
|
This file is part of Sortix.
|
||||||
|
|
||||||
|
@ -27,11 +27,6 @@
|
||||||
.section .text
|
.section .text
|
||||||
.type syscall_handler, @function
|
.type syscall_handler, @function
|
||||||
syscall_handler:
|
syscall_handler:
|
||||||
# The processor disabled interrupts during the int $0x80 instruction,
|
|
||||||
# however Sortix system calls runs with interrupts enabled such that they
|
|
||||||
# can be pre-empted.
|
|
||||||
sti
|
|
||||||
|
|
||||||
movl $0, global_errno # Reset errno
|
movl $0, global_errno # Reset errno
|
||||||
|
|
||||||
pushl %ebp
|
pushl %ebp
|
||||||
|
|
Loading…
Reference in New Issue