#include "interrupts.h" #include "string.h" #include "stdio.h" // TODO: for now the code segment is the first entry in the boot GDT #define GDT_CODE_SEGMENT_SELECTOR 8 // the Present bit in a IDT entry #define IDT_PRESENT_BIT 0x80 // DPL rings #define KERNEL_RING 0 // types of IDT entries #define IDT_TYPE_INTERRUPT_GATE 0xE interrupt_descriptor_table_pointer_t idt_pointer; void interrupts_init( interrupt_t *interrupt ) { memset( interrupt, 0, sizeof( interrupt_t ) ); for( int i = 0; i < NOF_INTERRUPT_GATES; i++ ) { interrupts_register_interrupt( interrupt, i, GDT_CODE_SEGMENT_SELECTOR, &interrupts_ignore_request, KERNEL_RING, IDT_TYPE_INTERRUPT_GATE ); } // divide-by-zero exception 0x00 interrupts_register_interrupt( interrupt, 0x00, GDT_CODE_SEGMENT_SELECTOR, &interrupts_handle_request_0x00, KERNEL_RING, IDT_TYPE_INTERRUPT_GATE ); idt_pointer.size = 256 * sizeof( interrupt_gate_descriptor_t ) - 1; idt_pointer.base = (uint32_t)interrupt->descriptor_table; printf( "IDT pointer at 0x%X\n", &idt_pointer ); interrupts_load_idt( &idt_pointer ); } 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 ) { 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->gdt_code_segment_selector = gdt_code_segment_selector; descr->access = IDT_PRESENT_BIT | (( privilege_level & 0x3 ) << 5 ) | descriptor_type; descr->reserved = 0; } uint32_t interrupts_handle_interrupt( uint8_t interrupt_no, uint32_t esp ) { printf( "interrupt 0x%X with ESP 0x%X", interrupt_no, esp ); // for now, we are using the same stack for kernel and interrupt // handlers (n task switching) return esp; }