Refactor kernel interrupt handling.

This commit is contained in:
Jonas 'Sortie' Termansen 2013-06-20 00:01:04 +02:00
parent 4dad48271a
commit c77d9395cd
7 changed files with 168 additions and 261 deletions

View File

@ -48,7 +48,6 @@ ifdef X86FAMILY
$(CPU)/interrupt.o \ $(CPU)/interrupt.o \
$(CPU)/gdt.o \ $(CPU)/gdt.o \
x86-family/gdt.o \ x86-family/gdt.o \
$(CPU)/idt.o \
x86-family/idt.o \ x86-family/idt.o \
$(CPU)/syscall.o \ $(CPU)/syscall.o \
$(CPU)/thread.o \ $(CPU)/thread.o \

View File

@ -1,6 +1,6 @@
/******************************************************************************* /*******************************************************************************
Copyright(C) Jonas 'Sortie' Termansen 2011, 2012. Copyright(C) Jonas 'Sortie' Termansen 2011, 2012, 2013.
This file is part of Sortix. This file is part of Sortix.
@ -35,22 +35,22 @@ struct InterruptRegisters;
namespace Interrupt { namespace Interrupt {
const unsigned IRQ0 = 32; const unsigned int IRQ0 = 32;
const unsigned IRQ1 = 33; const unsigned int IRQ1 = 33;
const unsigned IRQ2 = 34; const unsigned int IRQ2 = 34;
const unsigned IRQ3 = 35; const unsigned int IRQ3 = 35;
const unsigned IRQ4 = 36; const unsigned int IRQ4 = 36;
const unsigned IRQ5 = 37; const unsigned int IRQ5 = 37;
const unsigned IRQ6 = 38; const unsigned int IRQ6 = 38;
const unsigned IRQ7 = 39; const unsigned int IRQ7 = 39;
const unsigned IRQ8 = 40; const unsigned int IRQ8 = 40;
const unsigned IRQ9 = 41; const unsigned int IRQ9 = 41;
const unsigned IRQ10 = 42; const unsigned int IRQ10 = 42;
const unsigned IRQ11 = 43; const unsigned int IRQ11 = 43;
const unsigned IRQ12 = 44; const unsigned int IRQ12 = 44;
const unsigned IRQ13 = 45; const unsigned int IRQ13 = 45;
const unsigned IRQ14 = 46; const unsigned int IRQ14 = 46;
const unsigned IRQ15 = 47; const unsigned int IRQ15 = 47;
extern "C" unsigned long asm_interrupts_are_enabled(); extern "C" unsigned long asm_interrupts_are_enabled();
extern "C" unsigned long asm_is_cpu_interrupted; extern "C" unsigned long asm_is_cpu_interrupted;
@ -67,10 +67,10 @@ inline bool SetEnabled(bool isenabled)
} }
typedef void (*Handler)(CPU::InterruptRegisters* regs, void* user); typedef void (*Handler)(CPU::InterruptRegisters* regs, void* user);
void RegisterHandler(unsigned index, Handler handler, void* user); void RegisterHandler(unsigned int index, Handler handler, void* user);
typedef void (*RawHandler)(void); typedef void (*RawHandler)(void);
void RegisterRawHandler(unsigned index, RawHandler handler, bool userspace); void RegisterRawHandler(unsigned int index, RawHandler handler, bool userspace);
void Init(); void Init();
void InitWorker(); void InitWorker();

View File

@ -22,9 +22,14 @@
*******************************************************************************/ *******************************************************************************/
#include <assert.h>
#include <errno.h>
#include <string.h>
#include <sortix/kernel/platform.h> #include <sortix/kernel/platform.h>
#include <sortix/kernel/syscall.h> #include <sortix/kernel/syscall.h>
#include <sortix/kernel/interrupt.h> #include <sortix/kernel/interrupt.h>
#include <sortix/kernel/cpu.h>
#include <sortix/kernel/scheduler.h> #include <sortix/kernel/scheduler.h>
#include <sortix/kernel/signal.h> #include <sortix/kernel/signal.h>
#include <sortix/kernel/thread.h> #include <sortix/kernel/thread.h>
@ -32,10 +37,6 @@
#include <sortix/kernel/calltrace.h> #include <sortix/kernel/calltrace.h>
#include <sortix/kernel/debugger.h> #include <sortix/kernel/debugger.h>
#include <assert.h>
#include <errno.h>
#include <string.h>
#include "x86-family/idt.h" #include "x86-family/idt.h"
#include "sound.h" // Hack for SIGSEGV #include "sound.h" // Hack for SIGSEGV
@ -67,42 +68,40 @@ const bool DEBUG_ISR = false;
const bool CALLTRACE_KERNEL = false; const bool CALLTRACE_KERNEL = false;
const bool CALLTRACE_USER = false; const bool CALLTRACE_USER = false;
const bool RUN_DEBUGGER_ON_CRASH = false; const bool RUN_DEBUGGER_ON_CRASH = false;
bool initialized;
const size_t NUM_KNOWN_EXCEPTIONS = 20; const size_t NUM_KNOWN_EXCEPTIONS = 20;
const char* exceptions[] = const char* exceptions[] =
{ {
"Divide by zero", "Divide by zero", /* 0, 0x0 */
"Debug", "Debug", /* 1, 0x1 */
"Non maskable interrupt", "Non maskable interrupt", /* 2, 0x2 */
"Breakpoint", "Breakpoint", /* 3, 0x3 */
"Into detected overflow", "Into detected overflow", /* 4, 0x4 */
"Out of bounds", "Out of bounds", /* 5, 0x5 */
"Invalid opcode", "Invalid opcode", /* 6, 0x6 */
"No coprocessor", "No coprocessor", /* 7, 0x7 */
"Double fault", "Double fault", /* 8, 0x8 */
"Coprocessor segment overrun", "Coprocessor segment overrun", /* 9, 0x9 */
"Bad TSS", "Bad TSS", /* 10, 0xA */
"Segment not present", "Segment not present", /* 11, 0xB */
"Stack fault", "Stack fault", /* 12, 0xC */
"General protection fault", "General protection fault", /* 13, 0xD */
"Page fault", "Page fault", /* 14, 0xE */
"Unknown interrupt", "Unknown interrupt", /* 15, 0xF */
"Coprocessor fault", "Coprocessor fault", /* 16, 0x10 */
"Alignment check", "Alignment check", /* 17, 0x11 */
"Machine check", "Machine check", /* 18, 0x12 */
"SIMD Floating-Point", "SIMD Floating-Point", /* 19, 0x13 */
}; };
const unsigned NUM_INTERRUPTS = 256UL; const unsigned int NUM_INTERRUPTS = 256UL;
static Handler interrupt_handlers[NUM_INTERRUPTS];
Handler interrupthandlers[NUM_INTERRUPTS]; static void* interrupt_handler_params[NUM_INTERRUPTS];
void* interrupthandlerptr[NUM_INTERRUPTS];
extern "C" void ReprogramPIC() extern "C" void ReprogramPIC()
{ {
uint8_t mastermask = 0; uint8_t master_mask = 0;
uint8_t slavemask = 0; uint8_t slave_mask = 0;
CPU::OutPortB(PIC_MASTER + PIC_COMMAND, PIC_CMD_INIT | PIC_ICW1_ICW4); 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_SLAVE + PIC_COMMAND, PIC_CMD_INIT | PIC_ICW1_ICW4);
CPU::OutPortB(PIC_MASTER + PIC_DATA, IRQ0); CPU::OutPortB(PIC_MASTER + PIC_DATA, IRQ0);
@ -111,14 +110,14 @@ extern "C" void ReprogramPIC()
CPU::OutPortB(PIC_SLAVE + PIC_DATA, 0x02); // Cascade Identity CPU::OutPortB(PIC_SLAVE + PIC_DATA, 0x02); // Cascade Identity
CPU::OutPortB(PIC_MASTER + PIC_DATA, PIC_MODE_8086); CPU::OutPortB(PIC_MASTER + PIC_DATA, PIC_MODE_8086);
CPU::OutPortB(PIC_SLAVE + PIC_DATA, PIC_MODE_8086); CPU::OutPortB(PIC_SLAVE + PIC_DATA, PIC_MODE_8086);
CPU::OutPortB(PIC_MASTER + PIC_DATA, mastermask); CPU::OutPortB(PIC_MASTER + PIC_DATA, master_mask);
CPU::OutPortB(PIC_SLAVE + PIC_DATA, slavemask); CPU::OutPortB(PIC_SLAVE + PIC_DATA, slave_mask);
} }
extern "C" void DeprogramPIC() extern "C" void DeprogramPIC()
{ {
uint8_t mastermask = 0; uint8_t master_mask = 0;
uint8_t slavemask = 0; uint8_t slave_mask = 0;
CPU::OutPortB(PIC_MASTER + PIC_COMMAND, PIC_CMD_INIT | PIC_ICW1_ICW4); 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_SLAVE + PIC_COMMAND, PIC_CMD_INIT | PIC_ICW1_ICW4);
CPU::OutPortB(PIC_MASTER + PIC_DATA, 0x08); CPU::OutPortB(PIC_MASTER + PIC_DATA, 0x08);
@ -127,19 +126,18 @@ extern "C" void DeprogramPIC()
CPU::OutPortB(PIC_SLAVE + PIC_DATA, 0x02); // Cascade Identity CPU::OutPortB(PIC_SLAVE + PIC_DATA, 0x02); // Cascade Identity
CPU::OutPortB(PIC_MASTER + PIC_DATA, PIC_MODE_8086); CPU::OutPortB(PIC_MASTER + PIC_DATA, PIC_MODE_8086);
CPU::OutPortB(PIC_SLAVE + PIC_DATA, PIC_MODE_8086); CPU::OutPortB(PIC_SLAVE + PIC_DATA, PIC_MODE_8086);
CPU::OutPortB(PIC_MASTER + PIC_DATA, mastermask); CPU::OutPortB(PIC_MASTER + PIC_DATA, master_mask);
CPU::OutPortB(PIC_SLAVE + PIC_DATA, slavemask); CPU::OutPortB(PIC_SLAVE + PIC_DATA, slave_mask);
} }
void Init() void Init()
{ {
initialized = false;
IDT::Init(); IDT::Init();
for ( unsigned i = 0; i < NUM_INTERRUPTS; i++ ) for ( unsigned int i = 0; i < NUM_INTERRUPTS; i++ )
{ {
interrupthandlers[i] = NULL; interrupt_handlers[i] = NULL;
interrupthandlerptr[i] = NULL; interrupt_handler_params[i] = NULL;
RegisterRawHandler(i, interrupt_handler_null, false); RegisterRawHandler(i, interrupt_handler_null, false);
} }
@ -198,37 +196,38 @@ void Init()
// TODO: Let the syscall.cpp code register this. // TODO: Let the syscall.cpp code register this.
RegisterRawHandler(128, syscall_handler, true); RegisterRawHandler(128, syscall_handler, true);
IDT::Flush();
initialized = true;
Interrupt::Enable(); Interrupt::Enable();
} }
void RegisterHandler(unsigned n, Interrupt::Handler handler, void* user) void RegisterHandler(unsigned int index, Interrupt::Handler handler, void* user)
{ {
interrupthandlers[n] = handler; interrupt_handlers[index] = handler;
interrupthandlerptr[n] = user; interrupt_handler_params[index] = user;
} }
// TODO: This function contains magic IDT-related values! // TODO: This function contains magic IDT-related values!
void RegisterRawHandler(unsigned index, RawHandler handler, bool userspace) void RegisterRawHandler(unsigned int index, RawHandler handler, bool userspace)
{ {
addr_t handlerentry = (addr_t) handler; addr_t handler_entry = (addr_t) handler;
uint16_t sel = 0x08; uint16_t sel = KCS;
uint8_t flags = 0x8E; uint8_t flags = 0x8E;
if ( userspace ) { flags |= 0x60; } if ( userspace )
IDT::SetGate(index, handlerentry, sel, flags); flags |= 0x60;
if ( initialized ) { IDT::Flush(); } IDT::SetEntry(index, handler_entry, sel, flags);
} }
void CrashHandler(CPU::InterruptRegisters* regs) void CrashHandler(CPU::InterruptRegisters* regs)
{ {
CurrentThread()->SaveRegisters(regs); CurrentThread()->SaveRegisters(regs);
const char* message = ( regs->int_no < NUM_KNOWN_EXCEPTIONS ) const char* message = regs->int_no < NUM_KNOWN_EXCEPTIONS
? exceptions[regs->int_no] : "Unknown"; ? exceptions[regs->int_no] : "Unknown";
if ( DEBUG_EXCEPTION ) { regs->LogRegisters(); Log::Print("\n"); } if ( DEBUG_EXCEPTION )
{
regs->LogRegisters();
Log::Print("\n");
}
#ifdef PLATFORM_X64 #ifdef PLATFORM_X64
addr_t ip = regs->rip; addr_t ip = regs->rip;
@ -237,8 +236,8 @@ void CrashHandler(CPU::InterruptRegisters* regs)
#endif #endif
// Halt and catch fire if we are the kernel. // Halt and catch fire if we are the kernel.
unsigned codemode = regs->cs & 0x3U; unsigned code_mode = regs->cs & 0x3;
bool is_in_kernel = !codemode; bool is_in_kernel = !code_mode;
bool is_in_user = !is_in_kernel; bool is_in_user = !is_in_kernel;
if ( (is_in_kernel && CALLTRACE_KERNEL) || (is_in_user && CALLTRACE_USER) ) if ( (is_in_kernel && CALLTRACE_KERNEL) || (is_in_user && CALLTRACE_USER) )
@ -267,9 +266,6 @@ void CrashHandler(CPU::InterruptRegisters* regs)
Log::PrintF("%s exception at ip=0x%zx (cr2=0x%p, err_code=0x%p)\n", Log::PrintF("%s exception at ip=0x%zx (cr2=0x%p, err_code=0x%p)\n",
message, ip, regs->cr2, regs->err_code); message, ip, regs->cr2, regs->err_code);
//addr_t topofstack = ((size_t*) regs->useresp)[0];
//Log::PrintF("Top of stack is 0x%zx\n", topofstack);
Sound::Mute(); Sound::Mute();
// Exit the process with the right error code. // Exit the process with the right error code.
@ -280,33 +276,30 @@ void CrashHandler(CPU::InterruptRegisters* regs)
Signal::Dispatch(regs); Signal::Dispatch(regs);
} }
void ISRHandler(Sortix::CPU::InterruptRegisters* regs) void ISRHandler(CPU::InterruptRegisters* regs)
{ {
unsigned int int_no = regs->int_no;
if ( DEBUG_ISR ) if ( DEBUG_ISR )
{ {
Log::PrintF("ISR%u ", regs->int_no); Log::PrintF("ISR%u ", int_no);
regs->LogRegisters(); regs->LogRegisters();
Log::Print("\n"); Log::Print("\n");
} }
if ( regs->int_no < 32 && regs->int_no != 7 ) // Run the desired interrupt handler.
{ if ( int_no < 32 && int_no != 7 )
CrashHandler(regs); CrashHandler(regs);
return; else if ( interrupt_handlers[regs->int_no] != NULL )
} interrupt_handlers[int_no](regs, interrupt_handler_params[int_no]);
if ( interrupthandlers[regs->int_no] != NULL )
{
void* user = interrupthandlerptr[regs->int_no];
interrupthandlers[regs->int_no](regs, user);
}
} }
void IRQHandler(Sortix::CPU::InterruptRegisters* regs) void IRQHandler(CPU::InterruptRegisters* regs)
{ {
// TODO: IRQ 7 and 15 might be spurious and might need to be ignored. // 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). // 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 + 7 || regs->int_no == 32 + 15 )
return;
if ( DEBUG_IRQ ) if ( DEBUG_IRQ )
{ {
@ -315,24 +308,23 @@ void IRQHandler(Sortix::CPU::InterruptRegisters* regs)
Log::Print("\n"); Log::Print("\n");
} }
unsigned int_no = regs->int_no; unsigned int int_no = regs->int_no;
// Send an EOI (end of interrupt) signal to the PICs. // Send an EOI (end of interrupt) signal to the PICs.
if ( IRQ8 <= int_no ) { CPU::OutPortB(PIC_SLAVE, PIC_CMD_ENDINTR); } if ( IRQ8 <= int_no )
CPU::OutPortB(PIC_SLAVE, PIC_CMD_ENDINTR);
CPU::OutPortB(PIC_MASTER, PIC_CMD_ENDINTR); CPU::OutPortB(PIC_MASTER, PIC_CMD_ENDINTR);
if ( interrupthandlers[int_no] ) if ( interrupt_handlers[int_no] )
{ interrupt_handlers[int_no](regs, interrupt_handler_params[int_no]);
void* user = interrupthandlerptr[int_no];
interrupthandlers[int_no](regs, user);
}
} }
extern "C" void interrupt_handler(Sortix::CPU::InterruptRegisters* regs) extern "C" void interrupt_handler(CPU::InterruptRegisters* regs)
{ {
size_t int_no = regs->int_no; if ( 32 <= regs->int_no && regs->int_no < 48 )
if ( 32 <= int_no && int_no < 48 ) { IRQHandler(regs); } IRQHandler(regs);
else { ISRHandler(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.
@ -357,9 +349,11 @@ void InitWorker()
const size_t QUEUE_SIZE = 4UL*1024UL; const size_t QUEUE_SIZE = 4UL*1024UL;
STATIC_ASSERT(QUEUE_SIZE % sizeof(Package) == 0); STATIC_ASSERT(QUEUE_SIZE % sizeof(Package) == 0);
queue = new uint8_t[QUEUE_SIZE]; queue = new uint8_t[QUEUE_SIZE];
if ( !queue ) { Panic("Can't allocate interrupt worker queue"); } if ( !queue )
Panic("Can't allocate interrupt worker queue");
storage = new uint8_t[QUEUE_SIZE]; storage = new uint8_t[QUEUE_SIZE];
if ( !storage ) { Panic("Can't allocate interrupt worker storage"); } if ( !storage )
Panic("Can't allocate interrupt worker storage");
queuesize = QUEUE_SIZE; queuesize = QUEUE_SIZE;
queueoffset = 0; queueoffset = 0;
queueused = 0; queueused = 0;
@ -373,7 +367,8 @@ static void WriteToQueue(const void* src, size_t size)
size_t count = available < size ? available : size; size_t count = available < size ? available : size;
memcpy(queue + writeat, buf, count); memcpy(queue + writeat, buf, count);
queueused += count; queueused += count;
if ( count < size ) { WriteToQueue(buf + count, size - count); } if ( count < size )
WriteToQueue(buf + count, size - count);
} }
static void ReadFromQueue(void* dest, size_t size) static void ReadFromQueue(void* dest, size_t size)
@ -384,7 +379,8 @@ static void ReadFromQueue(void* dest, size_t size)
memcpy(buf, queue + queueoffset, count); memcpy(buf, queue + queueoffset, count);
queueused -= count; queueused -= count;
queueoffset = (queueoffset + count) % queuesize; queueoffset = (queueoffset + count) % queuesize;
if ( count < size ) { ReadFromQueue(buf + count, size - count); } if ( count < size )
ReadFromQueue(buf + count, size - count);
} }
static Package* PopPackage(uint8_t** payloadp, Package* /*prev*/) static Package* PopPackage(uint8_t** payloadp, Package* /*prev*/)
@ -393,7 +389,8 @@ static Package* PopPackage(uint8_t** payloadp, Package* /*prev*/)
uint8_t* payload = NULL; uint8_t* payload = NULL;
Interrupt::Disable(); Interrupt::Disable();
if ( !queueused ) { goto out; } if ( !queueused )
goto out;
package = (Package*) storage; package = (Package*) storage;
ReadFromQueue(package, sizeof(*package)); ReadFromQueue(package, sizeof(*package));
@ -431,7 +428,8 @@ bool ScheduleWork(WorkHandler handler, void* payload, size_t payloadsize)
package.handler = handler; package.handler = handler;
size_t queuefreespace = queuesize - queueused; size_t queuefreespace = queuesize - queueused;
if ( queuefreespace < package.size ) { return false; } if ( queuefreespace < package.size )
return false;
WriteToQueue(&package, sizeof(package)); WriteToQueue(&package, sizeof(package));
WriteToQueue(payload, payloadsize); WriteToQueue(payload, payloadsize);

