@@ -0,0 +1,270 @@
+lib KernelShim
+ fun outb(port : UInt16, value : UInt8)
+ fun wait()
+end
+
+module IDT
+ # Constants
+ IDT_ADDRESS = 0xc0007100_u32
+ KERNEL_CODE_SEGMENT_SELECTOR = 0x18_u16
+ INTERRUPT_GATE = 0x8e_u8
+
+ # Structs
+ struct IDTEntry
+ offset_low : UInt16
+ selector : UInt16
+ unused : UInt8
+ type : UInt8
+ offset_high : UInt16
+ end
+
+ struct IDTPointer
+ size : UInt16
+ address : UInt32
+ end
+
+ module Handlers
+ def self.handle_division_by_zero_exception
+ # handler code
+ end
+
+ def self.handle_debug_exception
+ # handler code
+ end
+
+ def self.handle_non_maskable_exception
+ # handler code
+ end
+
+ def self.handle_breakpoint_exception
+ # handler code
+ end
+
+ def self.handle_overflow_exception
+ # handler code
+ end
+
+ def self.handle_bound_range_exceeded_exception
+ # handler code
+ end
+
+ def self.handle_invalid_opcode_exception
+ # handler code
+ end
+
+ def self.handle_device_not_available_exception
+ # handler code
+ end
+
+ def self.handle_double_fault_exception
+ # handler code
+ end
+
+ def self.handle_invalid_tss_exception
+ # handler code
+ end
+
+ def self.handle_segment_not_present_exception
+ # handler code
+ end
+
+ def self.handle_stack_segment_fault_exception
+ # handler code
+ end
+
+ def self.handle_general_protection_fault_exception
+ # handler code
+ end
+
+ def self.handle_page_fault_exception
+ # handler code
+ end
+
+ def self.handle_x87_floating_point_exception
+ # handler code
+ end
+
+ def self.handle_alignment_check_exception
+ # handler code
+ end
+
+ def self.handle_machine_check_exception
+ # handler code
+ end
+
+ def self.handle_simd_floating_point_exception
+ # handler code
+ end
+
+ def self.handle_virtualisation_exception
+ # handler code
+ end
+
+ def self.handle_security_exception
+ # handler code
+ end
+
+ def self.handle_interrupt_request_0
+ # handler code
+ end
+
+ def self.handle_interrupt_request_1
+ # handler code
+ end
+
+ def self.handle_interrupt_request_2
+ # handler code
+ end
+
+ def self.handle_interrupt_request_3
+ # handler code
+ end
+
+ def self.handle_interrupt_request_4
+ # handler code
+ end
+
+ def self.handle_interrupt_request_5
+ # handler code
+ end
+
+ def self.handle_interrupt_request_6
+ # handler code
+ end
+
+ def self.handle_interrupt_request_7
+ # handler code
+ end
+
+ def self.handle_interrupt_request_8
+ # handler code
+ end
+
+ def self.handle_interrupt_request_9
+ # handler code
+ end
+
+ def self.handle_interrupt_request_10
+ # handler code
+ end
+
+ def self.handle_interrupt_request_11
+ # handler code
+ end
+
+ def self.handle_interrupt_request_12
+ # handler code
+ end
+
+ def self.handle_interrupt_request_13
+ # handler code
+ end
+
+ def self.handle_interrupt_request_14
+ # handler code
+ end
+
+ def self.handle_interrupt_request_15
+ # handler code
+ end
+ end
+
+ # Functions
+ def self.remap_pic
+ MASTER_PIC_COMMAND = 0x20_u8
+ MASTER_PIC_DATA = 0x21_u8
+ SLAVE_PIC_COMMAND = 0xa0_u8
+ SLAVE_PIC_DATA = 0xa1_u8
+
+ INIT_SEQUENCE_START = 0x11_u8
+ MASTER_PIC_OFFSET = 0x20_u8
+ SLAVE_PIC_OFFSET = 0x28_u8
+ MODE_8086 = 0x01_u8
+
+ KernelShim.outb(MASTER_PIC_COMMAND, INIT_SEQUENCE_START)
+ KernelShim.wait()
+ KernelShim.outb(SLAVE_PIC_COMMAND, INIT_SEQUENCE_START)
+ KernelShim.wait()
+ KernelShim.outb(MASTER_PIC_DATA, MASTER_PIC_OFFSET)
+ KernelShim.wait()
+ KernelShim.outb(SLAVE_PIC_DATA, SLAVE_PIC_OFFSET)
+ KernelShim.wait()
+ KernelShim.outb(MASTER_PIC_DATA, 0x04_u8) # Tells master there's a slave on IRQ2
+ KernelShim.wait()
+ KernelShim.outb(SLAVE_PIC_DATA, 0x02_u8) # Tells slave its cascade identity
+ KernelShim.wait()
+ KernelShim.outb(MASTER_PIC_DATA, MODE_8086)
+ KernelShim.wait()
+ KernelShim.outb(SLAVE_PIC_DATA, MODE_8086)
+ KernelShim.wait()
+ KernelShim.outb(MASTER_PIC_DATA, 0x00_u8) # Masks all interrupts (enable)
+ KernelShim.wait()
+ KernelShim.outb(SLAVE_PIC_DATA, 0x00_u8) # Masks all interrupts (enable)
+ KernelShim.wait()
+ end
+
+ def self.set_up_idt_entries(idt_entries : IDTEntry*)
+ handlers = [
+ Handlers.handle_division_by_zero_exception,
+ Handlers.handle_debug_exception,
+ Handlers.handle_non_maskable_exception,
+ Handlers.handle_breakpoint_exception,
+ Handlers.handle_overflow_exception,
+ Handlers.handle_bound_range_exceeded_exception,
+ Handlers.handle_invalid_opcode_exception,
+ Handlers.handle_device_not_available_exception,
+ Handlers.handle_double_fault_exception,
+ Handlers.handle_invalid_tss_exception,
+ Handlers.handle_segment_not_present_exception,
+ Handlers.handle_stack_segment_fault_exception,
+ Handlers.handle_general_protection_fault_exception,
+ Handlers.handle_page_fault_exception,
+ Handlers.handle_x87_floating_point_exception,
+ Handlers.handle_alignment_check_exception,
+ Handlers.handle_machine_check_exception,
+ Handlers.handle_simd_floating_point_exception,
+ Handlers.handle_virtualisation_exception,
+ Handlers.handle_security_exception,
+ Handlers.handle_interrupt_request_0,
+ Handlers.handle_interrupt_request_1,
+ Handlers.handle_interrupt_request_2,
+ Handlers.handle_interrupt_request_3,
+ Handlers.handle_interrupt_request_4,
+ Handlers.handle_interrupt_request_5,
+ Handlers.handle_interrupt_request_6,
+ Handlers.handle_interrupt_request_7,
+ Handlers.handle_interrupt_request_8,
+ Handlers.handle_interrupt_request_9,
+ Handlers.handle_interrupt_request_10,
+ Handlers.handle_interrupt_request_11,
+ Handlers.handle_interrupt_request_12,
+ Handlers.handle_interrupt_request_13,
+ Handlers.handle_interrupt_request_14,
+ Handlers.handle_interrupt_request_15,
+ ]
+
+ handlers.each_with_index do |handler, index|
+ idt_entries[index].offset_low = (handler.address & 0x0000ffff).to_u16
+ idt_entries[index].selector = KERNEL_CODE_SEGMENT_SELECTOR
+ idt_entries[index].unused = 0_u8
+ idt_entries[index].type = INTERRUPT_GATE
+ idt_entries[index].offset_high = ((handler.address & 0xffff0000) >> 16).to_u16
+ end
+ end
+
+ def self.load_idt(idt_entries : IDTEntry*)
+ idt_pointer = IDTPointer.new
+ idt_pointer.size = sizeof(IDTEntry) * 256
+ idt_pointer.address = IDT_ADDRESS
+
+ asm "lidt %{idt_pointer}" : : "m"(idt_pointer)
+ asm "sti" ::
+ end
+
+ def self.init
+ remap_pic
+ idt_entries = Pointer(IDTEntry).new(IDT_ADDRESS)
+ set_up_idt_entries(idt_entries)
+ load_idt(idt_entries)
+ end
+end