2019-04-06 15:29:29 +03:00
# include <AK/Types.h>
2018-10-16 12:01:38 +03:00
# include "i386.h"
# include "Assertions.h"
2018-11-01 15:15:46 +03:00
# include "Process.h"
2019-04-03 16:13:07 +03:00
# include <Kernel/VM/MemoryManager.h>
2018-10-22 13:58:29 +03:00
# include "IRQHandler.h"
# include "PIC.h"
2019-01-25 09:52:44 +03:00
# include "Scheduler.h"
2019-04-28 23:05:13 +03:00
# include <Kernel/KSyms.h>
2018-10-16 12:01:38 +03:00
2019-01-15 08:30:19 +03:00
//#define PAGE_FAULT_DEBUG
2018-11-05 16:10:18 +03:00
2019-02-15 14:30:48 +03:00
struct [[gnu::packed]] DescriptorTablePointer {
2019-05-17 19:16:22 +03:00
word limit ;
2018-10-16 12:01:38 +03:00
void * address ;
2019-02-15 14:30:48 +03:00
} ;
2018-10-16 12:01:38 +03:00
static DescriptorTablePointer s_idtr ;
static DescriptorTablePointer s_gdtr ;
2019-05-17 19:25:50 +03:00
static Descriptor s_idt [ 256 ] ;
static Descriptor s_gdt [ 256 ] ;
2018-10-16 12:01:38 +03:00
2019-05-17 19:25:50 +03:00
static IRQHandler * s_irq_handler [ 16 ] ;
2018-10-22 13:58:29 +03:00
2019-03-16 15:19:58 +03:00
static Vector < word > * s_gdt_freelist ;
2018-11-01 18:23:12 +03:00
2019-05-17 19:16:22 +03:00
static word s_gdt_length ;
2018-10-16 12:01:38 +03:00
2018-11-01 18:23:12 +03:00
word gdt_alloc_entry ( )
2018-10-16 12:01:38 +03:00
{
2018-11-01 18:23:12 +03:00
ASSERT ( s_gdt_freelist ) ;
2018-12-21 04:10:45 +03:00
ASSERT ( ! s_gdt_freelist - > is_empty ( ) ) ;
2019-01-20 00:53:05 +03:00
return s_gdt_freelist - > take_last ( ) ;
2018-11-01 18:23:12 +03:00
}
void gdt_free_entry ( word entry )
{
2019-01-14 16:21:51 +03:00
s_gdt_freelist - > append ( entry ) ;
2018-10-16 12:01:38 +03:00
}
2018-11-10 17:15:31 +03:00
extern " C " void handle_irq ( ) ;
extern " C " void asm_irq_entry ( ) ;
2018-10-22 13:58:29 +03:00
asm (
2018-11-10 17:15:31 +03:00
" .globl asm_irq_entry \n "
" asm_irq_entry: \n "
2018-10-22 13:58:29 +03:00
" pusha \n "
" pushw %ds \n "
" pushw %es \n "
" pushw %ss \n "
" pushw %ss \n "
" popw %ds \n "
" popw %es \n "
2018-11-10 17:15:31 +03:00
" call handle_irq \n "
2018-10-22 13:58:29 +03:00
" popw %es \n "
" popw %ds \n "
" popa \n "
" iret \n "
) ;
2018-10-18 00:49:32 +03:00
# define EH_ENTRY(ec) \
2018-11-05 15:48:07 +03:00
extern " C " void exception_ # # ec # # _handler ( RegisterDumpWithExceptionCode & ) ; \
2018-10-18 00:49:32 +03:00
extern " C " void exception_ # # ec # # _entry ( ) ; \
asm ( \
" .globl exception_ " # ec " _entry \n " \
" exception_ " # ec " _entry: \n " \
" pusha \n " \
" pushw %ds \n " \
" pushw %es \n " \
" pushw %fs \n " \
" pushw %gs \n " \
" pushw %ss \n " \
" pushw %ss \n " \
" pushw %ss \n " \
" pushw %ss \n " \
2018-10-23 11:12:50 +03:00
" pushw %ss \n " \
2018-10-18 00:49:32 +03:00
" popw %ds \n " \
" popw %es \n " \
" popw %fs \n " \
" popw %gs \n " \
2018-11-05 15:48:07 +03:00
" mov %esp, %eax \n " \
2018-10-18 00:49:32 +03:00
" call exception_ " # ec " _handler \n " \
" popw %gs \n " \
2018-10-23 11:12:50 +03:00
" popw %gs \n " \
2018-10-18 00:49:32 +03:00
" popw %fs \n " \
" popw %es \n " \
" popw %ds \n " \
" popa \n " \
2018-11-05 15:48:07 +03:00
" add $0x4, %esp \n " \
2018-10-18 00:49:32 +03:00
" iret \n " \
) ;
2018-10-19 12:28:43 +03:00
# define EH_ENTRY_NO_CODE(ec) \
2018-11-05 15:48:07 +03:00
extern " C " void exception_ # # ec # # _handler ( RegisterDump & ) ; \
2018-10-19 12:28:43 +03:00
extern " C " void exception_ # # ec # # _entry ( ) ; \
asm ( \
" .globl exception_ " # ec " _entry \n " \
" exception_ " # ec " _entry: \n " \
" pusha \n " \
" pushw %ds \n " \
" pushw %es \n " \
" pushw %fs \n " \
" pushw %gs \n " \
" pushw %ss \n " \
" pushw %ss \n " \
" pushw %ss \n " \
" pushw %ss \n " \
2018-10-23 11:12:50 +03:00
" pushw %ss \n " \
2018-10-19 12:28:43 +03:00
" popw %ds \n " \
" popw %es \n " \
" popw %fs \n " \
" popw %gs \n " \
2018-11-05 15:48:07 +03:00
" mov %esp, %eax \n " \
2018-10-19 12:28:43 +03:00
" call exception_ " # ec " _handler \n " \
" popw %gs \n " \
2018-10-23 11:12:50 +03:00
" popw %gs \n " \
2018-10-19 12:28:43 +03:00
" popw %fs \n " \
" popw %es \n " \
" popw %ds \n " \
" popa \n " \
" iret \n " \
) ;
2019-02-20 14:28:41 +03:00
template < typename DumpType >
static void dump ( const DumpType & regs )
2018-10-19 12:28:43 +03:00
{
word ss ;
dword esp ;
2019-03-24 00:03:17 +03:00
if ( ! current | | current - > process ( ) . is_ring0 ( ) ) {
2018-10-19 12:28:43 +03:00
ss = regs . ds ;
esp = regs . esp ;
} else {
ss = regs . ss_if_crossRing ;
esp = regs . esp_if_crossRing ;
}
2019-02-20 14:28:41 +03:00
if constexpr ( IsSame < DumpType , RegisterDumpWithExceptionCode > : : value ) {
kprintf ( " exception code: %w \n " , regs . exception_code ) ;
}
2019-03-05 14:50:55 +03:00
kprintf ( " pc=%w:%x ds=%w es=%w fs=%w gs=%w \n " , regs . cs , regs . eip , regs . ds , regs . es , regs . fs , regs . gs ) ;
kprintf ( " stk=%w:%x \n " , ss , esp ) ;
if ( current )
kprintf ( " kstk=%w:%x, base=%x, sigbase=%x \n " , current - > tss ( ) . ss0 , current - > tss ( ) . esp0 , current - > kernel_stack_base ( ) , current - > kernel_stack_for_signal_handler_base ( ) ) ;
2018-10-19 12:28:43 +03:00
kprintf ( " eax=%x ebx=%x ecx=%x edx=%x \n " , regs . eax , regs . ebx , regs . ecx , regs . edx ) ;
kprintf ( " ebp=%x esp=%x esi=%x edi=%x \n " , regs . ebp , esp , regs . esi , regs . edi ) ;
2019-03-24 00:03:17 +03:00
if ( current & & current - > process ( ) . validate_read ( ( void * ) regs . eip , 8 ) ) {
2019-02-20 14:28:41 +03:00
byte * codeptr = ( byte * ) regs . eip ;
kprintf ( " code: %b %b %b %b %b %b %b %b \n " ,
codeptr [ 0 ] ,
codeptr [ 1 ] ,
codeptr [ 2 ] ,
codeptr [ 3 ] ,
codeptr [ 4 ] ,
codeptr [ 5 ] ,
codeptr [ 6 ] ,
codeptr [ 7 ] ) ;
}
}
// 6: Invalid Opcode
EH_ENTRY_NO_CODE ( 6 ) ;
void exception_6_handler ( RegisterDump & regs )
{
2019-03-24 00:03:17 +03:00
if ( ! current ) {
kprintf ( " #UD with !current \n " ) ;
hang ( ) ;
}
kprintf ( " %s invalid opcode: %u(%s) \n " , current - > process ( ) . is_ring0 ( ) ? " Kernel " : " Process " , current - > pid ( ) , current - > process ( ) . name ( ) . characters ( ) ) ;
2019-02-20 14:28:41 +03:00
dump ( regs ) ;
2019-03-24 00:03:17 +03:00
if ( current - > process ( ) . is_ring0 ( ) ) {
2018-10-19 12:28:43 +03:00
kprintf ( " Oh shit, we've crashed in ring 0 :( \n " ) ;
2019-02-15 14:30:48 +03:00
hang ( ) ;
2018-10-19 12:28:43 +03:00
}
2019-02-15 14:30:48 +03:00
hang ( ) ;
2018-10-19 12:28:43 +03:00
2019-03-24 00:03:17 +03:00
current - > process ( ) . crash ( ) ;
2018-10-19 12:28:43 +03:00
}
2019-01-25 09:52:44 +03:00
// 7: FPU not available exception
2019-01-25 07:01:27 +03:00
EH_ENTRY_NO_CODE ( 7 ) ;
void exception_7_handler ( RegisterDump & regs )
{
( void ) regs ;
2019-01-25 09:52:44 +03:00
asm volatile ( " clts " ) ;
2019-03-24 00:03:17 +03:00
if ( g_last_fpu_thread = = current )
2019-01-25 09:52:44 +03:00
return ;
2019-03-24 00:03:17 +03:00
if ( g_last_fpu_thread ) {
2019-03-27 17:27:45 +03:00
asm volatile ( " fxsave %0 " : " =m " ( g_last_fpu_thread - > fpu_state ( ) ) ) ;
2019-01-25 09:52:44 +03:00
} else {
asm volatile ( " fnclex " ) ;
}
2019-03-24 00:03:17 +03:00
g_last_fpu_thread = current ;
2019-01-25 09:52:44 +03:00
if ( current - > has_used_fpu ( ) ) {
2019-03-27 17:27:45 +03:00
asm volatile ( " fxrstor %0 " : : " m " ( current - > fpu_state ( ) ) ) ;
2019-01-25 09:52:44 +03:00
} else {
asm volatile ( " fninit " ) ;
current - > set_has_used_fpu ( true ) ;
}
2019-01-25 07:01:27 +03:00
# ifdef FPU_EXCEPTION_DEBUG
2019-03-24 00:03:17 +03:00
kprintf ( " %s FPU not available exception: %u(%s) \n " , current - > process ( ) . is_ring0 ( ) ? " Kernel " : " Process " , current - > pid ( ) , current - > process ( ) . name ( ) . characters ( ) ) ;
2019-02-20 14:28:41 +03:00
dump ( regs ) ;
2019-01-25 07:01:27 +03:00
# endif
}
2019-02-20 04:39:46 +03:00
// 0: Divide error
EH_ENTRY_NO_CODE ( 0 ) ;
void exception_0_handler ( RegisterDump & regs )
{
2019-03-24 00:03:17 +03:00
kprintf ( " %s DIVIDE ERROR: %u(%s) \n " , current - > process ( ) . is_ring0 ( ) ? " Kernel " : " User " , current - > pid ( ) , current - > process ( ) . name ( ) . characters ( ) ) ;
2019-02-20 04:39:46 +03:00
2019-02-20 14:28:41 +03:00
dump ( regs ) ;
2019-02-20 04:39:46 +03:00
2019-03-24 00:03:17 +03:00
if ( current - > process ( ) . is_ring0 ( ) ) {
2019-02-20 04:39:46 +03:00
kprintf ( " Oh shit, we've crashed in ring 0 :( \n " ) ;
hang ( ) ;
}
2019-03-24 00:03:17 +03:00
current - > process ( ) . crash ( ) ;
2019-02-20 04:39:46 +03:00
}
2018-10-18 14:05:00 +03:00
// 13: General Protection Fault
EH_ENTRY ( 13 ) ;
2018-11-05 15:48:07 +03:00
void exception_13_handler ( RegisterDumpWithExceptionCode & regs )
2018-10-18 00:49:32 +03:00
{
2019-03-24 00:03:17 +03:00
kprintf ( " %s GPF: %u(%s) \n " , current - > process ( ) . is_ring0 ( ) ? " Kernel " : " User " , current - > pid ( ) , current - > process ( ) . name ( ) . characters ( ) ) ;
2018-10-18 15:53:00 +03:00
2019-02-20 14:28:41 +03:00
dump ( regs ) ;
2018-10-18 00:49:32 +03:00
2019-03-24 00:03:17 +03:00
if ( current - > process ( ) . is_ring0 ( ) ) {
2018-10-18 01:12:52 +03:00
kprintf ( " Oh shit, we've crashed in ring 0 :( \n " ) ;
2019-02-15 14:30:48 +03:00
hang ( ) ;
2018-10-18 01:12:52 +03:00
}
2019-03-24 00:03:17 +03:00
current - > process ( ) . crash ( ) ;
2018-10-18 00:49:32 +03:00
}
2018-10-18 14:05:00 +03:00
// 14: Page Fault
EH_ENTRY ( 14 ) ;
2018-11-05 15:48:07 +03:00
void exception_14_handler ( RegisterDumpWithExceptionCode & regs )
2018-10-18 14:05:00 +03:00
{
2018-10-30 17:33:37 +03:00
ASSERT ( current ) ;
2018-10-18 14:05:00 +03:00
dword faultAddress ;
asm ( " movl %%cr2, %%eax " : " =a " ( faultAddress ) ) ;
2018-11-08 23:20:09 +03:00
dword fault_page_directory ;
asm ( " movl %%cr3, %%eax " : " =a " ( fault_page_directory ) ) ;
2019-02-10 13:37:59 +03:00
# ifdef PAGE_FAULT_DEBUG
2018-11-08 23:20:09 +03:00
dbgprintf ( " %s(%u): ring%u %s page fault in PD=%x, %s L%x \n " ,
2019-03-24 00:03:17 +03:00
current - > process ( ) . name ( ) . characters ( ) ,
2018-10-27 01:14:24 +03:00
current - > pid ( ) ,
2018-11-08 14:59:16 +03:00
regs . cs & 3 ,
regs . exception_code & 1 ? " PV " : " NP " ,
2018-11-08 23:20:09 +03:00
fault_page_directory ,
2018-11-05 15:48:07 +03:00
regs . exception_code & 2 ? " write " : " read " ,
2018-10-18 14:05:00 +03:00
faultAddress ) ;
2019-02-10 13:37:59 +03:00
# endif
2018-10-18 14:05:00 +03:00
2019-01-25 02:32:44 +03:00
# ifdef PAGE_FAULT_DEBUG
2019-02-20 14:28:41 +03:00
dump ( regs ) ;
2019-01-25 02:32:44 +03:00
# endif
2018-11-05 15:48:07 +03:00
auto response = MM . handle_page_fault ( PageFault ( regs . exception_code , LinearAddress ( faultAddress ) ) ) ;
2018-10-18 14:05:00 +03:00
if ( response = = PageFaultResponse : : ShouldCrash ) {
2019-03-24 00:59:08 +03:00
kprintf ( " %s(%u:%u) unrecoverable page fault, %s laddr=%p \n " ,
2019-03-24 00:03:17 +03:00
current - > process ( ) . name ( ) . characters ( ) ,
2018-11-08 14:59:16 +03:00
current - > pid ( ) ,
2019-03-24 00:59:08 +03:00
current - > tid ( ) ,
2018-11-08 14:59:16 +03:00
regs . exception_code & 2 ? " write " : " read " ,
faultAddress ) ;
2019-02-20 14:28:41 +03:00
dump ( regs ) ;
2019-03-24 00:03:17 +03:00
current - > process ( ) . crash ( ) ;
2018-10-18 14:05:00 +03:00
} else if ( response = = PageFaultResponse : : Continue ) {
2018-11-05 15:48:07 +03:00
# ifdef PAGE_FAULT_DEBUG
dbgprintf ( " Continuing after resolved page fault \n " ) ;
# endif
2018-10-18 14:05:00 +03:00
} else {
ASSERT_NOT_REACHED ( ) ;
}
}
2018-10-16 12:01:38 +03:00
# define EH(i, msg) \
static void _exception # # i ( ) \
{ \
kprintf ( msg " \n " ) ; \
2018-11-17 02:11:08 +03:00
dword cr0 , cr2 , cr3 , cr4 ; \
2018-10-16 12:01:38 +03:00
asm ( " movl %%cr0, %%eax " : " =a " ( cr0 ) ) ; \
asm ( " movl %%cr2, %%eax " : " =a " ( cr2 ) ) ; \
asm ( " movl %%cr3, %%eax " : " =a " ( cr3 ) ) ; \
asm ( " movl %%cr4, %%eax " : " =a " ( cr4 ) ) ; \
kprintf ( " CR0=%x CR2=%x CR3=%x CR4=%x \n " , cr0 , cr2 , cr3 , cr4 ) ; \
2019-02-15 14:30:48 +03:00
hang ( ) ; \
2018-10-16 12:01:38 +03:00
}
EH ( 1 , " Debug exception " )
EH ( 2 , " Unknown error " )
EH ( 3 , " Breakpoint " )
EH ( 4 , " Overflow " )
EH ( 5 , " Bounds check " )
EH ( 8 , " Double fault " )
EH ( 9 , " Coprocessor segment overrun " )
EH ( 10 , " Invalid TSS " )
EH ( 11 , " Segment not present " )
EH ( 12 , " Stack exception " )
EH ( 15 , " Unknown error " )
EH ( 16 , " Coprocessor error " )
2019-01-31 19:31:23 +03:00
static void write_raw_gdt_entry ( word selector , dword low , dword high )
2018-10-16 12:01:38 +03:00
{
2018-11-17 02:11:08 +03:00
word i = ( selector & 0xfffc ) > > 3 ;
2018-10-16 12:01:38 +03:00
s_gdt [ i ] . low = low ;
s_gdt [ i ] . high = high ;
2019-05-17 19:16:22 +03:00
if ( i > s_gdt_length )
s_gdtr . limit = ( s_gdt_length + 1 ) * 8 - 1 ;
2018-10-16 12:01:38 +03:00
}
2018-12-03 02:39:25 +03:00
void write_gdt_entry ( word selector , Descriptor & descriptor )
2018-10-16 12:01:38 +03:00
{
2019-01-31 19:31:23 +03:00
write_raw_gdt_entry ( selector , descriptor . low , descriptor . high ) ;
2018-10-16 12:01:38 +03:00
}
2018-12-03 02:39:25 +03:00
Descriptor & get_gdt_entry ( word selector )
2018-10-16 12:01:38 +03:00
{
2018-11-17 02:11:08 +03:00
word i = ( selector & 0xfffc ) > > 3 ;
2018-10-16 12:01:38 +03:00
return * ( Descriptor * ) ( & s_gdt [ i ] ) ;
}
2018-12-03 02:39:25 +03:00
void flush_gdt ( )
2018-10-16 12:01:38 +03:00
{
s_gdtr . address = s_gdt ;
2019-05-17 19:16:22 +03:00
s_gdtr . limit = ( s_gdt_length * 8 ) - 1 ;
asm ( " lgdt %0 " : : " m " ( s_gdtr ) : " memory " ) ;
2018-10-16 12:01:38 +03:00
}
void gdt_init ( )
{
2019-05-17 19:16:22 +03:00
s_gdt_length = 5 ;
2018-10-16 12:01:38 +03:00
2019-03-16 15:19:58 +03:00
s_gdt_freelist = new Vector < word > ( ) ;
2019-01-20 00:53:05 +03:00
s_gdt_freelist - > ensure_capacity ( 256 ) ;
2019-05-17 19:16:22 +03:00
for ( size_t i = s_gdt_length ; i < 256 ; + + i )
2019-01-14 16:21:51 +03:00
s_gdt_freelist - > append ( i * 8 ) ;
2018-11-01 18:23:12 +03:00
2019-05-17 19:16:22 +03:00
s_gdt_length = 256 ;
2018-10-16 12:01:38 +03:00
s_gdtr . address = s_gdt ;
2019-05-17 19:16:22 +03:00
s_gdtr . limit = ( s_gdt_length * 8 ) - 1 ;
2018-10-16 12:01:38 +03:00
2019-01-31 19:31:23 +03:00
write_raw_gdt_entry ( 0x0000 , 0x00000000 , 0x00000000 ) ;
write_raw_gdt_entry ( 0x0008 , 0x0000ffff , 0x00cf9a00 ) ;
write_raw_gdt_entry ( 0x0010 , 0x0000ffff , 0x00cf9200 ) ;
write_raw_gdt_entry ( 0x0018 , 0x0000ffff , 0x00cffa00 ) ;
write_raw_gdt_entry ( 0x0020 , 0x0000ffff , 0x00cff200 ) ;
2018-10-16 12:01:38 +03:00
2018-12-03 02:39:25 +03:00
flush_gdt ( ) ;
2019-05-17 19:23:08 +03:00
asm volatile (
" mov %%ax, %%ds \n "
" mov %%ax, %%es \n "
" mov %%ax, %%fs \n "
" mov %%ax, %%gs \n "
" mov %%ax, %%ss \n "
: : " a " ( 0x10 )
: " memory "
) ;
2019-05-17 19:52:29 +03:00
// Make sure CS points to the kernel code descriptor.
asm volatile (
" ljmpl $0x8, $sanity \n "
" sanity: \n "
) ;
2018-10-16 12:01:38 +03:00
}
static void unimp_trap ( )
{
kprintf ( " Unhandled IRQ. " ) ;
2019-02-15 14:30:48 +03:00
hang ( ) ;
2018-10-16 12:01:38 +03:00
}
2018-12-03 02:39:25 +03:00
void register_irq_handler ( byte irq , IRQHandler & handler )
2018-10-22 13:58:29 +03:00
{
2019-01-31 19:31:23 +03:00
ASSERT ( ! s_irq_handler [ irq ] ) ;
s_irq_handler [ irq ] = & handler ;
2018-12-03 02:39:25 +03:00
register_interrupt_handler ( IRQ_VECTOR_BASE + irq , asm_irq_entry ) ;
2018-10-22 13:58:29 +03:00
}
2018-12-03 02:39:25 +03:00
void unregister_irq_handler ( byte irq , IRQHandler & handler )
2018-10-22 13:58:29 +03:00
{
2019-01-31 19:31:23 +03:00
ASSERT ( s_irq_handler [ irq ] = = & handler ) ;
s_irq_handler [ irq ] = nullptr ;
2018-10-22 13:58:29 +03:00
}
2018-12-03 02:39:25 +03:00
void register_interrupt_handler ( byte index , void ( * f ) ( ) )
2018-10-16 12:01:38 +03:00
{
s_idt [ index ] . low = 0x00080000 | LSW ( ( f ) ) ;
2018-11-17 02:11:08 +03:00
s_idt [ index ] . high = ( ( dword ) ( f ) & 0xffff0000 ) | 0x8e00 ;
2018-12-03 02:39:25 +03:00
flush_idt ( ) ;
2018-10-16 12:01:38 +03:00
}
2018-12-03 02:39:25 +03:00
void register_user_callable_interrupt_handler ( byte index , void ( * f ) ( ) )
2018-10-16 12:01:38 +03:00
{
s_idt [ index ] . low = 0x00080000 | LSW ( ( f ) ) ;
2018-11-17 02:11:08 +03:00
s_idt [ index ] . high = ( ( dword ) ( f ) & 0xffff0000 ) | 0xef00 ;
2018-12-03 02:39:25 +03:00
flush_idt ( ) ;
2018-10-16 12:01:38 +03:00
}
2018-12-03 02:39:25 +03:00
void flush_idt ( )
2018-10-16 12:01:38 +03:00
{
asm ( " lidt %0 " : : " m " ( s_idtr ) ) ;
}
/* If an 8259 gets cranky, it'll generate a spurious IRQ7.
* ATM I don ' t have a clear grasp on when / why this happens ,
* so I ignore them and assume it makes no difference .
*/
extern " C " void irq7_handler ( ) ;
asm (
" .globl irq7_handler \n "
" irq7_handler: \n "
" iret \n "
) ;
void idt_init ( )
{
s_idtr . address = s_idt ;
2019-05-17 19:16:22 +03:00
s_idtr . limit = 0x100 * 8 - 1 ;
2018-10-16 12:01:38 +03:00
2018-11-17 02:11:08 +03:00
for ( byte i = 0xff ; i > 0x10 ; - - i )
2018-12-03 02:39:25 +03:00
register_interrupt_handler ( i , unimp_trap ) ;
2019-02-20 04:39:46 +03:00
register_interrupt_handler ( 0x00 , exception_0_entry ) ;
2018-12-03 02:39:25 +03:00
register_interrupt_handler ( 0x01 , _exception1 ) ;
register_interrupt_handler ( 0x02 , _exception2 ) ;
register_interrupt_handler ( 0x03 , _exception3 ) ;
register_interrupt_handler ( 0x04 , _exception4 ) ;
register_interrupt_handler ( 0x05 , _exception5 ) ;
register_interrupt_handler ( 0x06 , exception_6_entry ) ;
2019-01-25 07:01:27 +03:00
register_interrupt_handler ( 0x07 , exception_7_entry ) ;
2018-12-03 02:39:25 +03:00
register_interrupt_handler ( 0x08 , _exception8 ) ;
register_interrupt_handler ( 0x09 , _exception9 ) ;
register_interrupt_handler ( 0x0a , _exception10 ) ;
register_interrupt_handler ( 0x0b , _exception11 ) ;
register_interrupt_handler ( 0x0c , _exception12 ) ;
register_interrupt_handler ( 0x0d , exception_13_entry ) ;
register_interrupt_handler ( 0x0e , exception_14_entry ) ;
register_interrupt_handler ( 0x0f , _exception15 ) ;
register_interrupt_handler ( 0x10 , _exception16 ) ;
register_interrupt_handler ( 0x57 , irq7_handler ) ;
2018-10-16 12:01:38 +03:00
2018-10-22 13:58:29 +03:00
for ( byte i = 0 ; i < 16 ; + + i ) {
2019-01-31 19:31:23 +03:00
s_irq_handler [ i ] = nullptr ;
2018-10-22 13:58:29 +03:00
}
2018-12-03 02:39:25 +03:00
flush_idt ( ) ;
2018-10-16 12:01:38 +03:00
}
2018-11-17 02:11:08 +03:00
void load_task_register ( word selector )
2018-10-16 12:01:38 +03:00
{
asm ( " ltr %0 " : : " r " ( selector ) ) ;
}
2018-10-22 13:58:29 +03:00
2018-11-10 17:15:31 +03:00
void handle_irq ( )
2018-10-22 13:58:29 +03:00
{
2019-01-31 19:31:23 +03:00
word isr = PIC : : get_isr ( ) ;
2018-10-22 13:58:29 +03:00
if ( ! isr ) {
kprintf ( " Spurious IRQ \n " ) ;
return ;
}
2018-11-09 12:03:21 +03:00
byte irq = 0 ;
2018-10-22 13:58:29 +03:00
for ( byte i = 0 ; i < 16 ; + + i ) {
2018-11-10 17:15:31 +03:00
if ( i = = 2 )
continue ;
2018-10-22 13:58:29 +03:00
if ( isr & ( 1 < < i ) ) {
irq = i ;
break ;
}
}
2019-01-31 19:31:23 +03:00
if ( s_irq_handler [ irq ] )
s_irq_handler [ irq ] - > handle_irq ( ) ;
2018-10-22 13:58:29 +03:00
PIC : : eoi ( irq ) ;
}
2018-11-04 15:12:58 +03:00
2019-04-23 22:52:02 +03:00
# ifdef DEBUG
2018-11-04 15:12:58 +03:00
void __assertion_failed ( const char * msg , const char * file , unsigned line , const char * func )
{
asm volatile ( " cli " ) ;
kprintf ( " ASSERTION FAILED: %s \n %s:%u in %s \n " , msg , file , line , func ) ;
2019-05-16 14:41:16 +03:00
dump_backtrace ( ) ;
2018-11-04 15:12:58 +03:00
asm volatile ( " hlt " ) ;
2018-11-09 12:03:21 +03:00
for ( ; ; ) ;
2018-11-04 15:12:58 +03:00
}
2019-04-23 22:52:02 +03:00
# endif
2019-03-27 15:40:00 +03:00
void sse_init ( )
{
asm volatile (
" mov %cr0, %eax \n "
" andl $0xfffffffb, %eax \n "
" orl $0x2, %eax \n "
" mov %eax, %cr0 \n "
" mov %cr4, %eax \n "
" orl $0x600, %eax \n "
" mov %eax, %cr4 \n "
) ;
}