lib KernelShim
fun outb(port : UInt16, value : UInt8)
fun wait()
end
module IDT
IDT_ADDRESS = 0xc0007100_u32
KERNEL_CODE_SEGMENT_SELECTOR = 0x18_u16
INTERRUPT_GATE = 0x8e_u8
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
end
def self.handle_debug_exception
end
def self.handle_non_maskable_exception
end
def self.handle_breakpoint_exception
end
def self.handle_overflow_exception
end
def self.handle_bound_range_exceeded_exception
end
def self.handle_invalid_opcode_exception
end
def self.handle_device_not_available_exception
end
def self.handle_double_fault_exception
end
def self.handle_invalid_tss_exception
end
def self.handle_segment_not_present_exception
end
def self.handle_stack_segment_fault_exception
end
def self.handle_general_protection_fault_exception
end
def self.handle_page_fault_exception
end
def self.handle_x87_floating_point_exception
end
def self.handle_alignment_check_exception
end
def self.handle_machine_check_exception
end
def self.handle_simd_floating_point_exception
end
def self.handle_virtualisation_exception
end
def self.handle_security_exception
end
def self.handle_interrupt_request_0
end
def self.handle_interrupt_request_1
end
def self.handle_interrupt_request_2
end
def self.handle_interrupt_request_3
end
def self.handle_interrupt_request_4
end
def self.handle_interrupt_request_5
end
def self.handle_interrupt_request_6
end
def self.handle_interrupt_request_7
end
def self.handle_interrupt_request_8
end
def self.handle_interrupt_request_9
end
def self.handle_interrupt_request_10
end
def self.handle_interrupt_request_11
end
def self.handle_interrupt_request_12
end
def self.handle_interrupt_request_13
end
def self.handle_interrupt_request_14
end
def self.handle_interrupt_request_15
end
end
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)
KernelShim.wait()
KernelShim.outb(SLAVE_PIC_DATA, 0x02_u8)
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)
KernelShim.wait()
KernelShim.outb(SLAVE_PIC_DATA, 0x00_u8)
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