Added support for 64-bit interrupts.

This commit is contained in:
Jonas 'Sortie' Termansen 2011-11-30 23:30:14 +01:00
parent f0ec4ffacc
commit f460c4abec
9 changed files with 599 additions and 238 deletions

View File

@ -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;

View File

@ -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);
}
}

View File

@ -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); }
}
}
}

View File

@ -49,6 +49,8 @@ namespace Sortix
typedef void (*Handler)(CPU::InterruptRegisters* Registers);
void RegisterHandler(uint8_t n, Handler handler);
void Init();
}
}

View File

@ -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.

View File

@ -26,7 +26,6 @@
.globl start, _start
.section .text
.text 0x100000
.type _start, @function
.code32

View File

@ -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

View File

@ -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

440
sortix/x64/interrupt.s Normal file
View File

@ -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