Added support for 64-bit interrupts.
This commit is contained in:
parent
f0ec4ffacc
commit
f460c4abec
|
@ -167,85 +167,84 @@ namespace Sortix
|
|||
|
||||
void Init()
|
||||
{
|
||||
#ifdef PLATFORM_X86
|
||||
idt_ptr.limit = sizeof(idt_entry_t) * 256 - 1;
|
||||
idt_ptr.base = (uint32_t)&idt_entries;
|
||||
idt_ptr.base = (addr_t) &idt_entries;
|
||||
|
||||
Memory::Set(&idt_entries, 0, sizeof(idt_entry_t)*256);
|
||||
|
||||
// Remap the irq table.
|
||||
X86::OutPortB(0x20, 0x11);
|
||||
X86::OutPortB(0xA0, 0x11);
|
||||
X86::OutPortB(0x21, 0x20);
|
||||
X86::OutPortB(0xA1, 0x28);
|
||||
X86::OutPortB(0x21, 0x04);
|
||||
X86::OutPortB(0xA1, 0x02);
|
||||
X86::OutPortB(0x21, 0x01);
|
||||
X86::OutPortB(0xA1, 0x01);
|
||||
X86::OutPortB(0x21, 0x0);
|
||||
X86::OutPortB(0xA1, 0x0);
|
||||
CPU::OutPortB(0x20, 0x11);
|
||||
CPU::OutPortB(0xA0, 0x11);
|
||||
CPU::OutPortB(0x21, 0x20);
|
||||
CPU::OutPortB(0xA1, 0x28);
|
||||
CPU::OutPortB(0x21, 0x04);
|
||||
CPU::OutPortB(0xA1, 0x02);
|
||||
CPU::OutPortB(0x21, 0x01);
|
||||
CPU::OutPortB(0xA1, 0x01);
|
||||
CPU::OutPortB(0x21, 0x0);
|
||||
CPU::OutPortB(0xA1, 0x0);
|
||||
|
||||
SetGate( 0, (uint32_t) isr0 , 0x08, 0x8E);
|
||||
SetGate( 1, (uint32_t) isr1 , 0x08, 0x8E);
|
||||
SetGate( 2, (uint32_t) isr2 , 0x08, 0x8E);
|
||||
SetGate( 3, (uint32_t) isr3 , 0x08, 0x8E);
|
||||
SetGate( 4, (uint32_t) isr4 , 0x08, 0x8E);
|
||||
SetGate( 5, (uint32_t) isr5 , 0x08, 0x8E);
|
||||
SetGate( 6, (uint32_t) isr6 , 0x08, 0x8E);
|
||||
SetGate( 7, (uint32_t) isr7 , 0x08, 0x8E);
|
||||
SetGate( 8, (uint32_t) isr8 , 0x08, 0x8E);
|
||||
SetGate( 9, (uint32_t) isr9 , 0x08, 0x8E);
|
||||
SetGate(10, (uint32_t) isr10, 0x08, 0x8E);
|
||||
SetGate(11, (uint32_t) isr11, 0x08, 0x8E);
|
||||
SetGate(12, (uint32_t) isr12, 0x08, 0x8E);
|
||||
SetGate(13, (uint32_t) isr13, 0x08, 0x8E);
|
||||
SetGate(14, (uint32_t) isr14, 0x08, 0x8E);
|
||||
SetGate(15, (uint32_t) isr15, 0x08, 0x8E);
|
||||
SetGate(16, (uint32_t) isr16, 0x08, 0x8E);
|
||||
SetGate(17, (uint32_t) isr17, 0x08, 0x8E);
|
||||
SetGate(18, (uint32_t) isr18, 0x08, 0x8E);
|
||||
SetGate(19, (uint32_t) isr19, 0x08, 0x8E);
|
||||
SetGate(20, (uint32_t) isr20, 0x08, 0x8E);
|
||||
SetGate(21, (uint32_t) isr21, 0x08, 0x8E);
|
||||
SetGate(22, (uint32_t) isr22, 0x08, 0x8E);
|
||||
SetGate(23, (uint32_t) isr23, 0x08, 0x8E);
|
||||
SetGate(24, (uint32_t) isr24, 0x08, 0x8E);
|
||||
SetGate(25, (uint32_t) isr25, 0x08, 0x8E);
|
||||
SetGate(26, (uint32_t) isr26, 0x08, 0x8E);
|
||||
SetGate(27, (uint32_t) isr27, 0x08, 0x8E);
|
||||
SetGate(28, (uint32_t) isr28, 0x08, 0x8E);
|
||||
SetGate(29, (uint32_t) isr29, 0x08, 0x8E);
|
||||
SetGate(30, (uint32_t) isr30, 0x08, 0x8E);
|
||||
SetGate(31, (uint32_t) isr31, 0x08, 0x8E);
|
||||
SetGate(32, (uint32_t) irq0, 0x08, 0x8E);
|
||||
SetGate(33, (uint32_t) irq1, 0x08, 0x8E);
|
||||
SetGate(34, (uint32_t) irq2, 0x08, 0x8E);
|
||||
SetGate(35, (uint32_t) irq3, 0x08, 0x8E);
|
||||
SetGate(36, (uint32_t) irq4, 0x08, 0x8E);
|
||||
SetGate(37, (uint32_t) irq5, 0x08, 0x8E);
|
||||
SetGate(38, (uint32_t) irq6, 0x08, 0x8E);
|
||||
SetGate(39, (uint32_t) irq7, 0x08, 0x8E);
|
||||
SetGate(40, (uint32_t) irq8, 0x08, 0x8E);
|
||||
SetGate(41, (uint32_t) irq9, 0x08, 0x8E);
|
||||
SetGate(42, (uint32_t) irq10, 0x08, 0x8E);
|
||||
SetGate(43, (uint32_t) irq11, 0x08, 0x8E);
|
||||
SetGate(44, (uint32_t) irq12, 0x08, 0x8E);
|
||||
SetGate(45, (uint32_t) irq13, 0x08, 0x8E);
|
||||
SetGate(46, (uint32_t) irq14, 0x08, 0x8E);
|
||||
SetGate(47, (uint32_t) irq15, 0x08, 0x8E);
|
||||
SetGate(128, (uint32_t) syscall_handler, 0x08, 0x8E | 0x60); // System Calls
|
||||
SetGate( 0, (addr_t) isr0 , 0x08, 0x8E);
|
||||
SetGate( 1, (addr_t) isr1 , 0x08, 0x8E);
|
||||
SetGate( 2, (addr_t) isr2 , 0x08, 0x8E);
|
||||
SetGate( 3, (addr_t) isr3 , 0x08, 0x8E);
|
||||
SetGate( 4, (addr_t) isr4 , 0x08, 0x8E);
|
||||
SetGate( 5, (addr_t) isr5 , 0x08, 0x8E);
|
||||
SetGate( 6, (addr_t) isr6 , 0x08, 0x8E);
|
||||
SetGate( 7, (addr_t) isr7 , 0x08, 0x8E);
|
||||
SetGate( 8, (addr_t) isr8 , 0x08, 0x8E);
|
||||
SetGate( 9, (addr_t) isr9 , 0x08, 0x8E);
|
||||
SetGate(10, (addr_t) isr10, 0x08, 0x8E);
|
||||
SetGate(11, (addr_t) isr11, 0x08, 0x8E);
|
||||
SetGate(12, (addr_t) isr12, 0x08, 0x8E);
|
||||
SetGate(13, (addr_t) isr13, 0x08, 0x8E);
|
||||
SetGate(14, (addr_t) isr14, 0x08, 0x8E);
|
||||
SetGate(15, (addr_t) isr15, 0x08, 0x8E);
|
||||
SetGate(16, (addr_t) isr16, 0x08, 0x8E);
|
||||
SetGate(17, (addr_t) isr17, 0x08, 0x8E);
|
||||
SetGate(18, (addr_t) isr18, 0x08, 0x8E);
|
||||
SetGate(19, (addr_t) isr19, 0x08, 0x8E);
|
||||
SetGate(20, (addr_t) isr20, 0x08, 0x8E);
|
||||
SetGate(21, (addr_t) isr21, 0x08, 0x8E);
|
||||
SetGate(22, (addr_t) isr22, 0x08, 0x8E);
|
||||
SetGate(23, (addr_t) isr23, 0x08, 0x8E);
|
||||
SetGate(24, (addr_t) isr24, 0x08, 0x8E);
|
||||
SetGate(25, (addr_t) isr25, 0x08, 0x8E);
|
||||
SetGate(26, (addr_t) isr26, 0x08, 0x8E);
|
||||
SetGate(27, (addr_t) isr27, 0x08, 0x8E);
|
||||
SetGate(28, (addr_t) isr28, 0x08, 0x8E);
|
||||
SetGate(29, (addr_t) isr29, 0x08, 0x8E);
|
||||
SetGate(30, (addr_t) isr30, 0x08, 0x8E);
|
||||
SetGate(31, (addr_t) isr31, 0x08, 0x8E);
|
||||
SetGate(32, (addr_t) irq0, 0x08, 0x8E);
|
||||
SetGate(33, (addr_t) irq1, 0x08, 0x8E);
|
||||
SetGate(34, (addr_t) irq2, 0x08, 0x8E);
|
||||
SetGate(35, (addr_t) irq3, 0x08, 0x8E);
|
||||
SetGate(36, (addr_t) irq4, 0x08, 0x8E);
|
||||
SetGate(37, (addr_t) irq5, 0x08, 0x8E);
|
||||
SetGate(38, (addr_t) irq6, 0x08, 0x8E);
|
||||
SetGate(39, (addr_t) irq7, 0x08, 0x8E);
|
||||
SetGate(40, (addr_t) irq8, 0x08, 0x8E);
|
||||
SetGate(41, (addr_t) irq9, 0x08, 0x8E);
|
||||
SetGate(42, (addr_t) irq10, 0x08, 0x8E);
|
||||
SetGate(43, (addr_t) irq11, 0x08, 0x8E);
|
||||
SetGate(44, (addr_t) irq12, 0x08, 0x8E);
|
||||
SetGate(45, (addr_t) irq13, 0x08, 0x8E);
|
||||
SetGate(46, (addr_t) irq14, 0x08, 0x8E);
|
||||
SetGate(47, (addr_t) irq15, 0x08, 0x8E);
|
||||
SetGate(128, (addr_t) syscall_handler, 0x08, 0x8E | 0x60); // System Calls
|
||||
|
||||
idt_flush((uint32_t)&idt_ptr);
|
||||
#else
|
||||
#warning "IDT is not yet supported on this arch!"
|
||||
while(true);
|
||||
#endif
|
||||
idt_flush((addr_t) &idt_ptr);
|
||||
}
|
||||
|
||||
void SetGate(uint8_t num, uint32_t base, uint16_t sel, uint8_t flags)
|
||||
void SetGate(uint8_t num, addr_t base, uint16_t sel, uint8_t flags)
|
||||
{
|
||||
idt_entries[num].base_lo = base & 0xFFFF;
|
||||
idt_entries[num].base_hi = (base >> 16) & 0xFFFF;
|
||||
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
|
||||
|
||||
idt_entries[num].sel = sel;
|
||||
idt_entries[num].always0 = 0;
|
||||
|
|
|
@ -127,16 +127,34 @@ namespace Sortix
|
|||
{
|
||||
|
||||
// A struct describing an interrupt gate.
|
||||
struct idt_entry_struct
|
||||
struct idt_entry32_struct
|
||||
{
|
||||
uint16_t base_lo; // The lower 16 bits of the address to jump to when this interrupt fires.
|
||||
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_hi; // The upper 16 bits of the address to jump to.
|
||||
uint16_t base_high; // The upper 16 bits of the address to jump to.
|
||||
} __attribute__((packed));
|
||||
|
||||
typedef struct idt_entry_struct idt_entry_t;
|
||||
struct idt_entry64_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.
|
||||
uint32_t base_highest;
|
||||
uint32_t zero1; // Reserved
|
||||
} __attribute__((packed));
|
||||
|
||||
typedef struct idt_entry32_struct idt_entry32_t;
|
||||
typedef struct idt_entry64_struct idt_entry64_t;
|
||||
#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'.
|
||||
|
@ -149,7 +167,7 @@ namespace Sortix
|
|||
typedef struct idt_ptr_struct idt_ptr_t;
|
||||
|
||||
void Init();
|
||||
void SetGate(uint8_t num, uint32_t base, uint16_t sel, uint8_t flags);
|
||||
void SetGate(uint8_t num, addr_t base, uint16_t sel, uint8_t flags);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -54,6 +54,14 @@ namespace Sortix
|
|||
|
||||
Handler interrupthandlers[256];
|
||||
|
||||
void Init()
|
||||
{
|
||||
for ( size_t i = 0; i < 256; i++ )
|
||||
{
|
||||
interrupthandlers[i] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void RegisterHandler(uint8_t n, Interrupt::Handler handler)
|
||||
{
|
||||
interrupthandlers[n] = handler;
|
||||
|
@ -62,7 +70,6 @@ namespace Sortix
|
|||
// This gets called from our ASM interrupt handler stub.
|
||||
extern "C" void ISRHandler(Sortix::CPU::InterruptRegisters* regs)
|
||||
{
|
||||
#ifdef PLATFORM_X86
|
||||
if ( regs->int_no < 32 )
|
||||
{
|
||||
const char* message = ( regs->int_no < numknownexceptions )
|
||||
|
@ -70,17 +77,23 @@ namespace Sortix
|
|||
|
||||
if ( DEBUG_EXCEPTION ) { regs->LogRegisters(); Log::Print("\n"); }
|
||||
|
||||
#ifdef PLATFORM_X64
|
||||
addr_t ip = regs->rip;
|
||||
#else
|
||||
addr_t ip = regs->eip;
|
||||
#endif
|
||||
|
||||
// Halt and catch fire if we are the kernel.
|
||||
if ( (regs->cs & (0x4-1)) == 0 )
|
||||
{
|
||||
PanicF("Unhandled CPU Exception id %zu '%s' at eip=0x%zx "
|
||||
PanicF("Unhandled CPU Exception id %zu '%s' at ip=0x%zx "
|
||||
"(cr2=0x%p, err_code=0x%p)", regs->int_no, message,
|
||||
regs->eip, regs->cr2, regs->err_code);
|
||||
ip, regs->cr2, regs->err_code);
|
||||
}
|
||||
|
||||
Log::Print("The current program has crashed and was terminated:\n");
|
||||
Log::PrintF("%s exception at eip=0x%zx (cr2=0x%p, err_code=0x%p)\n",
|
||||
message, regs->eip, regs->cr2, regs->err_code);
|
||||
Log::PrintF("%s exception at ip=0x%zx (cr2=0x%p, err_code=0x%p)\n",
|
||||
message, ip, regs->cr2, regs->err_code);
|
||||
|
||||
Sound::Mute();
|
||||
|
||||
|
@ -94,16 +107,11 @@ namespace Sortix
|
|||
{
|
||||
interrupthandlers[regs->int_no](regs);
|
||||
}
|
||||
#else
|
||||
#warning "ISR handlers are not supported on this arch"
|
||||
while(true);
|
||||
#endif
|
||||
}
|
||||
|
||||
// This gets called from our ASM interrupt handler stub.
|
||||
extern "C" void IRQHandler(Sortix::CPU::InterruptRegisters* regs)
|
||||
{
|
||||
#ifdef PLATFORM_X86
|
||||
// TODO! IRQ 7 and 15 might be spurious and might need to be ignored.
|
||||
// See http://wiki.osdev.org/PIC for details (section Spurious IRQs).
|
||||
if ( regs->int_no == 32 + 7 || regs->int_no == 32 + 15 ) { return; }
|
||||
|
@ -115,28 +123,25 @@ namespace Sortix
|
|||
Log::Print("\n");
|
||||
}
|
||||
|
||||
if ( regs->int_no < 32 || 48 < regs->int_no )
|
||||
{
|
||||
PanicF("IRQ eax=%u, int_no=%u, err_code=%u, eip=%u!",
|
||||
regs->eax, regs->int_no, regs->err_code, regs->eip);
|
||||
}
|
||||
|
||||
// Send an EOI (end of interrupt) signal to the PICs.
|
||||
|
||||
// Send reset signal to slave if this interrupt involved the slave.
|
||||
if (regs->int_no >= 40) { X86::OutPortB(0xA0, 0x20); }
|
||||
if (regs->int_no >= 40) { CPU::OutPortB(0xA0, 0x20); }
|
||||
|
||||
// Send reset signal to master.
|
||||
X86::OutPortB(0x20, 0x20);
|
||||
CPU::OutPortB(0x20, 0x20);
|
||||
|
||||
if ( interrupthandlers[regs->int_no] != NULL )
|
||||
if ( interrupthandlers[regs->int_no] )
|
||||
{
|
||||
interrupthandlers[regs->int_no](regs);
|
||||
}
|
||||
#else
|
||||
#warning "IRQ handlers are not supported on this arch"
|
||||
while(true);
|
||||
#endif
|
||||
}
|
||||
|
||||
extern "C" void interrupt_handler(Sortix::CPU::InterruptRegisters* regs)
|
||||
{
|
||||
size_t int_no = regs->int_no;
|
||||
if ( 32 <= int_no && int_no < 48 ) { IRQHandler(regs); }
|
||||
else { ISRHandler(regs); }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -49,6 +49,8 @@ namespace Sortix
|
|||
typedef void (*Handler)(CPU::InterruptRegisters* Registers);
|
||||
|
||||
void RegisterHandler(uint8_t n, Handler handler);
|
||||
|
||||
void Init();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -50,6 +50,7 @@
|
|||
#include "filesystem.h"
|
||||
#include "mount.h"
|
||||
#include "directory.h"
|
||||
#include "interrupt.h"
|
||||
|
||||
using namespace Maxsi;
|
||||
|
||||
|
@ -183,6 +184,28 @@ namespace Sortix
|
|||
// Display the boot welcome screen.
|
||||
DoWelcome();
|
||||
|
||||
if ( BootInfo == NULL ) { Panic("kernel.cpp: The bootinfo structure was NULL. Are your bootloader multiboot compliant?"); }
|
||||
|
||||
uint8_t* initrd = NULL;
|
||||
size_t initrdsize = 0;
|
||||
|
||||
#ifndef JSSORTIX
|
||||
uint32_t* modules = (uint32_t*) BootInfo->mods_addr;
|
||||
for ( uint32_t I = 0; I < BootInfo->mods_count; I++ )
|
||||
{
|
||||
initrdsize = modules[2*I+1] - modules[2*I+0];
|
||||
initrd = (uint8_t*) modules[2*I+0];
|
||||
break;
|
||||
}
|
||||
|
||||
if ( initrd == NULL ) { PanicF("No init ramdisk provided"); }
|
||||
|
||||
#else
|
||||
// TODO: UGLY HACK because JSVM doesn't support multiboot yet!
|
||||
initrd = (uint8_t*) 0x180000UL;
|
||||
initrdsize = 0x80000; // 512 KiB
|
||||
#endif
|
||||
|
||||
#ifndef JSSORTIX
|
||||
// Search for PCI devices and load their drivers.
|
||||
PCI::Init();
|
||||
|
@ -191,41 +214,15 @@ namespace Sortix
|
|||
// Initialize the paging and virtual memory.
|
||||
Memory::Init(BootInfo);
|
||||
|
||||
uint8_t* initrd = NULL;
|
||||
size_t initrdsize = 0;
|
||||
|
||||
#ifndef JSSORTIX
|
||||
uint8_t** modules = (uint8_t**) BootInfo->mods_addr;
|
||||
for ( uint32_t I = 0; I < BootInfo->mods_count; I++ )
|
||||
{
|
||||
initrdsize = modules[2*I+1] - modules[2*I+0];
|
||||
initrd = modules[2*I+0];
|
||||
break;
|
||||
}
|
||||
#else
|
||||
// TODO: UGLY HACK because JSVM doesn't support multiboot yet!
|
||||
initrd = (uint8_t*) 0x180000UL;
|
||||
initrdsize = 0x80000; // 512 KiB
|
||||
#endif
|
||||
|
||||
if ( initrd == NULL ) { PanicF("No initrd provided"); }
|
||||
|
||||
// Initialize the GDT and TSS structures.
|
||||
GDT::Init();
|
||||
|
||||
#ifdef PLATFORM_X64
|
||||
Log::Print("Halt: CPU x64 cannot boot because interrupts are not yet "
|
||||
"supported under 64-bit Sortix.\n");
|
||||
Log::Print("Sorry, it simply isn't possible to fully boot Sortix in x64 mode yet.\n");
|
||||
Log::Print("x64 may be working when Sortix 0.6 comes out, or try the git master.\n");
|
||||
while(true);
|
||||
#endif
|
||||
// Initialize the interrupt handler table to zeroes.
|
||||
Interrupt::Init();
|
||||
|
||||
// Initialize the interrupt descriptor tables.
|
||||
// Initialize the interrupt descriptor tables (enabling interrupts).
|
||||
IDT::Init();
|
||||
|
||||
if ( BootInfo == NULL ) { Panic("kernel.cpp: The bootinfo structure was NULL. Are your bootloader multiboot compliant?"); }
|
||||
|
||||
// Initialize the kernel heap.
|
||||
Maxsi::Memory::Init();
|
||||
|
||||
|
@ -265,6 +262,13 @@ namespace Sortix
|
|||
// Set up the initial ram disk.
|
||||
InitRD::Init(initrd, initrdsize);
|
||||
|
||||
#ifdef PLATFORM_X64
|
||||
Log::Print("Halt: There is no program loader for 64-bit Sortix\n");
|
||||
Log::Print("Sorry, it simply isn't possible to fully boot Sortix in x64 mode yet.\n");
|
||||
Log::Print("x64 may be working when Sortix 0.5 comes out, or try the git master.\n");
|
||||
while(true);
|
||||
#endif
|
||||
|
||||
// Alright, now the system's drivers are loaded and initialized. It is
|
||||
// time to load the initial user-space programs and start execution of
|
||||
// the actual operating system.
|
||||
|
|
|
@ -26,7 +26,6 @@
|
|||
.globl start, _start
|
||||
|
||||
.section .text
|
||||
|
||||
.text 0x100000
|
||||
.type _start, @function
|
||||
.code32
|
||||
|
|
|
@ -36,9 +36,11 @@ gdt_flush:
|
|||
mov %ax, %es
|
||||
mov %ax, %fs
|
||||
mov %ax, %gs
|
||||
mov %ax, %ss
|
||||
|
||||
# 0x08 is the offset to our code segment: Far jump!
|
||||
ljmp *GDT_FLUSH_POSTJMP
|
||||
# Far jump to our new code segment!
|
||||
movq $GDT_FLUSH_POSTJMP, %rax
|
||||
ljmp *(%rax)
|
||||
gdt_flush_postjmp:
|
||||
ret
|
||||
|
||||
|
@ -67,5 +69,5 @@ tss_flush:
|
|||
.section .data
|
||||
GDT_FLUSH_POSTJMP:
|
||||
.long gdt_flush_postjmp
|
||||
.word 0x08
|
||||
.word 0x08 # 0x08 is the offset to our code segment
|
||||
|
||||
|
|
|
@ -1,108 +0,0 @@
|
|||
;
|
||||
; interrupt.s -- Contains interrupt service routine wrappers.
|
||||
; Based on Bran's kernel development tutorials.
|
||||
; Rewritten for JamesM's kernel development tutorials.
|
||||
|
||||
; This macro creates a stub for an ISR which does NOT pass it's own
|
||||
; error code (adds a dummy errcode byte).
|
||||
%macro ISR_NOERRCODE 1
|
||||
global isr%1
|
||||
isr%1:
|
||||
cli ; Disable interrupts firstly.
|
||||
push long 0 ; Push a dummy error code.
|
||||
push long %1 ; Push the interrupt number.
|
||||
jmp isr_common_stub ; Go to our common handler code.
|
||||
%endmacro
|
||||
|
||||
; This macro creates a stub for an ISR which passes it's own
|
||||
; error code.
|
||||
%macro ISR_ERRCODE 1
|
||||
global isr%1
|
||||
isr%1:
|
||||
cli ; Disable interrupts.
|
||||
push long %1 ; Push the interrupt number
|
||||
jmp isr_common_stub
|
||||
%endmacro
|
||||
|
||||
; This macro creates a stub for an IRQ - the first parameter is
|
||||
; the IRQ number, the second is the ISR number it is remapped to.
|
||||
%macro IRQ 2
|
||||
global irq%1
|
||||
irq%1:
|
||||
cli
|
||||
push long 0
|
||||
push long %2
|
||||
jmp irq_common_stub
|
||||
%endmacro
|
||||
|
||||
ISR_NOERRCODE 0
|
||||
ISR_NOERRCODE 1
|
||||
ISR_NOERRCODE 2
|
||||
ISR_NOERRCODE 3
|
||||
ISR_NOERRCODE 4
|
||||
ISR_NOERRCODE 5
|
||||
ISR_NOERRCODE 6
|
||||
ISR_NOERRCODE 7
|
||||
ISR_ERRCODE 8
|
||||
ISR_NOERRCODE 9
|
||||
ISR_ERRCODE 10
|
||||
ISR_ERRCODE 11
|
||||
ISR_ERRCODE 12
|
||||
ISR_ERRCODE 13
|
||||
ISR_ERRCODE 14
|
||||
ISR_NOERRCODE 15
|
||||
ISR_NOERRCODE 16
|
||||
ISR_NOERRCODE 17
|
||||
ISR_NOERRCODE 18
|
||||
ISR_NOERRCODE 19
|
||||
ISR_NOERRCODE 20
|
||||
ISR_NOERRCODE 21
|
||||
ISR_NOERRCODE 22
|
||||
ISR_NOERRCODE 23
|
||||
ISR_NOERRCODE 24
|
||||
ISR_NOERRCODE 25
|
||||
ISR_NOERRCODE 26
|
||||
ISR_NOERRCODE 27
|
||||
ISR_NOERRCODE 28
|
||||
ISR_NOERRCODE 29
|
||||
ISR_NOERRCODE 30
|
||||
ISR_NOERRCODE 31
|
||||
ISR_NOERRCODE 128
|
||||
ISR_NOERRCODE 177
|
||||
IRQ 0, 32
|
||||
IRQ 1, 33
|
||||
IRQ 2, 34
|
||||
IRQ 3, 35
|
||||
IRQ 4, 36
|
||||
IRQ 5, 37
|
||||
IRQ 6, 38
|
||||
IRQ 7, 39
|
||||
IRQ 8, 40
|
||||
IRQ 9, 41
|
||||
IRQ 10, 42
|
||||
IRQ 11, 43
|
||||
IRQ 12, 44
|
||||
IRQ 13, 45
|
||||
IRQ 14, 46
|
||||
IRQ 15, 47
|
||||
|
||||
; In isr.c
|
||||
extern isr_handler
|
||||
|
||||
; This is our common ISR stub. It saves the processor state, sets
|
||||
; up for kernel mode segments, calls the C-level fault handler,
|
||||
; and finally restores the stack frame.
|
||||
isr_common_stub:
|
||||
|
||||
; TODO
|
||||
|
||||
; In isr.c
|
||||
extern irq_handler
|
||||
|
||||
; This is our common IRQ stub. It saves the processor state, sets
|
||||
; up for kernel mode segments, calls the C-level fault handler,
|
||||
; and finally restores the stack frame.
|
||||
irq_common_stub:
|
||||
|
||||
; TODO
|
||||
|
|
@ -0,0 +1,440 @@
|
|||
/******************************************************************************
|
||||
|
||||
COPYRIGHT(C) JONAS 'SORTIE' TERMANSEN 2011.
|
||||
|
||||
This file is part of Sortix.
|
||||
|
||||
Sortix is free software: you can redistribute it and/or modify it under the
|
||||
terms of the GNU General Public License as published by the Free Software
|
||||
Foundation, either version 3 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
Sortix is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with Sortix. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
x63/interrupt.s
|
||||
Transfers control to interrupt handlers when interrupts happen.
|
||||
|
||||
******************************************************************************/
|
||||
|
||||
.section .text
|
||||
|
||||
.global isr0
|
||||
.type isr0, @function
|
||||
isr0:
|
||||
cli
|
||||
pushq $0 # err_code
|
||||
pushq $0 # int_no
|
||||
jmp interrupt_handler_prepare
|
||||
.global isr1
|
||||
.type isr1, @function
|
||||
isr1:
|
||||
cli
|
||||
pushq $0 # err_code
|
||||
pushq $1 # int_no
|
||||
jmp interrupt_handler_prepare
|
||||
.global isr2
|
||||
.type isr2, @function
|
||||
isr2:
|
||||
cli
|
||||
pushq $0 # err_code
|
||||
pushq $2 # int_no
|
||||
jmp interrupt_handler_prepare
|
||||
.global isr3
|
||||
.type isr3, @function
|
||||
isr3:
|
||||
cli
|
||||
pushq $0 # err_code
|
||||
pushq $3 # int_no
|
||||
jmp interrupt_handler_prepare
|
||||
.global isr4
|
||||
.type isr4, @function
|
||||
isr4:
|
||||
cli
|
||||
pushq $0 # err_code
|
||||
pushq $4 # int_no
|
||||
jmp interrupt_handler_prepare
|
||||
.global isr5
|
||||
.type isr5, @function
|
||||
isr5:
|
||||
cli
|
||||
pushq $0 # err_code
|
||||
pushq $5 # int_no
|
||||
jmp interrupt_handler_prepare
|
||||
.global isr6
|
||||
.type isr6, @function
|
||||
isr6:
|
||||
cli
|
||||
pushq $0 # err_code
|
||||
pushq $6 # int_no
|
||||
jmp interrupt_handler_prepare
|
||||
.global isr7
|
||||
.type isr7, @function
|
||||
isr7:
|
||||
cli
|
||||
pushq $0 # err_code
|
||||
pushq $7 # int_no
|
||||
jmp interrupt_handler_prepare
|
||||
.global isr8
|
||||
.type isr8, @function
|
||||
isr8:
|
||||
cli
|
||||
# pushq $0 # err_code pushed by CPU
|
||||
pushq $8 # int_no
|
||||
jmp interrupt_handler_prepare
|
||||
.global isr9
|
||||
.type isr9, @function
|
||||
isr9:
|
||||
cli
|
||||
pushq $0 # err_code
|
||||
pushq $9 # int_no
|
||||
jmp interrupt_handler_prepare
|
||||
.global isr10
|
||||
.type isr10, @function
|
||||
isr10:
|
||||
cli
|
||||
# pushq $0 # err_code pushed by CPU
|
||||
pushq $10 # int_no
|
||||
jmp interrupt_handler_prepare
|
||||
.global isr11
|
||||
.type isr11, @function
|
||||
isr11:
|
||||
cli
|
||||
# pushq $0 # err_code pushed by CPU
|
||||
pushq $11 # int_no
|
||||
jmp interrupt_handler_prepare
|
||||
.global isr12
|
||||
.type isr12, @function
|
||||
isr12:
|
||||
cli
|
||||
# pushq $0 # err_code pushed by CPU
|
||||
pushq $12 # int_no
|
||||
jmp interrupt_handler_prepare
|
||||
.global isr13
|
||||
.type isr13, @function
|
||||
isr13:
|
||||
cli
|
||||
# pushq $0 # err_code pushed by CPU
|
||||
pushq $13 # int_no
|
||||
jmp interrupt_handler_prepare
|
||||
.global isr14
|
||||
.type isr14, @function
|
||||
isr14:
|
||||
cli
|
||||
# pushq $0 # err_code pushed by CPU
|
||||
pushq $14 # int_no
|
||||
jmp interrupt_handler_prepare
|
||||
.global isr15
|
||||
.type isr15, @function
|
||||
isr15:
|
||||
cli
|
||||
pushq $0 # err_code
|
||||
pushq $15 # int_no
|
||||
jmp interrupt_handler_prepare
|
||||
.global isr16
|
||||
.type isr16, @function
|
||||
isr16:
|
||||
cli
|
||||
pushq $0 # err_code
|
||||
pushq $16 # int_no
|
||||
jmp interrupt_handler_prepare
|
||||
.global isr17
|
||||
.type isr17, @function
|
||||
isr17:
|
||||
cli
|
||||
pushq $0 # err_code
|
||||
pushq $17 # int_no
|
||||
jmp interrupt_handler_prepare
|
||||
.global isr18
|
||||
.type isr18, @function
|
||||
isr18:
|
||||
cli
|
||||
pushq $0 # err_code
|
||||
pushq $18 # int_no
|
||||
jmp interrupt_handler_prepare
|
||||
.global isr19
|
||||
.type isr19, @function
|
||||
isr19:
|
||||
cli
|
||||
pushq $0 # err_code
|
||||
pushq $19 # int_no
|
||||
jmp interrupt_handler_prepare
|
||||
.global isr20
|
||||
.type isr20, @function
|
||||
isr20:
|
||||
cli
|
||||
pushq $0 # err_code
|
||||
pushq $20 # int_no
|
||||
jmp interrupt_handler_prepare
|
||||
.global isr21
|
||||
.type isr21, @function
|
||||
isr21:
|
||||
cli
|
||||
pushq $0 # err_code
|
||||
pushq $21 # int_no
|
||||
jmp interrupt_handler_prepare
|
||||
.global isr22
|
||||
.type isr22, @function
|
||||
isr22:
|
||||
cli
|
||||
pushq $0 # err_code
|
||||
pushq $22 # int_no
|
||||
jmp interrupt_handler_prepare
|
||||
.global isr23
|
||||
.type isr23, @function
|
||||
isr23:
|
||||
cli
|
||||
pushq $0 # err_code
|
||||
pushq $23 # int_no
|
||||
jmp interrupt_handler_prepare
|
||||
.global isr24
|
||||
.type isr24, @function
|
||||
isr24:
|
||||
cli
|
||||
pushq $0 # err_code
|
||||
pushq $24 # int_no
|
||||
jmp interrupt_handler_prepare
|
||||
.global isr25
|
||||
.type isr25, @function
|
||||
isr25:
|
||||
cli
|
||||
pushq $0 # err_code
|
||||
pushq $25 # int_no
|
||||
jmp interrupt_handler_prepare
|
||||
.global isr26
|
||||
.type isr26, @function
|
||||
isr26:
|
||||
cli
|
||||
pushq $0 # err_code
|
||||
pushq $26 # int_no
|
||||
jmp interrupt_handler_prepare
|
||||
.global isr27
|
||||
.type isr27, @function
|
||||
isr27:
|
||||
cli
|
||||
pushq $0 # err_code
|
||||
pushq $27 # int_no
|
||||
jmp interrupt_handler_prepare
|
||||
.global isr28
|
||||
.type isr28, @function
|
||||
isr28:
|
||||
cli
|
||||
pushq $0 # err_code
|
||||
pushq $28 # int_no
|
||||
jmp interrupt_handler_prepare
|
||||
.global isr29
|
||||
.type isr29, @function
|
||||
isr29:
|
||||
cli
|
||||
pushq $0 # err_code
|
||||
pushq $29 # int_no
|
||||
jmp interrupt_handler_prepare
|
||||
.global isr30
|
||||
.type isr30, @function
|
||||
isr30:
|
||||
cli
|
||||
pushq $0 # err_code
|
||||
pushq $30 # int_no
|
||||
jmp interrupt_handler_prepare
|
||||
.global isr31
|
||||
.type isr31, @function
|
||||
isr31:
|
||||
cli
|
||||
pushq $0 # err_code
|
||||
pushq $31 # int_no
|
||||
jmp interrupt_handler_prepare
|
||||
.global isr128
|
||||
.type isr128, @function
|
||||
isr128:
|
||||
cli
|
||||
pushq $0 # err_code
|
||||
pushq $128 # int_no
|
||||
jmp interrupt_handler_prepare
|
||||
.global irq0
|
||||
.type irq0, @function
|
||||
irq0:
|
||||
cli
|
||||
pushq $0 # err_code
|
||||
pushq $32 # int_no
|
||||
jmp interrupt_handler_prepare
|
||||
.global irq1
|
||||
.type irq1, @function
|
||||
irq1:
|
||||
cli
|
||||
pushq $0 # err_code
|
||||
pushq $33 # int_no
|
||||
jmp interrupt_handler_prepare
|
||||
.global irq2
|
||||
.type irq2, @function
|
||||
irq2:
|
||||
cli
|
||||
pushq $0 # err_code
|
||||
pushq $34 # int_no
|
||||
jmp interrupt_handler_prepare
|
||||
.global irq3
|
||||
.type irq3, @function
|
||||
irq3:
|
||||
cli
|
||||
pushq $0 # err_code
|
||||
pushq $35 # int_no
|
||||
jmp interrupt_handler_prepare
|
||||
.global irq4
|
||||
.type irq4, @function
|
||||
irq4:
|
||||
cli
|
||||
pushq $0 # err_code
|
||||
pushq $36 # int_no
|
||||
jmp interrupt_handler_prepare
|
||||
.global irq5
|
||||
.type irq5, @function
|
||||
irq5:
|
||||
cli
|
||||
pushq $0 # err_code
|
||||
pushq $37 # int_no
|
||||
jmp interrupt_handler_prepare
|
||||
.global irq6
|
||||
.type irq6, @function
|
||||
irq6:
|
||||
cli
|
||||
pushq $0 # err_code
|
||||
pushq $38 # int_no
|
||||
jmp interrupt_handler_prepare
|
||||
.global irq7
|
||||
.type irq7, @function
|
||||
irq7:
|
||||
cli
|
||||
pushq $0 # err_code
|
||||
pushq $39 # int_no
|
||||
jmp interrupt_handler_prepare
|
||||
.global irq8
|
||||
.type irq8, @function
|
||||
irq8:
|
||||
cli
|
||||
pushq $0 # err_code
|
||||
pushq $40 # int_no
|
||||
jmp interrupt_handler_prepare
|
||||
.global irq9
|
||||
.type irq9, @function
|
||||
irq9:
|
||||
cli
|
||||
pushq $0 # err_code
|
||||
pushq $41 # int_no
|
||||
jmp interrupt_handler_prepare
|
||||
.global irq10
|
||||
.type irq10, @function
|
||||
irq10:
|
||||
cli
|
||||
pushq $0 # err_code
|
||||
pushq $42 # int_no
|
||||
jmp interrupt_handler_prepare
|
||||
.global irq11
|
||||
.type irq11, @function
|
||||
irq11:
|
||||
cli
|
||||
pushq $0 # err_code
|
||||
pushq $43 # int_no
|
||||
jmp interrupt_handler_prepare
|
||||
.global irq12
|
||||
.type irq12, @function
|
||||
irq12:
|
||||
cli
|
||||
pushq $0 # err_code
|
||||
pushq $44 # int_no
|
||||
jmp interrupt_handler_prepare
|
||||
.global irq13
|
||||
.type irq13, @function
|
||||
irq13:
|
||||
cli
|
||||
pushq $0 # err_code
|
||||
pushq $45 # int_no
|
||||
jmp interrupt_handler_prepare
|
||||
.global irq14
|
||||
.type irq14, @function
|
||||
irq14:
|
||||
cli
|
||||
pushq $0 # err_code
|
||||
pushq $46 # int_no
|
||||
jmp interrupt_handler_prepare
|
||||
.global irq15
|
||||
.type irq15, @function
|
||||
irq15:
|
||||
cli
|
||||
pushq $0 # err_code
|
||||
pushq $47 # int_no
|
||||
jmp interrupt_handler_prepare
|
||||
|
||||
interrupt_handler_prepare:
|
||||
pushq %r15
|
||||
pushq %r14
|
||||
pushq %r13
|
||||
pushq %r12
|
||||
pushq %r11
|
||||
pushq %r10
|
||||
pushq %r9
|
||||
pushq %r8
|
||||
pushq %rax
|
||||
pushq %rcx
|
||||
pushq %rdx
|
||||
pushq %rbx
|
||||
pushq %rsp
|
||||
pushq %rbp
|
||||
pushq %rsi
|
||||
pushq %rdi
|
||||
|
||||
# Push the user-space data segment.
|
||||
movl %ds, %ebp
|
||||
pushq %rbp
|
||||
|
||||
# Load the kernel data segment.
|
||||
movw $0x10, %bp
|
||||
movl %ebp, %ds
|
||||
movl %ebp, %es
|
||||
movl %ebp, %fs
|
||||
movl %ebp, %gs
|
||||
|
||||
# Push CR2 in case of page faults
|
||||
movq %cr2, %rbp
|
||||
pushq %rbp
|
||||
|
||||
# Now call the interrupt handler.
|
||||
movq %rsp, %rdi
|
||||
call interrupt_handler
|
||||
|
||||
# Remove CR2 from the stack.
|
||||
addq $8, %rsp
|
||||
|
||||
# Restore the user-space data segment.
|
||||
popq %rbp
|
||||
movl %ebp, %ds
|
||||
movl %ebp, %es
|
||||
movl %ebp, %fs
|
||||
movl %ebp, %gs
|
||||
|
||||
popq %rdi
|
||||
popq %rsi
|
||||
popq %rbp
|
||||
popq %rsp
|
||||
popq %rbx
|
||||
popq %rdx
|
||||
popq %rcx
|
||||
popq %rax
|
||||
popq %r8
|
||||
popq %r9
|
||||
popq %r10
|
||||
popq %r11
|
||||
popq %r12
|
||||
popq %r13
|
||||
popq %r14
|
||||
popq %r15
|
||||
|
||||
# Remove int_no and err_code
|
||||
addq $16, %rsp
|
||||
|
||||
# Return to where we came from.
|
||||
iretq
|
||||
|
Loading…
Reference in New Issue