View of xos/kernel/it.S


XOS | Parent Directory | View | Download

/* 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 <http://www.gnu.org/licenses/>. */

#define _ASM_SOURCE
#include <gdt.h>
#include <errno.h>

	.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