Interrupts.cpp 44 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888
  1. /*
  2. * Copyright (c) 2018-2021, Andreas Kling <kling@serenityos.org>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include <AK/Format.h>
  7. #include <AK/RefPtr.h>
  8. #include <AK/Types.h>
  9. #include <Kernel/Arch/Interrupts.h>
  10. #include <Kernel/Arch/x86/common/Interrupts/PIC.h>
  11. #include <Kernel/Interrupts/GenericInterruptHandler.h>
  12. #include <Kernel/Interrupts/SharedIRQHandler.h>
  13. #include <Kernel/Interrupts/SpuriousInterruptHandler.h>
  14. #include <Kernel/Interrupts/UnhandledInterruptHandler.h>
  15. #include <Kernel/Panic.h>
  16. #include <Kernel/PerformanceManager.h>
  17. #include <Kernel/Process.h>
  18. #include <Kernel/Random.h>
  19. #include <Kernel/Scheduler.h>
  20. #include <Kernel/Sections.h>
  21. #include <Kernel/Thread.h>
  22. #include <Kernel/ThreadTracer.h>
  23. #include <LibC/mallocdefs.h>
  24. #include <Kernel/Arch/CPU.h>
  25. #include <Kernel/Arch/PageFault.h>
  26. #include <Kernel/Arch/Processor.h>
  27. #include <Kernel/Arch/RegisterState.h>
  28. #include <Kernel/Arch/SafeMem.h>
  29. #include <Kernel/Arch/x86/ISRStubs.h>
  30. #include <Kernel/Arch/x86/TrapFrame.h>
  31. extern FlatPtr start_of_unmap_after_init;
  32. extern FlatPtr end_of_unmap_after_init;
  33. extern FlatPtr start_of_ro_after_init;
  34. extern FlatPtr end_of_ro_after_init;
  35. extern FlatPtr start_of_kernel_ksyms;
  36. extern FlatPtr end_of_kernel_ksyms;
  37. namespace Kernel {
  38. READONLY_AFTER_INIT static DescriptorTablePointer s_idtr;
  39. READONLY_AFTER_INIT static IDTEntry s_idt[256];
  40. static GenericInterruptHandler* s_interrupt_handler[GENERIC_INTERRUPT_HANDLERS_COUNT];
  41. static GenericInterruptHandler* s_disabled_interrupt_handler[2];
  42. static EntropySource s_entropy_source_interrupts { EntropySource::Static::Interrupts };
  43. // clang-format off
  44. #if ARCH(I386)
  45. #define EH_ENTRY(ec, title) \
  46. extern "C" void title##_asm_entry(); \
  47. extern "C" void title##_handler(TrapFrame*) __attribute__((used)); \
  48. NAKED void title##_asm_entry() { \
  49. asm( \
  50. " pusha\n" \
  51. " pushl %ds\n" \
  52. " pushl %es\n" \
  53. " pushl %fs\n" \
  54. " pushl %gs\n" \
  55. " pushl %ss\n" \
  56. " mov $" __STRINGIFY(GDT_SELECTOR_DATA0) ", %ax\n" \
  57. " mov %ax, %ds\n" \
  58. " mov %ax, %es\n" \
  59. " mov $" __STRINGIFY(GDT_SELECTOR_PROC) ", %ax\n" \
  60. " mov %ax, %gs\n" \
  61. " pushl %esp \n" /* set TrapFrame::regs */ \
  62. " subl $" __STRINGIFY(TRAP_FRAME_SIZE - 4) ", %esp \n" \
  63. " pushl %esp \n" \
  64. " cld\n" \
  65. " call enter_trap_no_irq \n" \
  66. " call " #title "_handler\n" \
  67. " jmp common_trap_exit \n" \
  68. ); \
  69. }
  70. #define EH_ENTRY_NO_CODE(ec, title) \
  71. extern "C" void title##_asm_entry(); \
  72. extern "C" void title##_handler(TrapFrame*) __attribute__((used)); \
  73. NAKED void title##_asm_entry() { \
  74. asm( \
  75. " pushl $0x0\n" \
  76. " pusha\n" \
  77. " pushl %ds\n" \
  78. " pushl %es\n" \
  79. " pushl %fs\n" \
  80. " pushl %gs\n" \
  81. " pushl %ss\n" \
  82. " mov $" __STRINGIFY(GDT_SELECTOR_DATA0) ", %ax\n" \
  83. " mov %ax, %ds\n" \
  84. " mov %ax, %es\n" \
  85. " mov $" __STRINGIFY(GDT_SELECTOR_PROC) ", %ax\n" \
  86. " mov %ax, %gs\n" \
  87. " pushl %esp \n" /* set TrapFrame::regs */ \
  88. " subl $" __STRINGIFY(TRAP_FRAME_SIZE - 4) ", %esp \n" \
  89. " pushl %esp \n" \
  90. " cld\n" \
  91. " call enter_trap_no_irq \n" \
  92. " call " #title "_handler\n" \
  93. " jmp common_trap_exit \n" \
  94. ); \
  95. }
  96. #elif ARCH(X86_64)
  97. #define EH_ENTRY(ec, title) \
  98. extern "C" void title##_asm_entry(); \
  99. extern "C" void title##_handler(TrapFrame*) __attribute__((used)); \
  100. NAKED void title##_asm_entry() { \
  101. asm( \
  102. " pushq %r15\n" \
  103. " pushq %r14\n" \
  104. " pushq %r13\n" \
  105. " pushq %r12\n" \
  106. " pushq %r11\n" \
  107. " pushq %r10\n" \
  108. " pushq %r9\n" \
  109. " pushq %r8\n" \
  110. " pushq %rax\n" \
  111. " pushq %rcx\n" \
  112. " pushq %rdx\n" \
  113. " pushq %rbx\n" \
  114. " pushq %rsp\n" \
  115. " pushq %rbp\n" \
  116. " pushq %rsi\n" \
  117. " pushq %rdi\n" \
  118. " pushq %rsp \n" /* set TrapFrame::regs */ \
  119. " subq $" __STRINGIFY(TRAP_FRAME_SIZE - 8) ", %rsp \n" \
  120. " subq $0x8, %rsp\n" /* align stack */ \
  121. " lea 0x8(%rsp), %rdi \n" \
  122. " cld\n" \
  123. " call enter_trap_no_irq \n" \
  124. " lea 0x8(%rsp), %rdi \n" \
  125. " call " #title "_handler\n" \
  126. " addq $0x8, %rsp\n" /* undo alignment */ \
  127. " jmp common_trap_exit \n" \
  128. ); \
  129. }
  130. #define EH_ENTRY_NO_CODE(ec, title) \
  131. extern "C" void title##_handler(TrapFrame*) __attribute__((used)); \
  132. extern "C" void title##_asm_entry(); \
  133. NAKED void title##_asm_entry() { \
  134. asm( \
  135. " pushq $0x0\n" \
  136. " pushq %r15\n" \
  137. " pushq %r14\n" \
  138. " pushq %r13\n" \
  139. " pushq %r12\n" \
  140. " pushq %r11\n" \
  141. " pushq %r10\n" \
  142. " pushq %r9\n" \
  143. " pushq %r8\n" \
  144. " pushq %rax\n" \
  145. " pushq %rcx\n" \
  146. " pushq %rdx\n" \
  147. " pushq %rbx\n" \
  148. " pushq %rsp\n" \
  149. " pushq %rbp\n" \
  150. " pushq %rsi\n" \
  151. " pushq %rdi\n" \
  152. " pushq %rsp \n" /* set TrapFrame::regs */ \
  153. " subq $" __STRINGIFY(TRAP_FRAME_SIZE - 8) ", %rsp \n" \
  154. " movq %rsp, %rdi \n" \
  155. " cld\n" \
  156. " call enter_trap_no_irq \n" \
  157. " movq %rsp, %rdi \n" \
  158. " call " #title "_handler\n" \
  159. " jmp common_trap_exit \n" \
  160. ); \
  161. }
  162. #endif
  163. // clang-format on
  164. void dump_registers(RegisterState const& regs)
  165. {
  166. #if ARCH(I386)
  167. u16 ss;
  168. u32 esp;
  169. if (!(regs.cs & 3)) {
  170. ss = regs.ss;
  171. esp = regs.esp;
  172. } else {
  173. ss = regs.userspace_ss;
  174. esp = regs.userspace_esp;
  175. }
  176. #else
  177. u64 rsp;
  178. if (!(regs.cs & 3))
  179. rsp = regs.rsp;
  180. else
  181. rsp = regs.userspace_rsp;
  182. #endif
  183. dbgln("Exception code: {:04x} (isr: {:04x})", regs.exception_code, regs.isr_number);
  184. #if ARCH(I386)
  185. dbgln(" pc={:#04x}:{:p} eflags={:p}", (u16)regs.cs, regs.eip, regs.eflags);
  186. dbgln(" stack={:#04x}:{:p}", ss, esp);
  187. dbgln(" ds={:#04x} es={:#04x} fs={:#04x} gs={:#04x}", (u16)regs.ds, (u16)regs.es, (u16)regs.fs, (u16)regs.gs);
  188. dbgln(" eax={:p} ebx={:p} ecx={:p} edx={:p}", regs.eax, regs.ebx, regs.ecx, regs.edx);
  189. dbgln(" ebp={:p} esp={:p} esi={:p} edi={:p}", regs.ebp, regs.esp, regs.esi, regs.edi);
  190. dbgln(" cr0={:p} cr2={:p} cr3={:p} cr4={:p}", read_cr0(), read_cr2(), read_cr3(), read_cr4());
  191. #else
  192. dbgln(" pc={:#04x}:{:p} rflags={:p}", (u16)regs.cs, regs.rip, regs.rflags);
  193. dbgln(" stack={:p}", rsp);
  194. // FIXME: Add fs_base and gs_base here
  195. dbgln(" rax={:p} rbx={:p} rcx={:p} rdx={:p}", regs.rax, regs.rbx, regs.rcx, regs.rdx);
  196. dbgln(" rbp={:p} rsp={:p} rsi={:p} rdi={:p}", regs.rbp, regs.rsp, regs.rsi, regs.rdi);
  197. dbgln(" r8={:p} r9={:p} r10={:p} r11={:p}", regs.r8, regs.r9, regs.r10, regs.r11);
  198. dbgln(" r12={:p} r13={:p} r14={:p} r15={:p}", regs.r12, regs.r13, regs.r14, regs.r15);
  199. dbgln(" cr0={:p} cr2={:p} cr3={:p} cr4={:p}", read_cr0(), read_cr2(), read_cr3(), read_cr4());
  200. #endif
  201. }
  202. EH_ENTRY_NO_CODE(6, illegal_instruction);
  203. void illegal_instruction_handler(TrapFrame* trap)
  204. {
  205. clac();
  206. handle_crash(*trap->regs, "Illegal instruction", SIGILL);
  207. }
  208. EH_ENTRY_NO_CODE(0, divide_error);
  209. void divide_error_handler(TrapFrame* trap)
  210. {
  211. clac();
  212. handle_crash(*trap->regs, "Divide error", SIGFPE);
  213. }
  214. EH_ENTRY(13, general_protection_fault);
  215. void general_protection_fault_handler(TrapFrame* trap)
  216. {
  217. clac();
  218. handle_crash(*trap->regs, "General protection fault", SIGSEGV);
  219. }
  220. // 7: FPU not available exception
  221. EH_ENTRY_NO_CODE(7, fpu_exception);
  222. void fpu_exception_handler(TrapFrame*)
  223. {
  224. // Just clear the TS flag. We've already restored the FPU state eagerly.
  225. // FIXME: It would be nice if we didn't have to do this at all.
  226. asm volatile("clts");
  227. }
  228. // 14: Page Fault
  229. EH_ENTRY(14, page_fault);
  230. void page_fault_handler(TrapFrame* trap)
  231. {
  232. clac();
  233. // NOTE: Once we've extracted the faulting address from CR2,
  234. // we can re-enable interrupts.
  235. auto fault_address = read_cr2();
  236. sti();
  237. auto& regs = *trap->regs;
  238. if constexpr (PAGE_FAULT_DEBUG) {
  239. u32 fault_page_directory = read_cr3();
  240. dbgln("CPU #{} ring {} {} page fault in PD={:#x}, {}{} {}",
  241. Processor::is_initialized() ? Processor::current_id() : 0,
  242. regs.cs & 3,
  243. regs.exception_code & 1 ? "PV" : "NP",
  244. fault_page_directory,
  245. regs.exception_code & 8 ? "reserved-bit " : "",
  246. regs.exception_code & 2 ? "write" : "read",
  247. VirtualAddress(fault_address));
  248. dump_registers(regs);
  249. }
  250. bool faulted_in_kernel = !(regs.cs & 3);
  251. if (faulted_in_kernel && Processor::current_in_irq()) {
  252. // If we're faulting in an IRQ handler, first check if we failed
  253. // due to safe_memcpy, safe_strnlen, or safe_memset. If we did,
  254. // gracefully continue immediately. Because we're in an IRQ handler
  255. // we can't really try to resolve the page fault in a meaningful
  256. // way, so we need to do this before calling into
  257. // MemoryManager::handle_page_fault, which would just bail and
  258. // request a crash
  259. if (handle_safe_access_fault(regs, fault_address))
  260. return;
  261. }
  262. auto current_thread = Thread::current();
  263. if (current_thread) {
  264. current_thread->set_handling_page_fault(true);
  265. PerformanceManager::add_page_fault_event(*current_thread, regs);
  266. }
  267. ScopeGuard guard = [current_thread] {
  268. if (current_thread)
  269. current_thread->set_handling_page_fault(false);
  270. };
  271. VirtualAddress userspace_sp = VirtualAddress { regs.userspace_sp() };
  272. if (!faulted_in_kernel) {
  273. bool has_valid_stack_pointer = current_thread->process().address_space().with([&](auto& space) {
  274. return MM.validate_user_stack(*space, userspace_sp);
  275. });
  276. if (!has_valid_stack_pointer) {
  277. dbgln("Invalid stack pointer: {}", userspace_sp);
  278. return handle_crash(regs, "Bad stack on page fault", SIGSEGV);
  279. }
  280. }
  281. PageFault fault { regs.exception_code, VirtualAddress { fault_address } };
  282. auto response = MM.handle_page_fault(fault);
  283. if (response == PageFaultResponse::ShouldCrash || response == PageFaultResponse::OutOfMemory) {
  284. if (faulted_in_kernel && handle_safe_access_fault(regs, fault_address)) {
  285. // If this would be a ring0 (kernel) fault and the fault was triggered by
  286. // safe_memcpy, safe_strnlen, or safe_memset then we resume execution at
  287. // the appropriate _fault label rather than crashing
  288. return;
  289. }
  290. if (response != PageFaultResponse::OutOfMemory && current_thread) {
  291. if (current_thread->has_signal_handler(SIGSEGV)) {
  292. current_thread->send_urgent_signal_to_self(SIGSEGV);
  293. return;
  294. }
  295. }
  296. dbgln("Unrecoverable page fault, {}{}{} address {}",
  297. regs.exception_code & PageFaultFlags::ReservedBitViolation ? "reserved bit violation / " : "",
  298. regs.exception_code & PageFaultFlags::InstructionFetch ? "instruction fetch / " : "",
  299. regs.exception_code & PageFaultFlags::Write ? "write to" : "read from",
  300. VirtualAddress(fault_address));
  301. constexpr FlatPtr malloc_scrub_pattern = explode_byte(MALLOC_SCRUB_BYTE);
  302. constexpr FlatPtr free_scrub_pattern = explode_byte(FREE_SCRUB_BYTE);
  303. constexpr FlatPtr kmalloc_scrub_pattern = explode_byte(KMALLOC_SCRUB_BYTE);
  304. constexpr FlatPtr kfree_scrub_pattern = explode_byte(KFREE_SCRUB_BYTE);
  305. if ((fault_address & 0xffff0000) == (malloc_scrub_pattern & 0xffff0000)) {
  306. dbgln("Note: Address {} looks like it may be uninitialized malloc() memory", VirtualAddress(fault_address));
  307. } else if ((fault_address & 0xffff0000) == (free_scrub_pattern & 0xffff0000)) {
  308. dbgln("Note: Address {} looks like it may be recently free()'d memory", VirtualAddress(fault_address));
  309. } else if ((fault_address & 0xffff0000) == (kmalloc_scrub_pattern & 0xffff0000)) {
  310. dbgln("Note: Address {} looks like it may be uninitialized kmalloc() memory", VirtualAddress(fault_address));
  311. } else if ((fault_address & 0xffff0000) == (kfree_scrub_pattern & 0xffff0000)) {
  312. dbgln("Note: Address {} looks like it may be recently kfree()'d memory", VirtualAddress(fault_address));
  313. } else if (fault_address < 4096) {
  314. dbgln("Note: Address {} looks like a possible nullptr dereference", VirtualAddress(fault_address));
  315. } else if constexpr (SANITIZE_PTRS) {
  316. constexpr FlatPtr refptr_scrub_pattern = explode_byte(REFPTR_SCRUB_BYTE);
  317. constexpr FlatPtr nonnullrefptr_scrub_pattern = explode_byte(NONNULLREFPTR_SCRUB_BYTE);
  318. constexpr FlatPtr ownptr_scrub_pattern = explode_byte(OWNPTR_SCRUB_BYTE);
  319. constexpr FlatPtr nonnullownptr_scrub_pattern = explode_byte(NONNULLOWNPTR_SCRUB_BYTE);
  320. constexpr FlatPtr lockrefptr_scrub_pattern = explode_byte(LOCKREFPTR_SCRUB_BYTE);
  321. constexpr FlatPtr nonnulllockrefptr_scrub_pattern = explode_byte(NONNULLLOCKREFPTR_SCRUB_BYTE);
  322. if ((fault_address & 0xffff0000) == (refptr_scrub_pattern & 0xffff0000)) {
  323. dbgln("Note: Address {} looks like it may be a recently destroyed LockRefPtr", VirtualAddress(fault_address));
  324. } else if ((fault_address & 0xffff0000) == (nonnullrefptr_scrub_pattern & 0xffff0000)) {
  325. dbgln("Note: Address {} looks like it may be a recently destroyed NonnullLockRefPtr", VirtualAddress(fault_address));
  326. } else if ((fault_address & 0xffff0000) == (ownptr_scrub_pattern & 0xffff0000)) {
  327. dbgln("Note: Address {} looks like it may be a recently destroyed OwnPtr", VirtualAddress(fault_address));
  328. } else if ((fault_address & 0xffff0000) == (nonnullownptr_scrub_pattern & 0xffff0000)) {
  329. dbgln("Note: Address {} looks like it may be a recently destroyed NonnullOwnPtr", VirtualAddress(fault_address));
  330. } else if ((fault_address & 0xffff0000) == (lockrefptr_scrub_pattern & 0xffff0000)) {
  331. dbgln("Note: Address {} looks like it may be a recently destroyed LockRefPtr", VirtualAddress(fault_address));
  332. } else if ((fault_address & 0xffff0000) == (nonnulllockrefptr_scrub_pattern & 0xffff0000)) {
  333. dbgln("Note: Address {} looks like it may be a recently destroyed NonnullLockRefPtr", VirtualAddress(fault_address));
  334. }
  335. }
  336. if (current_thread) {
  337. auto& current_process = current_thread->process();
  338. if (current_process.is_user_process()) {
  339. auto fault_address_string = KString::formatted("{:p}", fault_address);
  340. auto fault_address_view = fault_address_string.is_error() ? ""sv : fault_address_string.value()->view();
  341. (void)current_process.try_set_coredump_property("fault_address"sv, fault_address_view);
  342. (void)current_process.try_set_coredump_property("fault_type"sv, fault.type() == PageFault::Type::PageNotPresent ? "NotPresent"sv : "ProtectionViolation"sv);
  343. StringView fault_access;
  344. if (fault.is_instruction_fetch())
  345. fault_access = "Execute"sv;
  346. else
  347. fault_access = fault.access() == PageFault::Access::Read ? "Read"sv : "Write"sv;
  348. (void)current_process.try_set_coredump_property("fault_access"sv, fault_access);
  349. }
  350. }
  351. return handle_crash(regs, "Page Fault", SIGSEGV, response == PageFaultResponse::OutOfMemory);
  352. } else if (response == PageFaultResponse::Continue) {
  353. dbgln_if(PAGE_FAULT_DEBUG, "Continuing after resolved page fault");
  354. } else {
  355. VERIFY_NOT_REACHED();
  356. }
  357. }
  358. EH_ENTRY_NO_CODE(1, debug);
  359. void debug_handler(TrapFrame* trap)
  360. {
  361. clac();
  362. auto& regs = *trap->regs;
  363. auto current_thread = Thread::current();
  364. auto& process = current_thread->process();
  365. if ((regs.cs & 3) == 0) {
  366. PANIC("Debug exception in ring 0");
  367. }
  368. constexpr u8 REASON_SINGLESTEP = 14;
  369. auto debug_status = read_dr6();
  370. auto should_trap_mask = (1 << REASON_SINGLESTEP) | 0b1111;
  371. if ((debug_status & should_trap_mask) == 0)
  372. return;
  373. if (auto tracer = process.tracer()) {
  374. tracer->set_regs(regs);
  375. }
  376. current_thread->send_urgent_signal_to_self(SIGTRAP);
  377. write_dr6(debug_status & ~(should_trap_mask));
  378. }
  379. EH_ENTRY_NO_CODE(3, breakpoint);
  380. void breakpoint_handler(TrapFrame* trap)
  381. {
  382. clac();
  383. auto& regs = *trap->regs;
  384. auto current_thread = Thread::current();
  385. auto& process = current_thread->process();
  386. if ((regs.cs & 3) == 0) {
  387. PANIC("Breakpoint trap in ring 0");
  388. }
  389. if (auto tracer = process.tracer()) {
  390. tracer->set_regs(regs);
  391. }
  392. current_thread->send_urgent_signal_to_self(SIGTRAP);
  393. }
  394. #define EH(i, msg) \
  395. static void _exception##i() \
  396. { \
  397. dbgln("{}", msg); \
  398. PANIC("cr0={:08x} cr2={:08x} cr3={:08x} cr4={:08x}", read_cr0(), read_cr2(), read_cr3(), read_cr4()); \
  399. }
  400. EH(2, "Unknown error")
  401. EH(4, "Overflow")
  402. EH(5, "Bounds check")
  403. EH(8, "Double fault")
  404. EH(9, "Coprocessor segment overrun")
  405. EH(10, "Invalid TSS")
  406. EH(11, "Segment not present")
  407. EH(12, "Stack exception")
  408. EH(15, "Unknown error")
  409. EH(16, "Coprocessor error")
  410. extern "C" void pre_init_finished(void) __attribute__((used));
  411. extern "C" void post_init_finished(void) __attribute__((used));
  412. extern "C" void handle_interrupt(TrapFrame*) __attribute__((used));
  413. extern "C" UNMAP_AFTER_INIT void pre_init_finished(void)
  414. {
  415. VERIFY(g_scheduler_lock.is_locked_by_current_processor());
  416. // Because init_finished() will wait on the other APs, we need
  417. // to release the scheduler lock so that the other APs can also get
  418. // to this point
  419. // The target flags will get restored upon leaving the trap
  420. Scheduler::leave_on_first_switch(processor_interrupts_state());
  421. }
  422. extern "C" UNMAP_AFTER_INIT void post_init_finished(void)
  423. {
  424. // We need to re-acquire the scheduler lock before a context switch
  425. // transfers control into the idle loop, which needs the lock held
  426. Scheduler::prepare_for_idle_loop();
  427. }
  428. void handle_interrupt(TrapFrame* trap)
  429. {
  430. clac();
  431. auto& regs = *trap->regs;
  432. GenericInterruptHandler* handler = nullptr;
  433. // Note: we declare interrupt service routine offset 0x20 to 0x2f as
  434. // reserved for when the PIC is disabled, so we can still route spurious
  435. // IRQs to a different interrupt handlers at different location.
  436. if (regs.isr_number >= pic_disabled_vector_base && regs.isr_number <= pic_disabled_vector_end) {
  437. u8 irq = (u8)(regs.isr_number - pic_disabled_vector_base);
  438. if (irq == 7) {
  439. handler = s_disabled_interrupt_handler[0];
  440. } else if (irq == 15) {
  441. handler = s_disabled_interrupt_handler[1];
  442. }
  443. } else {
  444. VERIFY(regs.isr_number >= IRQ_VECTOR_BASE && regs.isr_number <= (IRQ_VECTOR_BASE + GENERIC_INTERRUPT_HANDLERS_COUNT));
  445. u8 irq = (u8)(regs.isr_number - IRQ_VECTOR_BASE);
  446. s_entropy_source_interrupts.add_random_event(irq);
  447. handler = s_interrupt_handler[irq];
  448. }
  449. VERIFY(handler);
  450. handler->increment_invoking_counter();
  451. handler->handle_interrupt(regs);
  452. handler->eoi();
  453. }
  454. DescriptorTablePointer const& get_idtr()
  455. {
  456. return s_idtr;
  457. }
  458. static void unimp_trap()
  459. {
  460. PANIC("Unhandled IRQ");
  461. }
  462. GenericInterruptHandler& get_interrupt_handler(u8 interrupt_number)
  463. {
  464. auto*& handler_slot = s_interrupt_handler[interrupt_number];
  465. VERIFY(handler_slot != nullptr);
  466. return *handler_slot;
  467. }
  468. static void revert_to_unused_handler(u8 interrupt_number)
  469. {
  470. auto handler = new UnhandledInterruptHandler(interrupt_number);
  471. handler->register_interrupt_handler();
  472. }
  473. void register_disabled_interrupt_handler(u8 number, GenericInterruptHandler& handler)
  474. {
  475. if (number == 15) {
  476. s_disabled_interrupt_handler[0] = &handler;
  477. return;
  478. } else if (number == 7) {
  479. s_disabled_interrupt_handler[1] = &handler;
  480. return;
  481. }
  482. VERIFY_NOT_REACHED();
  483. }
  484. void register_generic_interrupt_handler(u8 interrupt_number, GenericInterruptHandler& handler)
  485. {
  486. VERIFY(interrupt_number < GENERIC_INTERRUPT_HANDLERS_COUNT);
  487. auto*& handler_slot = s_interrupt_handler[interrupt_number];
  488. if (handler_slot != nullptr) {
  489. if (handler_slot->type() == HandlerType::UnhandledInterruptHandler) {
  490. if (handler_slot) {
  491. auto* unhandled_handler = static_cast<UnhandledInterruptHandler*>(handler_slot);
  492. unhandled_handler->unregister_interrupt_handler();
  493. delete unhandled_handler;
  494. }
  495. handler_slot = &handler;
  496. return;
  497. }
  498. if (handler_slot->is_shared_handler() && !handler_slot->is_sharing_with_others()) {
  499. VERIFY(handler_slot->type() == HandlerType::SharedIRQHandler);
  500. static_cast<SharedIRQHandler*>(handler_slot)->register_handler(handler);
  501. return;
  502. }
  503. if (!handler_slot->is_shared_handler()) {
  504. if (handler_slot->type() == HandlerType::SpuriousInterruptHandler) {
  505. static_cast<SpuriousInterruptHandler*>(handler_slot)->register_handler(handler);
  506. return;
  507. }
  508. VERIFY(handler_slot->type() == HandlerType::IRQHandler);
  509. auto& previous_handler = *handler_slot;
  510. handler_slot = nullptr;
  511. SharedIRQHandler::initialize(interrupt_number);
  512. VERIFY(handler_slot);
  513. static_cast<SharedIRQHandler*>(handler_slot)->register_handler(previous_handler);
  514. static_cast<SharedIRQHandler*>(handler_slot)->register_handler(handler);
  515. return;
  516. }
  517. VERIFY_NOT_REACHED();
  518. } else {
  519. handler_slot = &handler;
  520. }
  521. }
  522. void unregister_generic_interrupt_handler(u8 interrupt_number, GenericInterruptHandler& handler)
  523. {
  524. auto*& handler_slot = s_interrupt_handler[interrupt_number];
  525. VERIFY(handler_slot != nullptr);
  526. if (handler_slot->type() == HandlerType::UnhandledInterruptHandler) {
  527. dbgln("Trying to unregister unused handler (?)");
  528. return;
  529. }
  530. if (handler_slot->is_shared_handler() && !handler_slot->is_sharing_with_others()) {
  531. VERIFY(handler_slot->type() == HandlerType::SharedIRQHandler);
  532. auto* shared_handler = static_cast<SharedIRQHandler*>(handler_slot);
  533. shared_handler->unregister_handler(handler);
  534. if (!shared_handler->sharing_devices_count()) {
  535. handler_slot = nullptr;
  536. revert_to_unused_handler(interrupt_number);
  537. }
  538. return;
  539. }
  540. if (!handler_slot->is_shared_handler()) {
  541. VERIFY(handler_slot->type() == HandlerType::IRQHandler);
  542. handler_slot = nullptr;
  543. revert_to_unused_handler(interrupt_number);
  544. return;
  545. }
  546. VERIFY_NOT_REACHED();
  547. }
  548. UNMAP_AFTER_INIT void register_interrupt_handler(u8 index, void (*handler)())
  549. {
  550. // FIXME: Is the Gate Type really required to be an Interrupt
  551. // FIXME: What's up with that storage segment 0?
  552. s_idt[index] = IDTEntry((FlatPtr)handler, GDT_SELECTOR_CODE0, IDTEntryType::InterruptGate32, 0, 0);
  553. }
  554. UNMAP_AFTER_INIT void register_user_callable_interrupt_handler(u8 index, void (*handler)())
  555. {
  556. // FIXME: Is the Gate Type really required to be a Trap
  557. // FIXME: What's up with that storage segment 0?
  558. s_idt[index] = IDTEntry((FlatPtr)handler, GDT_SELECTOR_CODE0, IDTEntryType::TrapGate32, 0, 3);
  559. }
  560. UNMAP_AFTER_INIT void flush_idt()
  561. {
  562. asm("lidt %0" ::"m"(s_idtr));
  563. }
  564. UNMAP_AFTER_INIT void initialize_interrupts()
  565. {
  566. s_idtr.address = s_idt;
  567. s_idtr.limit = 256 * sizeof(IDTEntry) - 1;
  568. register_interrupt_handler(0x00, divide_error_asm_entry);
  569. register_user_callable_interrupt_handler(0x01, debug_asm_entry);
  570. register_interrupt_handler(0x02, _exception2);
  571. register_user_callable_interrupt_handler(0x03, breakpoint_asm_entry);
  572. register_interrupt_handler(0x04, _exception4);
  573. register_interrupt_handler(0x05, _exception5);
  574. register_interrupt_handler(0x06, illegal_instruction_asm_entry);
  575. register_interrupt_handler(0x07, fpu_exception_asm_entry);
  576. register_interrupt_handler(0x08, _exception8);
  577. register_interrupt_handler(0x09, _exception9);
  578. register_interrupt_handler(0x0a, _exception10);
  579. register_interrupt_handler(0x0b, _exception11);
  580. register_interrupt_handler(0x0c, _exception12);
  581. register_interrupt_handler(0x0d, general_protection_fault_asm_entry);
  582. register_interrupt_handler(0x0e, page_fault_asm_entry);
  583. register_interrupt_handler(0x0f, _exception15);
  584. register_interrupt_handler(0x10, _exception16);
  585. for (u8 i = 0x11; i < 0x20; i++)
  586. register_interrupt_handler(i, unimp_trap);
  587. dbgln("Initializing unhandled interrupt handlers");
  588. register_interrupt_handler(0x20, interrupt_32_asm_entry);
  589. register_interrupt_handler(0x21, interrupt_33_asm_entry);
  590. register_interrupt_handler(0x22, interrupt_34_asm_entry);
  591. register_interrupt_handler(0x23, interrupt_35_asm_entry);
  592. register_interrupt_handler(0x24, interrupt_36_asm_entry);
  593. register_interrupt_handler(0x25, interrupt_37_asm_entry);
  594. register_interrupt_handler(0x26, interrupt_38_asm_entry);
  595. register_interrupt_handler(0x27, interrupt_39_asm_entry);
  596. register_interrupt_handler(0x28, interrupt_40_asm_entry);
  597. register_interrupt_handler(0x29, interrupt_41_asm_entry);
  598. register_interrupt_handler(0x2a, interrupt_42_asm_entry);
  599. register_interrupt_handler(0x2b, interrupt_43_asm_entry);
  600. register_interrupt_handler(0x2c, interrupt_44_asm_entry);
  601. register_interrupt_handler(0x2d, interrupt_45_asm_entry);
  602. register_interrupt_handler(0x2e, interrupt_46_asm_entry);
  603. register_interrupt_handler(0x2f, interrupt_47_asm_entry);
  604. register_interrupt_handler(0x30, interrupt_48_asm_entry);
  605. register_interrupt_handler(0x31, interrupt_49_asm_entry);
  606. register_interrupt_handler(0x32, interrupt_50_asm_entry);
  607. register_interrupt_handler(0x33, interrupt_51_asm_entry);
  608. register_interrupt_handler(0x34, interrupt_52_asm_entry);
  609. register_interrupt_handler(0x35, interrupt_53_asm_entry);
  610. register_interrupt_handler(0x36, interrupt_54_asm_entry);
  611. register_interrupt_handler(0x37, interrupt_55_asm_entry);
  612. register_interrupt_handler(0x38, interrupt_56_asm_entry);
  613. register_interrupt_handler(0x39, interrupt_57_asm_entry);
  614. register_interrupt_handler(0x3a, interrupt_58_asm_entry);
  615. register_interrupt_handler(0x3b, interrupt_59_asm_entry);
  616. register_interrupt_handler(0x3c, interrupt_60_asm_entry);
  617. register_interrupt_handler(0x3d, interrupt_61_asm_entry);
  618. register_interrupt_handler(0x3e, interrupt_62_asm_entry);
  619. register_interrupt_handler(0x3f, interrupt_63_asm_entry);
  620. register_interrupt_handler(0x40, interrupt_64_asm_entry);
  621. register_interrupt_handler(0x41, interrupt_65_asm_entry);
  622. register_interrupt_handler(0x42, interrupt_66_asm_entry);
  623. register_interrupt_handler(0x43, interrupt_67_asm_entry);
  624. register_interrupt_handler(0x44, interrupt_68_asm_entry);
  625. register_interrupt_handler(0x45, interrupt_69_asm_entry);
  626. register_interrupt_handler(0x46, interrupt_70_asm_entry);
  627. register_interrupt_handler(0x47, interrupt_71_asm_entry);
  628. register_interrupt_handler(0x48, interrupt_72_asm_entry);
  629. register_interrupt_handler(0x49, interrupt_73_asm_entry);
  630. register_interrupt_handler(0x4a, interrupt_74_asm_entry);
  631. register_interrupt_handler(0x4b, interrupt_75_asm_entry);
  632. register_interrupt_handler(0x4c, interrupt_76_asm_entry);
  633. register_interrupt_handler(0x4d, interrupt_77_asm_entry);
  634. register_interrupt_handler(0x4e, interrupt_78_asm_entry);
  635. register_interrupt_handler(0x4f, interrupt_79_asm_entry);
  636. register_interrupt_handler(0x50, interrupt_80_asm_entry);
  637. register_interrupt_handler(0x51, interrupt_81_asm_entry);
  638. register_interrupt_handler(0x52, interrupt_82_asm_entry);
  639. register_interrupt_handler(0x53, interrupt_83_asm_entry);
  640. register_interrupt_handler(0x54, interrupt_84_asm_entry);
  641. register_interrupt_handler(0x55, interrupt_85_asm_entry);
  642. register_interrupt_handler(0x56, interrupt_86_asm_entry);
  643. register_interrupt_handler(0x57, interrupt_87_asm_entry);
  644. register_interrupt_handler(0x58, interrupt_88_asm_entry);
  645. register_interrupt_handler(0x59, interrupt_89_asm_entry);
  646. register_interrupt_handler(0x5a, interrupt_90_asm_entry);
  647. register_interrupt_handler(0x5b, interrupt_91_asm_entry);
  648. register_interrupt_handler(0x5c, interrupt_92_asm_entry);
  649. register_interrupt_handler(0x5d, interrupt_93_asm_entry);
  650. register_interrupt_handler(0x5e, interrupt_94_asm_entry);
  651. register_interrupt_handler(0x5f, interrupt_95_asm_entry);
  652. register_interrupt_handler(0x60, interrupt_96_asm_entry);
  653. register_interrupt_handler(0x61, interrupt_97_asm_entry);
  654. register_interrupt_handler(0x62, interrupt_98_asm_entry);
  655. register_interrupt_handler(0x63, interrupt_99_asm_entry);
  656. register_interrupt_handler(0x64, interrupt_100_asm_entry);
  657. register_interrupt_handler(0x65, interrupt_101_asm_entry);
  658. register_interrupt_handler(0x66, interrupt_102_asm_entry);
  659. register_interrupt_handler(0x67, interrupt_103_asm_entry);
  660. register_interrupt_handler(0x68, interrupt_104_asm_entry);
  661. register_interrupt_handler(0x69, interrupt_105_asm_entry);
  662. register_interrupt_handler(0x6a, interrupt_106_asm_entry);
  663. register_interrupt_handler(0x6b, interrupt_107_asm_entry);
  664. register_interrupt_handler(0x6c, interrupt_108_asm_entry);
  665. register_interrupt_handler(0x6d, interrupt_109_asm_entry);
  666. register_interrupt_handler(0x6e, interrupt_110_asm_entry);
  667. register_interrupt_handler(0x6f, interrupt_111_asm_entry);
  668. register_interrupt_handler(0x70, interrupt_112_asm_entry);
  669. register_interrupt_handler(0x71, interrupt_113_asm_entry);
  670. register_interrupt_handler(0x72, interrupt_114_asm_entry);
  671. register_interrupt_handler(0x73, interrupt_115_asm_entry);
  672. register_interrupt_handler(0x74, interrupt_116_asm_entry);
  673. register_interrupt_handler(0x75, interrupt_117_asm_entry);
  674. register_interrupt_handler(0x76, interrupt_118_asm_entry);
  675. register_interrupt_handler(0x77, interrupt_119_asm_entry);
  676. register_interrupt_handler(0x78, interrupt_120_asm_entry);
  677. register_interrupt_handler(0x79, interrupt_121_asm_entry);
  678. register_interrupt_handler(0x7a, interrupt_122_asm_entry);
  679. register_interrupt_handler(0x7b, interrupt_123_asm_entry);
  680. register_interrupt_handler(0x7c, interrupt_124_asm_entry);
  681. register_interrupt_handler(0x7d, interrupt_125_asm_entry);
  682. register_interrupt_handler(0x7e, interrupt_126_asm_entry);
  683. register_interrupt_handler(0x7f, interrupt_127_asm_entry);
  684. register_interrupt_handler(0x80, interrupt_128_asm_entry);
  685. register_interrupt_handler(0x81, interrupt_129_asm_entry);
  686. register_interrupt_handler(0x82, interrupt_130_asm_entry);
  687. register_interrupt_handler(0x83, interrupt_131_asm_entry);
  688. register_interrupt_handler(0x84, interrupt_132_asm_entry);
  689. register_interrupt_handler(0x85, interrupt_133_asm_entry);
  690. register_interrupt_handler(0x86, interrupt_134_asm_entry);
  691. register_interrupt_handler(0x87, interrupt_135_asm_entry);
  692. register_interrupt_handler(0x88, interrupt_136_asm_entry);
  693. register_interrupt_handler(0x89, interrupt_137_asm_entry);
  694. register_interrupt_handler(0x8a, interrupt_138_asm_entry);
  695. register_interrupt_handler(0x8b, interrupt_139_asm_entry);
  696. register_interrupt_handler(0x8c, interrupt_140_asm_entry);
  697. register_interrupt_handler(0x8d, interrupt_141_asm_entry);
  698. register_interrupt_handler(0x8e, interrupt_142_asm_entry);
  699. register_interrupt_handler(0x8f, interrupt_143_asm_entry);
  700. register_interrupt_handler(0x90, interrupt_144_asm_entry);
  701. register_interrupt_handler(0x91, interrupt_145_asm_entry);
  702. register_interrupt_handler(0x92, interrupt_146_asm_entry);
  703. register_interrupt_handler(0x93, interrupt_147_asm_entry);
  704. register_interrupt_handler(0x94, interrupt_148_asm_entry);
  705. register_interrupt_handler(0x95, interrupt_149_asm_entry);
  706. register_interrupt_handler(0x96, interrupt_150_asm_entry);
  707. register_interrupt_handler(0x97, interrupt_151_asm_entry);
  708. register_interrupt_handler(0x98, interrupt_152_asm_entry);
  709. register_interrupt_handler(0x99, interrupt_153_asm_entry);
  710. register_interrupt_handler(0x9a, interrupt_154_asm_entry);
  711. register_interrupt_handler(0x9b, interrupt_155_asm_entry);
  712. register_interrupt_handler(0x9c, interrupt_156_asm_entry);
  713. register_interrupt_handler(0x9d, interrupt_157_asm_entry);
  714. register_interrupt_handler(0x9e, interrupt_158_asm_entry);
  715. register_interrupt_handler(0x9f, interrupt_159_asm_entry);
  716. register_interrupt_handler(0xa0, interrupt_160_asm_entry);
  717. register_interrupt_handler(0xa1, interrupt_161_asm_entry);
  718. register_interrupt_handler(0xa2, interrupt_162_asm_entry);
  719. register_interrupt_handler(0xa3, interrupt_163_asm_entry);
  720. register_interrupt_handler(0xa4, interrupt_164_asm_entry);
  721. register_interrupt_handler(0xa5, interrupt_165_asm_entry);
  722. register_interrupt_handler(0xa6, interrupt_166_asm_entry);
  723. register_interrupt_handler(0xa7, interrupt_167_asm_entry);
  724. register_interrupt_handler(0xa8, interrupt_168_asm_entry);
  725. register_interrupt_handler(0xa9, interrupt_169_asm_entry);
  726. register_interrupt_handler(0xaa, interrupt_170_asm_entry);
  727. register_interrupt_handler(0xab, interrupt_171_asm_entry);
  728. register_interrupt_handler(0xac, interrupt_172_asm_entry);
  729. register_interrupt_handler(0xad, interrupt_173_asm_entry);
  730. register_interrupt_handler(0xae, interrupt_174_asm_entry);
  731. register_interrupt_handler(0xaf, interrupt_175_asm_entry);
  732. register_interrupt_handler(0xb0, interrupt_176_asm_entry);
  733. register_interrupt_handler(0xb1, interrupt_177_asm_entry);
  734. register_interrupt_handler(0xb2, interrupt_178_asm_entry);
  735. register_interrupt_handler(0xb3, interrupt_179_asm_entry);
  736. register_interrupt_handler(0xb4, interrupt_180_asm_entry);
  737. register_interrupt_handler(0xb5, interrupt_181_asm_entry);
  738. register_interrupt_handler(0xb6, interrupt_182_asm_entry);
  739. register_interrupt_handler(0xb7, interrupt_183_asm_entry);
  740. register_interrupt_handler(0xb8, interrupt_184_asm_entry);
  741. register_interrupt_handler(0xb9, interrupt_185_asm_entry);
  742. register_interrupt_handler(0xba, interrupt_186_asm_entry);
  743. register_interrupt_handler(0xbb, interrupt_187_asm_entry);
  744. register_interrupt_handler(0xbc, interrupt_188_asm_entry);
  745. register_interrupt_handler(0xbd, interrupt_189_asm_entry);
  746. register_interrupt_handler(0xbe, interrupt_190_asm_entry);
  747. register_interrupt_handler(0xbf, interrupt_191_asm_entry);
  748. register_interrupt_handler(0xc0, interrupt_192_asm_entry);
  749. register_interrupt_handler(0xc1, interrupt_193_asm_entry);
  750. register_interrupt_handler(0xc2, interrupt_194_asm_entry);
  751. register_interrupt_handler(0xc3, interrupt_195_asm_entry);
  752. register_interrupt_handler(0xc4, interrupt_196_asm_entry);
  753. register_interrupt_handler(0xc5, interrupt_197_asm_entry);
  754. register_interrupt_handler(0xc6, interrupt_198_asm_entry);
  755. register_interrupt_handler(0xc7, interrupt_199_asm_entry);
  756. register_interrupt_handler(0xc8, interrupt_200_asm_entry);
  757. register_interrupt_handler(0xc9, interrupt_201_asm_entry);
  758. register_interrupt_handler(0xca, interrupt_202_asm_entry);
  759. register_interrupt_handler(0xcb, interrupt_203_asm_entry);
  760. register_interrupt_handler(0xcc, interrupt_204_asm_entry);
  761. register_interrupt_handler(0xcd, interrupt_205_asm_entry);
  762. register_interrupt_handler(0xce, interrupt_206_asm_entry);
  763. register_interrupt_handler(0xcf, interrupt_207_asm_entry);
  764. register_interrupt_handler(0xd0, interrupt_208_asm_entry);
  765. register_interrupt_handler(0xd1, interrupt_209_asm_entry);
  766. register_interrupt_handler(0xd2, interrupt_210_asm_entry);
  767. register_interrupt_handler(0xd3, interrupt_211_asm_entry);
  768. register_interrupt_handler(0xd4, interrupt_212_asm_entry);
  769. register_interrupt_handler(0xd5, interrupt_213_asm_entry);
  770. register_interrupt_handler(0xd6, interrupt_214_asm_entry);
  771. register_interrupt_handler(0xd7, interrupt_215_asm_entry);
  772. register_interrupt_handler(0xd8, interrupt_216_asm_entry);
  773. register_interrupt_handler(0xd9, interrupt_217_asm_entry);
  774. register_interrupt_handler(0xda, interrupt_218_asm_entry);
  775. register_interrupt_handler(0xdb, interrupt_219_asm_entry);
  776. register_interrupt_handler(0xdc, interrupt_220_asm_entry);
  777. register_interrupt_handler(0xdd, interrupt_221_asm_entry);
  778. register_interrupt_handler(0xde, interrupt_222_asm_entry);
  779. register_interrupt_handler(0xdf, interrupt_223_asm_entry);
  780. register_interrupt_handler(0xe0, interrupt_224_asm_entry);
  781. register_interrupt_handler(0xe1, interrupt_225_asm_entry);
  782. register_interrupt_handler(0xe2, interrupt_226_asm_entry);
  783. register_interrupt_handler(0xe3, interrupt_227_asm_entry);
  784. register_interrupt_handler(0xe4, interrupt_228_asm_entry);
  785. register_interrupt_handler(0xe5, interrupt_229_asm_entry);
  786. register_interrupt_handler(0xe6, interrupt_230_asm_entry);
  787. register_interrupt_handler(0xe7, interrupt_231_asm_entry);
  788. register_interrupt_handler(0xe8, interrupt_232_asm_entry);
  789. register_interrupt_handler(0xe9, interrupt_233_asm_entry);
  790. register_interrupt_handler(0xea, interrupt_234_asm_entry);
  791. register_interrupt_handler(0xeb, interrupt_235_asm_entry);
  792. register_interrupt_handler(0xec, interrupt_236_asm_entry);
  793. register_interrupt_handler(0xed, interrupt_237_asm_entry);
  794. register_interrupt_handler(0xee, interrupt_238_asm_entry);
  795. register_interrupt_handler(0xef, interrupt_239_asm_entry);
  796. register_interrupt_handler(0xf0, interrupt_240_asm_entry);
  797. register_interrupt_handler(0xf1, interrupt_241_asm_entry);
  798. register_interrupt_handler(0xf2, interrupt_242_asm_entry);
  799. register_interrupt_handler(0xf3, interrupt_243_asm_entry);
  800. register_interrupt_handler(0xf4, interrupt_244_asm_entry);
  801. register_interrupt_handler(0xf5, interrupt_245_asm_entry);
  802. register_interrupt_handler(0xf6, interrupt_246_asm_entry);
  803. register_interrupt_handler(0xf7, interrupt_247_asm_entry);
  804. register_interrupt_handler(0xf8, interrupt_248_asm_entry);
  805. register_interrupt_handler(0xf9, interrupt_249_asm_entry);
  806. register_interrupt_handler(0xfa, interrupt_250_asm_entry);
  807. register_interrupt_handler(0xfb, interrupt_251_asm_entry);
  808. register_interrupt_handler(0xfc, interrupt_252_asm_entry);
  809. register_interrupt_handler(0xfd, interrupt_253_asm_entry);
  810. register_interrupt_handler(0xfe, interrupt_254_asm_entry);
  811. register_interrupt_handler(0xff, interrupt_255_asm_entry);
  812. for (u8 i = 0; i < GENERIC_INTERRUPT_HANDLERS_COUNT; ++i) {
  813. auto* handler = new UnhandledInterruptHandler(i);
  814. handler->register_interrupt_handler();
  815. }
  816. flush_idt();
  817. }
  818. }