#include "arch/cpu/interrupts.hpp" #include "kapi/cpu.hpp" #include "arch/cpu/segment_selector.hpp" #include #include namespace arch::cpu { namespace { constexpr auto isr_code_PF = 14; auto handle_page_fault(interrupt_frame * frame) -> void { auto fault_address = std::uintptr_t{}; asm volatile("mov %%cr2, %0" : "=r"(fault_address)); auto const present = (frame->interrupt.error_code & 0x1) != 0; auto const write = (frame->interrupt.error_code & 0x2) != 0; auto const user = (frame->interrupt.error_code & 0x4) != 0; kstd::println(kstd::print_sink::stderr, "[x86_64:MMU] PAGE FAULT!"); kstd::println(kstd::print_sink::stderr, "\tFault address: 0x{:x}", fault_address); kstd::println(kstd::print_sink::stderr, "\tPresent: {}", present); kstd::println(kstd::print_sink::stderr, "\tWrite: {}", write); kstd::println(kstd::print_sink::stderr, "\tUser: {}", user); kstd::println(kstd::print_sink::stderr, "\tRIP: {:#018x}", frame->cpu_saved.rip); kstd::println(kstd::print_sink::stderr, "\tHalting the system now!"); kapi::cpu::halt(); } } // namespace extern "C" { extern std::uintptr_t const isr_stub_table[256]; auto interrupt_dispatch(interrupt_frame * frame) -> void { switch (frame->interrupt.number) { case isr_code_PF: handle_page_fault(frame); break; default: kstd::println(kstd::print_sink::stderr, "[x86_64:SYS] Unhandled interrupt {} received with code {}", frame->interrupt.number, frame->interrupt.error_code); kapi::cpu::halt(); } } } interrupt_descriptor_table::interrupt_descriptor_table() noexcept { for (auto i = 0uz; i < 256; ++i) { m_descriptors[i] = gate_descriptor{ .offset_low = static_cast(isr_stub_table[i] & 0xffff), // NOLINT(readability-magic-numbers) .m_code_segment = segment_selector{0, false, 1}, .interrupt_stack_table_selector = 0, .gate_type = gate_type::interrupt_gate, .descriptor_privilege_level = 0, .present = true, .offset_middle = static_cast((isr_stub_table[i] >> 16) & 0xffff), // NOLINT(readability-magic-numbers) .offset_high = static_cast((isr_stub_table[i] >> 32) & 0xffff'ffff), // NOLINT(readability-magic-numbers) }; } } auto interrupt_descriptor_table::load() const -> void { interrupt_descriptor_table_register{.limit = sizeof(m_descriptors) - 1, .base = m_descriptors.data()}.load(); } auto interrupt_descriptor_table_register::load() const -> void { asm volatile("lidt %0" : : "m"(*this)); } auto interrupt_descriptor_table_register::read() -> interrupt_descriptor_table_register { interrupt_descriptor_table_register idtr{}; asm volatile("sidt %0" : : "m"(idtr)); return idtr; } auto enable_interrupts() -> void { asm volatile("sti"); } auto disable_interrupts() -> void { asm volatile("cli"); } } // namespace arch::cpu