2018-12-15 19:13:26 +01:00
/*******************************************************************************/
/* COS2000 - Compatible Operating System - LGPL v3 - Hordé Nicolas */
/* */
# include "interrupts.h"
# include "types.h"
# include "asm.h"
# include "memory.h"
# include "video.h"
# include "gdt.h"
# include "system.h"
# include "debug.h"
# include "process.h"
/******************************************************************************/
/* Déclenché lors de l'appel d'une interruption */
2018-12-19 16:13:47 +01:00
__attribute__ ( ( noreturn ) ) void interruption_handler ( regs * dump )
2018-12-15 19:13:26 +01:00
{
2018-12-19 16:13:47 +01:00
u32 interruption = dump - > eip ;
exception_stack_noerror * caller = ( exception_stack_noerror * ) ( ( u32 * ) dump - > esp + 1 ) ;
bool noerror , user ;
2018-12-26 00:54:19 +01:00
if ( ( caller - > cs & 0xFFF8 ) = = SEL_KERNEL_CODE | | ( caller - > cs & 0xFFF8 ) = = SEL_USER_CODE )
2018-12-19 16:13:47 +01:00
{
noerror = true ;
dump - > eip = caller - > eip ;
dump - > cs = caller - > cs ;
dump - > eflags = caller - > eflags ;
2018-12-26 00:54:19 +01:00
if ( ( dump - > cs & 0xFFF8 ) = = SEL_KERNEL_CODE )
2018-12-19 16:13:47 +01:00
{
dump - > esp = ( u32 ) caller + sizeof ( exception_stack_noerror ) ;
user = false ;
}
else
{
dump - > esp = ( u32 ) ( ( exception_stack_noerror_user * ) caller ) - > esp ;
dump - > ss = ( u32 ) ( ( exception_stack_noerror_user * ) caller ) - > ss ;
user = true ;
}
}
else
{
noerror = false ;
dump - > eip = ( ( exception_stack * ) caller ) - > eip ;
dump - > cs = ( ( exception_stack * ) caller ) - > cs ;
2018-12-26 00:54:19 +01:00
if ( ( dump - > cs & 0xFFF8 ) = = SEL_KERNEL_CODE )
2018-12-19 16:13:47 +01:00
{
dump - > esp = ( u32 ) caller + sizeof ( exception_stack ) ;
user = false ;
}
else
{
dump - > esp = ( u32 ) ( ( exception_stack_user * ) caller ) - > esp ;
dump - > ss = ( u32 ) ( ( exception_stack_user * ) caller ) - > ss ;
user = true ;
}
}
switch ( interruption )
{
case 20 :
show_lightcpu ( dump ) ;
break ;
default :
print ( " Appel d'une interruption \r \n " ) ;
}
2018-12-26 00:54:19 +01:00
if ( ( dump - > cs & 0xFFF8 ) = = SEL_KERNEL_CODE )
2018-12-19 16:13:47 +01:00
{
setESP ( dump ) ;
restcpu_kernel ( ) ;
}
else
{
setESP ( dump ) ;
restcpu_user ( ) ;
iret ( ) ;
}
2018-12-15 19:13:26 +01:00
}
/******************************************************************************/
/* Les expections */
static u8 ex14_errors1 [ ] =
" Supervisory process tried to read a non-present page entry " ;
static u8 ex14_errors2 [ ] =
" Supervisory process tried to read a page and caused a protection fault " ;
static u8 ex14_errors3 [ ] =
" Supervisory process tried to write to a non-present page entry " ;
static u8 ex14_errors4 [ ] =
" Supervisory process tried to write a page and caused a protection fault " ;
static u8 ex14_errors5 [ ] =
" User process tried to read a non-present page entry " ;
static u8 ex14_errors6 [ ] =
" User process tried to read a page and caused a protection fault " ;
static u8 ex14_errors7 [ ] =
" User process tried to write to a non-present page entry " ;
static u8 ex14_errors8 [ ] =
" User process tried to write a page and caused a protection fault " ;
static u8 * ex14_errors [ ] =
{ & ex14_errors1 , & ex14_errors2 , & ex14_errors3 , & ex14_errors4 ,
& ex14_errors5 , & ex14_errors6 , & ex14_errors7 , & ex14_errors8
} ;
2018-12-16 01:50:03 +01:00
__attribute__ ( ( noreturn ) ) void exception_handler ( regs * dump )
2018-12-15 19:13:26 +01:00
{
2018-12-16 01:50:03 +01:00
u32 exception = dump - > eip ;
exception_stack_noerror * caller = ( exception_stack_noerror * ) ( ( u32 * ) dump - > esp + 1 ) ;
bool noerror , user ;
2018-12-26 00:54:19 +01:00
if ( ( caller - > cs & 0xFFF8 ) = = SEL_KERNEL_CODE | | ( caller - > cs & 0xFFF8 ) = = SEL_USER_CODE )
2018-12-15 19:13:26 +01:00
{
2018-12-16 01:50:03 +01:00
noerror = true ;
dump - > eip = caller - > eip ;
dump - > cs = caller - > cs ;
dump - > eflags = caller - > eflags ;
2018-12-26 00:54:19 +01:00
if ( ( dump - > cs & 0xFFF8 ) = = SEL_KERNEL_CODE )
2018-12-16 01:50:03 +01:00
{
dump - > esp = ( u32 ) caller + sizeof ( exception_stack_noerror ) ;
user = false ;
}
else
{
dump - > esp = ( u32 ) ( ( exception_stack_noerror_user * ) caller ) - > esp ;
dump - > ss = ( u32 ) ( ( exception_stack_noerror_user * ) caller ) - > ss ;
user = true ;
}
2018-12-15 19:13:26 +01:00
}
2018-12-16 01:50:03 +01:00
else
2018-12-15 19:13:26 +01:00
{
2018-12-16 01:50:03 +01:00
noerror = false ;
dump - > eip = ( ( exception_stack * ) caller ) - > eip ;
dump - > cs = ( ( exception_stack * ) caller ) - > cs ;
2018-12-26 00:54:19 +01:00
if ( ( dump - > cs & 0xFFF8 ) = = SEL_KERNEL_CODE )
2018-12-16 01:50:03 +01:00
{
dump - > esp = ( u32 ) caller + sizeof ( exception_stack ) ;
user = false ;
}
else
{
dump - > esp = ( u32 ) ( ( exception_stack_user * ) caller ) - > esp ;
dump - > ss = ( u32 ) ( ( exception_stack_user * ) caller ) - > ss ;
user = true ;
}
2018-12-15 19:13:26 +01:00
}
2018-12-16 01:50:03 +01:00
switch ( exception )
2018-12-15 19:13:26 +01:00
{
2018-12-16 01:50:03 +01:00
case 0 :
cpuerror ( " #DE Divide error " , dump , false ) ;
case 1 :
changevc ( 6 ) ;
clearscreen ( ) ;
show_lightcpu ( dump ) ;
printf ( " \r \n \033 [7m[P] \033 [0m PAS A PAS \033 [7m D \033 [0m PAS A PAS DETAILLE \033 [7m C \033 [0m CONTINUER \033 [7m S \033 [0m STOPPER \033 [7m V \033 [0m VOIR \033 [7m S \033 [0m SCINDER " ) ;
sti ( ) ;
u8 ascii = waitascii ( ) ;
cli ( ) ;
if ( ascii = = ' P ' | | ascii = = ' p ' )
setdebugreg ( 0 ,
caller - > eip + disasm ( caller - > eip , NULL , false ) ,
DBG_EXEC ) ;
else if ( ascii = = ' D ' | | ascii = = ' d ' )
setdebugreg ( 0 , 0 , DBG_CLEAR ) ;
else if ( ascii = = ' C ' | | ascii = = ' c ' )
setdebugreg ( 0 , 0 , DBG_CLEAR ) ;
else if ( ascii = = ' S ' | | ascii = = ' s ' )
{
changevc ( 0 ) ;
sti ( ) ;
initselectors ( getinitretry ( ) ) ;
}
changevc ( 0 ) ;
goto endofexception ;
case 2 :
cpuerror ( " NMI Non-maskable hardware interrupt " , dump , false ) ;
case 3 :
cpuerror ( " #BP INT3 instruction " , dump , true ) ;
iret ( ) ;
case 4 :
cpuerror ( " #OF INTO instruction detected overflow " , dump , false ) ;
case 5 :
cpuerror ( " #BR BOUND instruction detected overrange " , dump , false ) ;
case 6 :
cpuerror ( " #UD Invalid instruction opcode " , dump , false ) ;
case 7 :
cpuerror ( " #NM No coprocessor " , dump , false ) ;
case 8 :
cpuerror ( " #DF Double fault " , dump , false ) ;
case 9 :
cpuerror ( " Coprocessor segment overrun " , dump , false ) ;
case 10 :
cpuerror ( " #TS Invalid task state segment (TSS) " , dump , false ) ;
case 11 :
cpuerror ( " #NP Segment not present " , dump , false ) ;
case 12 :
cpuerror ( " #SS Stack fault " , dump , false ) ;
case 13 :
cpuerror ( " #GP General protection fault (GPF) " , dump , false ) ;
case 14 :
if ( dump - > cr2 > = USER_CODE & & dump - > cr2 < USER_STACK )
{
2018-12-19 12:06:05 +01:00
virtual_range_new ( findcurrentprocess ( ) - > pdd ,
2018-12-16 01:50:03 +01:00
( u8 * ) ( dump - > cr2 & 0xFFFFF000 ) ,
PAGESIZE , PAGE_ALL ) ;
}
else
{
printf ( " Page fault - %s at adress %Y cs:eip - %Y:%Y \r \n " ,
ex14_errors [ ( ( exception_stack * ) caller ) - > error_code & 0xF ] , dump - > cr2 ,
dump - > cs , dump - > eip ) ;
cpuerror ( " #PGF Page fault " , dump , false ) ;
}
goto endofexception ;
case 15 :
cpuerror ( " (reserved) " , dump , false ) ;
case 16 :
cpuerror ( " #MF Coprocessor error " , dump , false ) ;
case 17 :
cpuerror ( " #AC Alignment check " , dump , false ) ;
case 18 :
cpuerror ( " #MC Machine check " , dump , false ) ;
2018-12-15 19:13:26 +01:00
}
2018-12-16 01:50:03 +01:00
endofexception :
2018-12-26 00:54:19 +01:00
if ( ( dump - > cs & 0xFFF8 ) = = SEL_KERNEL_CODE )
2018-12-16 01:50:03 +01:00
{
setESP ( dump ) ;
restcpu_kernel ( ) ;
}
else
{
setESP ( dump ) ;
restcpu_user ( ) ;
iret ( ) ;
}
2018-12-15 19:13:26 +01:00
}
/******************************************************************************/
/* Les IRQ par défaut */
__attribute__ ( ( interrupt ) ) void irq0 ( exception_stack_noerror * caller )
2018-12-19 16:13:47 +01:00
{
print ( " irq 0 " ) ;
2018-12-15 19:13:26 +01:00
irqendmaster ( ) ;
}
__attribute__ ( ( interrupt ) ) void irq1 ( exception_stack_noerror * caller )
{
print ( " irq 1 " ) ;
while ( ( inb ( 0x64 ) & 1 ) = = 0 ) ;
inb ( 0x60 ) ;
irqendmaster ( ) ;
}
__attribute__ ( ( interrupt ) ) void irq2 ( exception_stack_noerror * caller )
{ print ( " irq 2 " ) ;
irqendmaster ( ) ;
}
__attribute__ ( ( interrupt ) ) void irq3 ( exception_stack_noerror * caller )
{
print ( " irq 3 " ) ;
irqendmaster ( ) ;
}
__attribute__ ( ( interrupt ) ) void irq4 ( exception_stack_noerror * caller )
{
print ( " irq 4 " ) ;
irqendmaster ( ) ;
}
__attribute__ ( ( interrupt ) ) void irq5 ( exception_stack_noerror * caller )
{
print ( " irq 5 " ) ;
irqendmaster ( ) ;
}
__attribute__ ( ( interrupt ) ) void irq6 ( exception_stack_noerror * caller )
{
print ( " irq 6 " ) ;
irqendmaster ( ) ;
}
__attribute__ ( ( interrupt ) ) void irq7 ( exception_stack_noerror * caller )
{
print ( " irq 7 " ) ;
irqendmaster ( ) ;
}
__attribute__ ( ( interrupt ) ) void irq8 ( exception_stack_noerror * caller )
{
print ( " irq 8 " ) ;
irqendslave ( ) ;
irqendmaster ( ) ;
}
__attribute__ ( ( interrupt ) ) void irq9 ( exception_stack_noerror * caller )
{
print ( " irq 9 " ) ;
irqendslave ( ) ;
irqendmaster ( ) ;
}
__attribute__ ( ( interrupt ) ) void irq10 ( exception_stack_noerror * caller )
{
print ( " irq 10 " ) ;
irqendslave ( ) ;
irqendmaster ( ) ;
}
__attribute__ ( ( interrupt ) ) void irq11 ( exception_stack_noerror * caller )
{
print ( " irq 11 " ) ;
irqendslave ( ) ;
irqendmaster ( ) ;
}
__attribute__ ( ( interrupt ) ) void irq12 ( exception_stack_noerror * caller )
{
print ( " irq 12 " ) ;
while ( ( inb ( 0x64 ) & 1 ) = = 0 ) ;
inb ( 0x60 ) ;
irqendslave ( ) ;
irqendmaster ( ) ;
}
__attribute__ ( ( interrupt ) ) void irq13 ( exception_stack_noerror * caller )
{
print ( " irq 13 " ) ;
irqendslave ( ) ;
irqendmaster ( ) ;
}
__attribute__ ( ( interrupt ) ) void irq14 ( exception_stack_noerror * caller )
{
print ( " irq 14 " ) ;
irqendslave ( ) ;
irqendmaster ( ) ;
}
__attribute__ ( ( interrupt ) ) void irq15 ( exception_stack_noerror * caller )
{
print ( " irq 15 " ) ;
irqendslave ( ) ;
irqendmaster ( ) ;
}