/* 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