View File

@ -1,33 +0,0 @@
/*******************************************************************************
Copyright(C) Jonas 'Sortie' Termansen 2011, 2012.
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/>.
x64/idt.s
Handles initialization of the 64-bit IDT.
*******************************************************************************/
.section .text
.global idt_flush
.type idt_flush, @function
idt_flush:
# Load the IDT pointer.
lidt (%rdi)
ret
.size idt_flush, . - idt_flush

View File

@ -1,6 +1,6 @@
/******************************************************************************* /*******************************************************************************
Copyright(C) Jonas 'Sortie' Termansen 2011, 2012. Copyright(C) Jonas 'Sortie' Termansen 2011, 2012, 2013.
This file is part of Sortix. This file is part of Sortix.
@ -18,48 +18,64 @@
Sortix. If not, see <http://www.gnu.org/licenses/>. Sortix. If not, see <http://www.gnu.org/licenses/>.
x86-family/idt.cpp x86-family/idt.cpp
Initializes and handles the IDT. Initializes and handles the interrupt descriptor table.
*******************************************************************************/ *******************************************************************************/
#include <sortix/kernel/platform.h> #include <stdint.h>
#include <string.h> #include <string.h>
#include "idt.h" #include "idt.h"
namespace Sortix namespace Sortix {
namespace IDT {
struct idt_entry
{ {
namespace IDT uint16_t handler_low;
{ uint16_t sel;
extern "C" void idt_flush(addr_t); uint8_t reserved0;
uint8_t flags;
idt_entry_t idt_entries[256]; uint16_t handler_high;
idt_ptr_t idt_ptr; #if defined(__x86_64__)
uint32_t handler_highest;
void Init() uint32_t reserved1;
{
idt_ptr.limit = sizeof(idt_entry_t) * 256 - 1;
idt_ptr.base = (addr_t) &idt_entries;
memset(&idt_entries, 0, sizeof(idt_entry_t)*256);
}
void Flush()
{
idt_flush((addr_t) &idt_ptr);
}
void SetGate(uint8_t num, addr_t base, uint16_t sel, uint8_t flags)
{
idt_entries[num].base_low = base & 0xFFFF;
idt_entries[num].base_high = (base >> 16) & 0xFFFF;
#ifdef PLATFORM_X64
idt_entries[num].base_highest = (base >> 32 ) & 0xFFFFFFFFU;
idt_entries[num].zero1 = 0;
#endif #endif
};
idt_entries[num].sel = sel; struct idt_ptr
idt_entries[num].always0 = 0; {
idt_entries[num].flags = flags; 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];
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));
} }
void SetEntry(uint8_t num, uintptr_t handler, uint16_t sel, uint8_t flags)
{
idt_entries[num].flags = flags;
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__)
idt_entries[num].handler_highest = handler >> 32 & 0xFFFFFFFFU;
idt_entries[num].reserved1 = 0;
#endif
}
} // namespace IDT
} // namespace Sortix

