Interrupts.cpp 36 KB

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