diff options
author | Andreas Baumann <mail@andreasbaumann.cc> | 2017-06-01 09:46:31 +0200 |
---|---|---|
committer | Andreas Baumann <mail@andreasbaumann.cc> | 2017-06-01 09:46:31 +0200 |
commit | 50dcbcbe2a661f55da0037b0a545ff8d2c3ef890 (patch) | |
tree | e0c04c488db0f34815294dff00e1309cf19232a5 | |
parent | 92f72bedbec7c4ebf0271bf3e34fa082973d2652 (diff) | |
download | abaos-50dcbcbe2a661f55da0037b0a545ff8d2c3ef890.tar.gz abaos-50dcbcbe2a661f55da0037b0a545ff8d2c3ef890.tar.bz2 |
added some interrupt handler functions, handling unhandled exceptions with panic,
delegating to sub interrupt handlers from main interrupt handler
-rw-r--r-- | src/interrupts.c | 58 | ||||
-rw-r--r-- | src/interrupts.h | 17 | ||||
-rw-r--r-- | src/kernel.c | 1 |
3 files changed, 62 insertions, 14 deletions
diff --git a/src/interrupts.c b/src/interrupts.c index d4c84ba..c04eb59 100644 --- a/src/interrupts.c +++ b/src/interrupts.c @@ -54,26 +54,34 @@ #define ICW4_BUFFER 0x08 #define ICW4_FULLY_NESTED 0x10 +// must be global: when called via assembly code we loose the context +// of the interrupt handler structure +interrupt_t interrupt; + void interrupts_init( interrupt_t *interrupt ) { memset( interrupt, 0, sizeof( interrupt_t ) ); - for( int i = 0; i < NOF_INTERRUPT_GATES; i++ ) { + for( int i = 0; i < NOF_INTERRUPTS; i++ ) { interrupts_register_interrupt( interrupt, i, GDT_CODE_SEGMENT_SELECTOR, - &interrupts_ignore_request, KERNEL_RING, IDT_TYPE_INTERRUPT_GATE ); + &interrupts_ignore_request, KERNEL_RING, IDT_TYPE_INTERRUPT_GATE, + NULL ); } // divide-by-zero exception 0x00 interrupts_register_interrupt( interrupt, 0x00, GDT_CODE_SEGMENT_SELECTOR, - &interrupts_handle_exception_0x00, KERNEL_RING, IDT_TYPE_INTERRUPT_GATE ); + &interrupts_handle_exception_0x00, KERNEL_RING, IDT_TYPE_INTERRUPT_GATE, + &interrupts_exception_division_by_zero ); // IRQ 0 - PIT - programmable interrupt timer interrupts_register_interrupt( interrupt, IRQ_BASE + 0x00, GDT_CODE_SEGMENT_SELECTOR, - &interrupts_handle_irq_0x00, KERNEL_RING, IDT_TYPE_INTERRUPT_GATE ); + &interrupts_handle_irq_0x00, KERNEL_RING, IDT_TYPE_INTERRUPT_GATE, + &interrupts_interrupt_PIT ); // IRQ 1 - keyboard interrupts_register_interrupt( interrupt, IRQ_BASE + 0x01, GDT_CODE_SEGMENT_SELECTOR, - &interrupts_handle_irq_0x01, KERNEL_RING, IDT_TYPE_INTERRUPT_GATE ); + &interrupts_handle_irq_0x01, KERNEL_RING, IDT_TYPE_INTERRUPT_GATE, + &interrupts_interrupt_keyboard ); port8_init( &interrupt->PIC_master_control, 0x20 ); port8_init( &interrupt->PIC_master_data, 0x21 ); @@ -106,22 +114,52 @@ void interrupts_init( interrupt_t *interrupt ) void interrupts_register_interrupt( interrupt_t *interrupts, uint8_t interrupt_no, uint16_t gdt_code_segment_selector, - void (*handler)( ), uint8_t privilege_level, uint8_t descriptor_type ) + void (*helper_handler)( ), uint8_t privilege_level, uint8_t descriptor_type, + interrupt_handler_t handler ) { interrupt_gate_descriptor_t *descr = &interrupts->descriptor_table[interrupt_no]; - descr->handler_address_low_bits = ( (uint32_t )handler ) & 0xFFFF; - descr->handler_address_high_bits = ( ( (uint32_t )handler ) >> 16 ) & 0xFFFF; + descr->handler_address_low_bits = ( (uint32_t )helper_handler ) & 0xFFFF; + descr->handler_address_high_bits = ( ( (uint32_t )helper_handler ) >> 16 ) & 0xFFFF; descr->gdt_code_segment_selector = gdt_code_segment_selector; descr->access = IDT_PRESENT_BIT | (( privilege_level & 0x3 ) << 5 ) | descriptor_type; descr->reserved = 0; + + interrupts->interrupt_handler[interrupt_no] = handler; +} + +uint32_t interrupts_exception_division_by_zero( uint32_t esp ) +{ + // TODO: caused by kernel code or user land code? or a task we can kill? + // For now, the kernel has no task management, so we panic + kernel_panic( "Division by zero with ESP 0x%X\n", esp ); + + return esp; } +uint32_t interrupts_interrupt_PIT( uint32_t esp ) +{ + puts( "PIT PIT PIT PIT PIT PIT PIT" ); + return esp; +} + +uint32_t interrupts_interrupt_keyboard( uint32_t esp ) +{ + puts( "KBD KBD KBD KBD KBD KBD KBD" ); + return esp; +} + + uint32_t interrupts_handle_interrupt( uint8_t interrupt_no, uint32_t esp ) { + interrupt_handler_t handler = interrupt.interrupt_handler[interrupt_no]; + + if( handler != NULL ) { + uint32_t new_esp = handler( esp ); + return new_esp; + } + kernel_panic( "Unhandled interrupt 0x%X with ESP 0x%X\n", interrupt_no, esp ); - // for now, we are using the same stack for kernel and interrupt - // handlers (n task switching) return esp; } diff --git a/src/interrupts.h b/src/interrupts.h index ec408f7..0b514ea 100644 --- a/src/interrupts.h +++ b/src/interrupts.h @@ -26,7 +26,7 @@ typedef struct interrupt_gate_descriptor_t { #pragma pack() #endif -#define NOF_INTERRUPT_GATES 256 +#define NOF_INTERRUPTS 256 #if defined( __TINYC__ ) #pragma pack(1) @@ -41,9 +41,12 @@ typedef struct { #pragma pack() #endif +typedef uint32_t (*interrupt_handler_t)( uint32_t esp ); + typedef struct { interrupt_descriptor_table_pointer_t idt_pointer; - interrupt_gate_descriptor_t descriptor_table[NOF_INTERRUPT_GATES]; + interrupt_gate_descriptor_t descriptor_table[NOF_INTERRUPTS]; + interrupt_handler_t interrupt_handler[NOF_INTERRUPTS]; port8_t PIC_master_control; port8_t PIC_master_data; // since PC/AT we always have a slave PIC, we don't support the PC/XT architecture @@ -52,16 +55,24 @@ typedef struct { port8_t PIC_slave_data; } interrupt_t; +extern interrupt_t interrupt; + void interrupts_enable( void ); void interrupts_disable( void ); void interrupts_init( interrupt_t *interrupt ); void interrupts_register_interrupt( interrupt_t *interrupt, uint8_t interrupt_no, uint16_t gdt_code_segment_selector, - void (*handler)( ), uint8_t privilege_level, uint8_t descriptor_type ); + void (*helper_handler)( ), uint8_t privilege_level, uint8_t descriptor_type, + interrupt_handler_t handler ); void interrupts_load_idt( interrupt_descriptor_table_pointer_t *idt_pointer ); uint32_t interrupts_handle_interrupt( uint8_t interrupt_no, uint32_t esp ); +uint32_t interrupts_exception_division_by_zero( uint32_t esp ); + +uint32_t interrupts_interrupt_PIT( uint32_t esp ); +uint32_t interrupts_interrupt_keyboard( uint32_t esp ); + void interrupts_ignore_request( ); void interrupts_handle_exception_0x00( ); void interrupts_handle_irq_0x00( ); diff --git a/src/kernel.c b/src/kernel.c index e33d509..ceb1380 100644 --- a/src/kernel.c +++ b/src/kernel.c @@ -32,7 +32,6 @@ void entry( void ) printf( "Kernel code and data is at 0x%X, kernel stack at 0x%X\n", 0x8400, 0x90000 ); puts( "Initializing interrupts" ); - interrupt_t interrupt; interrupts_init( &interrupt ); // exit point in case of kernel panic, do this as soon as |