View File

@ -1,6 +1,6 @@
/******************************************************************************* /*******************************************************************************
Copyright(C) Jonas 'Sortie' Termansen 2011, 2012. Copyright(C) Jonas 'Sortie' Termansen 2011, 2012, 2013.
This file is part of Sortix. This file is part of Sortix.
@ -25,53 +25,14 @@
#ifndef SORTIX_X86_FAMILY_IDT_H #ifndef SORTIX_X86_FAMILY_IDT_H
#define SORTIX_X86_FAMILY_IDT_H #define SORTIX_X86_FAMILY_IDT_H
namespace Sortix namespace Sortix {
{ namespace IDT {
namespace IDT
{
// A struct describing an interrupt gate.
struct idt_entry32_struct
{
uint16_t base_low; // The lower 16 bits of the address to jump to when this interrupt fires.
uint16_t sel; // Kernel segment selector.
uint8_t always0; // This must always be zero.
uint8_t flags; // More flags. See documentation.
uint16_t base_high; // The upper 16 bits of the address to jump to.
} __attribute__((packed));
struct idt_entry64_struct void Init();
{ void SetEntry(uint8_t num, uintptr_t handler, uint16_t sel, uint8_t flags);
uint16_t base_low; // The lower 16 bits of the address to jump to when this interrupt fires. void Flush();
uint16_t sel; // Kernel segment selector.
uint8_t always0; // This must always be zero.
uint8_t flags; // More flags. See documentation.
uint16_t base_high; // The upper 16 bits of the address to jump to.
uint32_t base_highest;
uint32_t zero1; // Reserved
} __attribute__((packed));
typedef struct idt_entry32_struct idt_entry32_t; } // namespace IDT
typedef struct idt_entry64_struct idt_entry64_t; } // namespace Sortix
#ifdef PLATFORM_X64
typedef idt_entry64_t idt_entry_t;
#else
typedef idt_entry32_t idt_entry_t;
#endif
// A struct describing a pointer to an array of interrupt handlers.
// This is in a format suitable for giving to 'lidt'.
struct idt_ptr_struct
{
uint16_t limit;
addr_t base; // The address of the first element in our idt_entry_t array.
} __attribute__((packed));
typedef struct idt_ptr_struct idt_ptr_t;
void Init();
void SetGate(uint8_t num, addr_t base, uint16_t sel, uint8_t flags);
void Flush();
}
}
#endif #endif

View File

@ -1,34 +0,0 @@
/*******************************************************************************
Copyright(C) Jonas 'Sortie' Termansen 2011, 2012.
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/idt.s
Handles initialization of the 32-bit IDT.
*******************************************************************************/
.section .text
.global idt_flush
.type idt_flush, @function
idt_flush:
# Load the IDT pointer.
mov 4(%esp), %eax
lidt (%eax)
ret
.size idt_flush, . - idt_flush