/* Copyright (C) 2008 Emmanuel Varoquaux
This file is part of XOS.
This program 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.
This program 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 this program. If not, see . */
#define _ASM_SOURCE
#include
#include
.text
.globl ignore_it
.type ignore_it,@function
.align 4
ignore_it:
iret
/* Exceptions */
.globl divide_error_it
.type divide_error_it,@function
.align 4
divide_error_it:
pushl $do_divide_error
jmp no_error_code_exception
.globl debug_it
.type debug_it,@function
.align 4
debug_it:
pushl $do_debug
jmp no_error_code_exception
.globl nonmaskable_interrupt_it
.type nonmaskable_interrupt_it,@function
.align 4
nonmaskable_interrupt_it:
pushl $do_nonmaskable_interrupt
jmp no_error_code_exception
.globl breakpoint_it
.type breakpoint_it,@function
.align 4
breakpoint_it:
pushl $do_breakpoint
jmp no_error_code_exception
.globl overflow_it
.type overflow_it,@function
.align 4
overflow_it:
pushl $do_overflow
jmp no_error_code_exception
.globl bounds_check_it
.type bounds_check_it,@function
.align 4
bounds_check_it:
pushl $do_bounds_check
jmp no_error_code_exception
.globl invalid_opcode_it
.type invalid_opcode_it,@function
.align 4
invalid_opcode_it:
pushl $do_invalid_opcode
jmp no_error_code_exception
.globl device_not_available_it
.type device_not_available_it,@function
.align 4
device_not_available_it:
pushl $do_device_not_available
jmp no_error_code_exception
.globl double_fault_it
.type double_fault_it,@function
.align 4
double_fault_it:
pushl $do_double_fault
jmp error_code_exception
.globl coprocessor_segment_overrun_it
.type coprocessor_segment_overrun_it,@function
.align 4
coprocessor_segment_overrun_it:
pushl $do_coprocessor_segment_overrun
jmp error_code_exception
.globl invalid_tss_it
.type invalid_tss_it,@function
.align 4
invalid_tss_it:
pushl $do_invalid_tss
jmp error_code_exception
.globl segment_not_present_it
.type segment_not_present_it,@function
.align 4
segment_not_present_it:
pushl $do_segment_not_present
jmp error_code_exception
.globl stack_segment_fault_it
.type stack_segment_fault_it,@function
.align 4
stack_segment_fault_it:
pushl $do_stack_segment_fault
jmp error_code_exception
.globl general_protection_it
.type general_protection_it,@function
.align 4
general_protection_it:
pushl $do_general_protection
jmp error_code_exception
.globl page_fault_it
.type page_fault_it,@function
.align 4
page_fault_it:
pushl $do_page_fault
jmp error_code_exception
.globl coprocessor_error_it
.type coprocessor_error_it,@function
.align 4
coprocessor_error_it:
pushl $do_coprocessor_error
jmp no_error_code_exception
.globl alignment_check_it
.type alignment_check_it,@function
.align 4
alignment_check_it:
pushl $do_alignment_check
jmp error_code_exception
.globl machine_check_it
.type machine_check_it,@function
.align 4
machine_check_it:
pushl $do_machine_check
jmp no_error_code_exception
no_error_code_exception:
pushl (%esp)
movl $0, 4(%esp) /* pseudo-code d'erreur */
error_code_exception:
/* sauvegarde des registres */
subl $40, %esp
movl %eax, (%esp)
movl 40(%esp), %eax
movl %ebx, 4(%esp)
movl %ecx, 8(%esp)
movl %edx, 12(%esp)
movl %esi, 16(%esp)
movl %edi, 20(%esp)
movl %ebp, 24(%esp)
movw %ds, 28(%esp)
movw %es, 32(%esp)
movw %fs, 36(%esp)
movw %gs, 40(%esp)
movl %esp, %ebp /* base du cadre de pile */
/* chargement des registres de segments de donnees */
movw $KERNEL_DATA_SEL, %dx
movw %dx, %ds
movw %dx, %es
movw %dx, %fs
movw %dx, %gs
/* appel du gestionnaire d'exception */
subl $12, %esp
leal 48(%ebp), %ebx /* instruction interrompue */
movl %ebx, 8(%esp)
movl %ebx, (%esp)
movl 44(%ebp), %ebx /* code d'erreur */
movl %ebx, 4(%esp)
call *%eax
addl $8, %esp
call do_bottom_half_it
addl $4, %esp
/* restauration des registres */
popl %eax
popl %ebx
popl %ecx
popl %edx
popl %esi
popl %edi
popl %ebp
pop %ds
pop %es
pop %fs
pop %gs
/* retour de l'interruption */
addl $4, %esp /* code d'erreur */
iret
/* Interruptions materielles */
.globl timer_it
.type timer_it,@function
.align 4
timer_it:
pushl $do_timer_interrupt
jmp irq_master
.globl keyboard_it
.type keyboard_it,@function
.align 4
keyboard_it:
pushl $do_keyboard_interrupt
jmp irq_master
.globl floppy_it
.type floppy_it,@function
.align 4
floppy_it:
pushl $do_floppy_interrupt
jmp irq_master
irq_master:
/* sauvegarde des registres */
subl $40, %esp
movl %eax, (%esp)
movl 40(%esp), %eax
movl %ebx, 4(%esp)
movl %ecx, 8(%esp)
movl %edx, 12(%esp)
movl %esi, 16(%esp)
movl %edi, 20(%esp)
movl %ebp, 24(%esp)
movw %ds, 28(%esp)
movw %es, 32(%esp)
movw %fs, 36(%esp)
movw %gs, 40(%esp)
movl %esp, %ebp /* base du cadre de pile */
/* chargement des registres de segments de donnees */
movw $KERNEL_DATA_SEL, %dx
movw %dx, %ds
movw %dx, %es
movw %dx, %fs
movw %dx, %gs
/* appel du gestionnaire d'interruption */
pushl %eax /* sauvegarde de eax */
call pic_ack_master
leal 44(%ebp), %eax /* instruction interrompue */
pushl %eax
xchgl %eax, 4(%esp)
call *%eax
addl $4, %esp
call do_bottom_half_it
addl $4, %esp
/* restauration des registres */
popl %eax
popl %ebx
popl %ecx
popl %edx
popl %esi
popl %edi
popl %ebp
pop %ds
pop %es
pop %fs
pop %gs
/* retour de l'interruption */
iret
/* Appels systemes */
.globl syscall_it
.type syscall_it,@function
.align 4
syscall_it:
/* sauvegarde des registres */
subl $44, %esp
movl %eax, (%esp)
movl %ebx, 4(%esp)
movl %ecx, 8(%esp)
movl %edx, 12(%esp)
movl %esi, 16(%esp)
movl %edi, 20(%esp)
movl %ebp, 24(%esp)
movw %ds, 28(%esp)
movw %es, 32(%esp)
movw %fs, 36(%esp)
movw %gs, 40(%esp)
movl %esp, %ebp /* base du cadre de pile */
/* chargement des registres de segments de donnees */
movw $KERNEL_DATA_SEL, %dx
movw %dx, %ds
movw %dx, %es
/* fs, gs restent a leur valeur dans la procedure appelante. */
call_syscall_handler:
/* appel du gestionnaire d'appel systeme */
pushl %ebp /* registres */
leal 44(%ebp), %ebx /* instruction interrompue */
pushl %ebx
pushl 24(%ebp) /* arg6 (%ebp) */
pushl 20(%ebp) /* arg5 (%edi) */
pushl 16(%ebp) /* arg4 (%esi) */
pushl 12(%ebp) /* arg3 (%edx) */
pushl 8(%ebp) /* arg2 (%ecx) */
pushl 4(%ebp) /* arg1 (%ebx) */
testl %eax, %eax /* verification du numero de l'appel systeme */
je 1f /* le numero de l'appel systeme est nul */
cmpl syscall_table_size, %eax
jae 1f /* le numero de l'appel systeme est trop grand */
call *syscall_table(,%eax,4)
jmp 2f
1: call do_invalid_syscall
2: addl $28, %esp
movl %eax, (%esp) /* sauvegarde de eax */
call do_bottom_half_syscall
popl %eax
cmpl $-ERESTARTSYS, %eax
je restart_syscall
/* restauration des registres */
addl $4, %esp
popl %ebx
popl %ecx
popl %edx
popl %esi
popl %edi
popl %ebp
pop %ds
pop %es
pop %fs
pop %gs
/* retour de l'interruption */
iret
restart_syscall:
movl (%ebp), %eax
jmp call_syscall_handler
.section .note.GNU-stack,"",%progbits