From f460c4abece838cca5774df2daf186b89e99e923 Mon Sep 17 00:00:00 2001 From: Jonas 'Sortie' Termansen Date: Wed, 30 Nov 2011 23:30:14 +0100 Subject: [PATCH] Added support for 64-bit interrupts. --- sortix/descriptor_tables.cpp | 137 ++++++----- sortix/descriptor_tables.h | 28 ++- sortix/interrupt.cpp | 51 ++-- sortix/interrupt.h | 2 + sortix/kernel.cpp | 62 ++--- sortix/x64/boot.s | 1 - sortix/x64/gdt.s | 8 +- sortix/x64/interrupt.asm | 108 --------- sortix/x64/interrupt.s | 440 +++++++++++++++++++++++++++++++++++ 9 files changed, 599 insertions(+), 238 deletions(-) delete mode 100644 sortix/x64/interrupt.asm create mode 100644 sortix/x64/interrupt.s diff --git a/sortix/descriptor_tables.cpp b/sortix/descriptor_tables.cpp index ff30d8f8..4004cc9e 100644 --- a/sortix/descriptor_tables.cpp +++ b/sortix/descriptor_tables.cpp @@ -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; diff --git a/sortix/descriptor_tables.h b/sortix/descriptor_tables.h index a52486cd..ae058182 100644 --- a/sortix/descriptor_tables.h +++ b/sortix/descriptor_tables.h @@ -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); } } diff --git a/sortix/interrupt.cpp b/sortix/interrupt.cpp index d7ac6d0c..6f878a99 100644 --- a/sortix/interrupt.cpp +++ b/sortix/interrupt.cpp @@ -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); } } } } diff --git a/sortix/interrupt.h b/sortix/interrupt.h index 013849cf..62ca42ec 100644 --- a/sortix/interrupt.h +++ b/sortix/interrupt.h @@ -49,6 +49,8 @@ namespace Sortix typedef void (*Handler)(CPU::InterruptRegisters* Registers); void RegisterHandler(uint8_t n, Handler handler); + + void Init(); } } diff --git a/sortix/kernel.cpp b/sortix/kernel.cpp index 07049700..09b2d2a3 100644 --- a/sortix/kernel.cpp +++ b/sortix/kernel.cpp @@ -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. diff --git a/sortix/x64/boot.s b/sortix/x64/boot.s index f42d85e4..e0bb1192 100644 --- a/sortix/x64/boot.s +++ b/sortix/x64/boot.s @@ -26,7 +26,6 @@ .globl start, _start .section .text - .text 0x100000 .type _start, @function .code32 diff --git a/sortix/x64/gdt.s b/sortix/x64/gdt.s index 51ee946a..97d3c1e0 100644 --- a/sortix/x64/gdt.s +++ b/sortix/x64/gdt.s @@ -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 diff --git a/sortix/x64/interrupt.asm b/sortix/x64/interrupt.asm deleted file mode 100644 index cbe2d2d1..00000000 --- a/sortix/x64/interrupt.asm +++ /dev/null @@ -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 - diff --git a/sortix/x64/interrupt.s b/sortix/x64/interrupt.s new file mode 100644 index 00000000..9c32c129 --- /dev/null +++ b/sortix/x64/interrupt.s @@ -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 . + + 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 +