CPU.cpp 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846
  1. /*
  2. * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
  3. * All rights reserved.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions are met:
  7. *
  8. * 1. Redistributions of source code must retain the above copyright notice, this
  9. * list of conditions and the following disclaimer.
  10. *
  11. * 2. Redistributions in binary form must reproduce the above copyright notice,
  12. * this list of conditions and the following disclaimer in the documentation
  13. * and/or other materials provided with the distribution.
  14. *
  15. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  16. * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  17. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  18. * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
  19. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  20. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  21. * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  22. * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  23. * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  24. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  25. */
  26. #include <AK/Assertions.h>
  27. #include <AK/String.h>
  28. #include <AK/Types.h>
  29. #include <Kernel/Arch/i386/CPU.h>
  30. #include <Kernel/Arch/i386/ISRStubs.h>
  31. #include <Kernel/Interrupts/APIC.h>
  32. #include <Kernel/Interrupts/GenericInterruptHandler.h>
  33. #include <Kernel/Interrupts/IRQHandler.h>
  34. #include <Kernel/Interrupts/InterruptManagement.h>
  35. #include <Kernel/Interrupts/SharedIRQHandler.h>
  36. #include <Kernel/Interrupts/SpuriousInterruptHandler.h>
  37. #include <Kernel/Interrupts/UnhandledInterruptHandler.h>
  38. #include <Kernel/KSyms.h>
  39. #include <Kernel/Process.h>
  40. #include <Kernel/VM/MemoryManager.h>
  41. #include <LibBareMetal/IO.h>
  42. #include <LibC/mallocdefs.h>
  43. //#define PAGE_FAULT_DEBUG
  44. namespace Kernel {
  45. struct [[gnu::packed]] DescriptorTablePointer
  46. {
  47. u16 limit;
  48. void* address;
  49. };
  50. static DescriptorTablePointer s_idtr;
  51. static DescriptorTablePointer s_gdtr;
  52. static Descriptor s_idt[256];
  53. static Descriptor s_gdt[256];
  54. static GenericInterruptHandler* s_interrupt_handler[GENERIC_INTERRUPT_HANDLERS_COUNT];
  55. static Vector<u16>* s_gdt_freelist;
  56. static u16 s_gdt_length;
  57. u16 gdt_alloc_entry()
  58. {
  59. ASSERT(s_gdt_freelist);
  60. ASSERT(!s_gdt_freelist->is_empty());
  61. return s_gdt_freelist->take_last();
  62. }
  63. void gdt_free_entry(u16 entry)
  64. {
  65. s_gdt_freelist->append(entry);
  66. }
  67. extern "C" void handle_interrupt(RegisterState);
  68. #define EH_ENTRY(ec, title) \
  69. extern "C" void title##_asm_entry(); \
  70. extern "C" void title##_handler(RegisterState); \
  71. asm( \
  72. ".globl " #title "_asm_entry\n" \
  73. "" #title "_asm_entry: \n" \
  74. " pusha\n" \
  75. " pushl %ds\n" \
  76. " pushl %es\n" \
  77. " pushl %fs\n" \
  78. " pushl %gs\n" \
  79. " pushl %ss\n" \
  80. " mov $0x10, %ax\n" \
  81. " mov %ax, %ds\n" \
  82. " mov %ax, %es\n" \
  83. " cld\n" \
  84. " call " #title "_handler\n" \
  85. " add $0x4, %esp \n" \
  86. " popl %gs\n" \
  87. " popl %fs\n" \
  88. " popl %es\n" \
  89. " popl %ds\n" \
  90. " popa\n" \
  91. " add $0x4, %esp\n" \
  92. " iret\n");
  93. #define EH_ENTRY_NO_CODE(ec, title) \
  94. extern "C" void title##_handler(RegisterState); \
  95. extern "C" void title##_asm_entry(); \
  96. asm( \
  97. ".globl " #title "_asm_entry\n" \
  98. "" #title "_asm_entry: \n" \
  99. " pushl $0x0\n" \
  100. " pusha\n" \
  101. " pushl %ds\n" \
  102. " pushl %es\n" \
  103. " pushl %fs\n" \
  104. " pushl %gs\n" \
  105. " pushl %ss\n" \
  106. " mov $0x10, %ax\n" \
  107. " mov %ax, %ds\n" \
  108. " mov %ax, %es\n" \
  109. " cld\n" \
  110. " call " #title "_handler\n" \
  111. " add $0x4, %esp\n" \
  112. " popl %gs\n" \
  113. " popl %fs\n" \
  114. " popl %es\n" \
  115. " popl %ds\n" \
  116. " popa\n" \
  117. " add $0x4, %esp\n" \
  118. " iret\n");
  119. static void dump(const RegisterState& regs)
  120. {
  121. u16 ss;
  122. u32 esp;
  123. if (!Process::current || Process::current->is_ring0()) {
  124. ss = regs.ss;
  125. esp = regs.esp;
  126. } else {
  127. ss = regs.userspace_ss;
  128. esp = regs.userspace_esp;
  129. }
  130. klog() << "exception code: " << String::format("%04x", regs.exception_code) << " (isr: " << String::format("%04x", regs.isr_number);
  131. klog() << " pc=" << String::format("%04x", (u16)regs.cs) << ":" << String::format("%08x", regs.eip) << " flags=" << String::format("%04x", (u16)regs.eflags);
  132. klog() << " stk=" << String::format("%04x", ss) << ":" << String::format("%08x", esp);
  133. klog() << " ds=" << String::format("%04x", (u16)regs.ds) << " es=" << String::format("%04x", (u16)regs.es) << " fs=" << String::format("%04x", (u16)regs.fs) << " gs=" << String::format("%04x", (u16)regs.gs);
  134. klog() << "eax=" << String::format("%08x", regs.eax) << " ebx=" << String::format("%08x", regs.ebx) << " ecx=" << String::format("%08x", regs.ecx) << " edx=" << String::format("%08x", regs.edx);
  135. klog() << "ebp=" << String::format("%08x", regs.ebp) << " esp=" << String::format("%08x", regs.esp) << " esi=" << String::format("%08x", regs.esi) << " edi=" << String::format("%08x", regs.edi);
  136. u32 cr0;
  137. asm("movl %%cr0, %%eax"
  138. : "=a"(cr0));
  139. u32 cr2;
  140. asm("movl %%cr2, %%eax"
  141. : "=a"(cr2));
  142. u32 cr3 = read_cr3();
  143. u32 cr4;
  144. asm("movl %%cr4, %%eax"
  145. : "=a"(cr4));
  146. klog() << "cr0=" << String::format("%08x", cr0) << " cr2=" << String::format("%08x", cr2) << " cr3=" << String::format("%08x", cr3) << " cr4=" << String::format("%08x", cr4);
  147. if (Process::current && Process::current->validate_read((void*)regs.eip, 8)) {
  148. SmapDisabler disabler;
  149. u8* codeptr = (u8*)regs.eip;
  150. klog() << "code: " << String::format("%02x", codeptr[0]) << " " << String::format("%02x", codeptr[1]) << " " << String::format("%02x", codeptr[2]) << " " << String::format("%02x", codeptr[3]) << " " << String::format("%02x", codeptr[4]) << " " << String::format("%02x", codeptr[5]) << " " << String::format("%02x", codeptr[6]) << " " << String::format("%02x", codeptr[7]);
  151. }
  152. }
  153. void handle_crash(RegisterState& regs, const char* description, int signal)
  154. {
  155. if (!Process::current) {
  156. klog() << description << " with !current";
  157. hang();
  158. }
  159. // If a process crashed while inspecting another process,
  160. // make sure we switch back to the right page tables.
  161. MM.enter_process_paging_scope(*Process::current);
  162. klog() << "CRASH: " << description << ". Ring " << (Process::current->is_ring0() ? 0 : 3) << ".";
  163. dump(regs);
  164. if (Process::current->is_ring0()) {
  165. klog() << "Oh shit, we've crashed in ring 0 :(";
  166. dump_backtrace();
  167. hang();
  168. }
  169. cli();
  170. Process::current->crash(signal, regs.eip);
  171. }
  172. EH_ENTRY_NO_CODE(6, illegal_instruction);
  173. void illegal_instruction_handler(RegisterState regs)
  174. {
  175. clac();
  176. handle_crash(regs, "Illegal instruction", SIGILL);
  177. }
  178. EH_ENTRY_NO_CODE(0, divide_error);
  179. void divide_error_handler(RegisterState regs)
  180. {
  181. clac();
  182. handle_crash(regs, "Divide error", SIGFPE);
  183. }
  184. EH_ENTRY(13, general_protection_fault);
  185. void general_protection_fault_handler(RegisterState regs)
  186. {
  187. clac();
  188. handle_crash(regs, "General protection fault", SIGSEGV);
  189. }
  190. // 7: FPU not available exception
  191. EH_ENTRY_NO_CODE(7, fpu_exception);
  192. void fpu_exception_handler(RegisterState)
  193. {
  194. // Just clear the TS flag. We've already restored the FPU state eagerly.
  195. // FIXME: It would be nice if we didn't have to do this at all.
  196. asm volatile("clts");
  197. }
  198. // 14: Page Fault
  199. EH_ENTRY(14, page_fault);
  200. void page_fault_handler(RegisterState regs)
  201. {
  202. clac();
  203. u32 fault_address;
  204. asm("movl %%cr2, %%eax"
  205. : "=a"(fault_address));
  206. #ifdef PAGE_FAULT_DEBUG
  207. u32 fault_page_directory = read_cr3();
  208. dbg() << "Ring " << (regs.cs & 3)
  209. << " " << (regs.exception_code & 1 ? "PV" : "NP")
  210. << " page fault in PD=" << String::format("%x", fault_page_directory) << ", "
  211. << (regs.exception_code & 8 ? "reserved-bit " : "")
  212. << (regs.exception_code & 2 ? "write" : "read")
  213. << " " << VirtualAddress(fault_address);
  214. #endif
  215. #ifdef PAGE_FAULT_DEBUG
  216. dump(regs);
  217. #endif
  218. bool faulted_in_userspace = (regs.cs & 3) == 3;
  219. if (faulted_in_userspace && !MM.validate_user_stack(*Process::current, VirtualAddress(regs.userspace_esp))) {
  220. dbg() << "Invalid stack pointer: " << VirtualAddress(regs.userspace_esp);
  221. handle_crash(regs, "Bad stack on page fault", SIGSTKFLT);
  222. ASSERT_NOT_REACHED();
  223. }
  224. auto response = MM.handle_page_fault(PageFault(regs.exception_code, VirtualAddress(fault_address)));
  225. if (response == PageFaultResponse::ShouldCrash) {
  226. if (Thread::current->has_signal_handler(SIGSEGV)) {
  227. Thread::current->send_urgent_signal_to_self(SIGSEGV);
  228. return;
  229. }
  230. dbg() << "Unrecoverable page fault, "
  231. << (regs.exception_code & PageFaultFlags::ReservedBitViolation ? "reserved bit violation / " : "")
  232. << (regs.exception_code & PageFaultFlags::InstructionFetch ? "instruction fetch / " : "")
  233. << (regs.exception_code & PageFaultFlags::Write ? "write to" : "read from")
  234. << " address " << VirtualAddress(fault_address);
  235. u32 malloc_scrub_pattern = explode_byte(MALLOC_SCRUB_BYTE);
  236. u32 free_scrub_pattern = explode_byte(FREE_SCRUB_BYTE);
  237. u32 kmalloc_scrub_pattern = explode_byte(KMALLOC_SCRUB_BYTE);
  238. u32 kfree_scrub_pattern = explode_byte(KFREE_SCRUB_BYTE);
  239. u32 slab_alloc_scrub_pattern = explode_byte(SLAB_ALLOC_SCRUB_BYTE);
  240. u32 slab_dealloc_scrub_pattern = explode_byte(SLAB_DEALLOC_SCRUB_BYTE);
  241. if ((fault_address & 0xffff0000) == (malloc_scrub_pattern & 0xffff0000)) {
  242. dbg() << "Note: Address " << VirtualAddress(fault_address) << " looks like it may be uninitialized malloc() memory";
  243. } else if ((fault_address & 0xffff0000) == (free_scrub_pattern & 0xffff0000)) {
  244. dbg() << "Note: Address " << VirtualAddress(fault_address) << " looks like it may be recently free()'d memory";
  245. } else if ((fault_address & 0xffff0000) == (kmalloc_scrub_pattern & 0xffff0000)) {
  246. dbg() << "Note: Address " << VirtualAddress(fault_address) << " looks like it may be uninitialized kmalloc() memory";
  247. } else if ((fault_address & 0xffff0000) == (kfree_scrub_pattern & 0xffff0000)) {
  248. dbg() << "Note: Address " << VirtualAddress(fault_address) << " looks like it may be recently kfree()'d memory";
  249. } else if ((fault_address & 0xffff0000) == (slab_alloc_scrub_pattern & 0xffff0000)) {
  250. dbg() << "Note: Address " << VirtualAddress(fault_address) << " looks like it may be uninitialized slab_alloc() memory";
  251. } else if ((fault_address & 0xffff0000) == (slab_dealloc_scrub_pattern & 0xffff0000)) {
  252. dbg() << "Note: Address " << VirtualAddress(fault_address) << " looks like it may be recently slab_dealloc()'d memory";
  253. } else if (fault_address < 4096) {
  254. dbg() << "Note: Address " << VirtualAddress(fault_address) << " looks like a possible nullptr dereference";
  255. }
  256. handle_crash(regs, "Page Fault", SIGSEGV);
  257. } else if (response == PageFaultResponse::Continue) {
  258. #ifdef PAGE_FAULT_DEBUG
  259. dbg() << "Continuing after resolved page fault";
  260. #endif
  261. } else {
  262. ASSERT_NOT_REACHED();
  263. }
  264. }
  265. #define EH(i, msg) \
  266. static void _exception##i() \
  267. { \
  268. klog() << msg; \
  269. u32 cr0, cr2, cr3, cr4; \
  270. asm("movl %%cr0, %%eax" \
  271. : "=a"(cr0)); \
  272. asm("movl %%cr2, %%eax" \
  273. : "=a"(cr2)); \
  274. asm("movl %%cr3, %%eax" \
  275. : "=a"(cr3)); \
  276. asm("movl %%cr4, %%eax" \
  277. : "=a"(cr4)); \
  278. klog() << "CR0=" << String::format("%x", cr0) << " CR2=" << String::format("%x", cr2) << " CR3=" << String::format("%x", cr3) << " CR4=" << String::format("%x", cr4); \
  279. hang(); \
  280. }
  281. EH(1, "Debug exception")
  282. EH(2, "Unknown error")
  283. EH(3, "Breakpoint")
  284. EH(4, "Overflow")
  285. EH(5, "Bounds check")
  286. EH(8, "Double fault")
  287. EH(9, "Coprocessor segment overrun")
  288. EH(10, "Invalid TSS")
  289. EH(11, "Segment not present")
  290. EH(12, "Stack exception")
  291. EH(15, "Unknown error")
  292. EH(16, "Coprocessor error")
  293. static void write_raw_gdt_entry(u16 selector, u32 low, u32 high)
  294. {
  295. u16 i = (selector & 0xfffc) >> 3;
  296. s_gdt[i].low = low;
  297. s_gdt[i].high = high;
  298. if (i > s_gdt_length)
  299. s_gdtr.limit = (s_gdt_length + 1) * 8 - 1;
  300. }
  301. void write_gdt_entry(u16 selector, Descriptor& descriptor)
  302. {
  303. write_raw_gdt_entry(selector, descriptor.low, descriptor.high);
  304. }
  305. Descriptor& get_gdt_entry(u16 selector)
  306. {
  307. u16 i = (selector & 0xfffc) >> 3;
  308. return *(Descriptor*)(&s_gdt[i]);
  309. }
  310. void flush_gdt()
  311. {
  312. s_gdtr.address = s_gdt;
  313. s_gdtr.limit = (s_gdt_length * 8) - 1;
  314. asm("lgdt %0" ::"m"(s_gdtr)
  315. : "memory");
  316. }
  317. void gdt_init()
  318. {
  319. s_gdt_length = 5;
  320. s_gdt_freelist = new Vector<u16>();
  321. s_gdt_freelist->ensure_capacity(256);
  322. for (size_t i = s_gdt_length; i < 256; ++i)
  323. s_gdt_freelist->append(i * 8);
  324. s_gdt_length = 256;
  325. s_gdtr.address = s_gdt;
  326. s_gdtr.limit = (s_gdt_length * 8) - 1;
  327. write_raw_gdt_entry(0x0000, 0x00000000, 0x00000000);
  328. write_raw_gdt_entry(0x0008, 0x0000ffff, 0x00cf9a00);
  329. write_raw_gdt_entry(0x0010, 0x0000ffff, 0x00cf9200);
  330. write_raw_gdt_entry(0x0018, 0x0000ffff, 0x00cffa00);
  331. write_raw_gdt_entry(0x0020, 0x0000ffff, 0x00cff200);
  332. flush_gdt();
  333. asm volatile(
  334. "mov %%ax, %%ds\n"
  335. "mov %%ax, %%es\n"
  336. "mov %%ax, %%fs\n"
  337. "mov %%ax, %%gs\n"
  338. "mov %%ax, %%ss\n" ::"a"(0x10)
  339. : "memory");
  340. // Make sure CS points to the kernel code descriptor.
  341. asm volatile(
  342. "ljmpl $0x8, $sanity\n"
  343. "sanity:\n");
  344. }
  345. static void unimp_trap()
  346. {
  347. klog() << "Unhandled IRQ.";
  348. hang();
  349. }
  350. GenericInterruptHandler& get_interrupt_handler(u8 interrupt_number)
  351. {
  352. ASSERT(s_interrupt_handler[interrupt_number] != nullptr);
  353. return *s_interrupt_handler[interrupt_number];
  354. }
  355. static void revert_to_unused_handler(u8 interrupt_number)
  356. {
  357. new UnhandledInterruptHandler(interrupt_number);
  358. }
  359. void register_generic_interrupt_handler(u8 interrupt_number, GenericInterruptHandler& handler)
  360. {
  361. if (s_interrupt_handler[interrupt_number] != nullptr) {
  362. if (s_interrupt_handler[interrupt_number]->type() == HandlerType::UnhandledInterruptHandler) {
  363. s_interrupt_handler[interrupt_number] = &handler;
  364. return;
  365. }
  366. if (s_interrupt_handler[interrupt_number]->is_shared_handler() && !s_interrupt_handler[interrupt_number]->is_sharing_with_others()) {
  367. ASSERT(s_interrupt_handler[interrupt_number]->type() == HandlerType::SharedIRQHandler);
  368. static_cast<SharedIRQHandler*>(s_interrupt_handler[interrupt_number])->register_handler(handler);
  369. return;
  370. }
  371. if (!s_interrupt_handler[interrupt_number]->is_shared_handler()) {
  372. ASSERT(s_interrupt_handler[interrupt_number]->type() == HandlerType::IRQHandler);
  373. auto& previous_handler = *s_interrupt_handler[interrupt_number];
  374. s_interrupt_handler[interrupt_number] = nullptr;
  375. SharedIRQHandler::initialize(interrupt_number);
  376. static_cast<SharedIRQHandler*>(s_interrupt_handler[interrupt_number])->register_handler(previous_handler);
  377. static_cast<SharedIRQHandler*>(s_interrupt_handler[interrupt_number])->register_handler(handler);
  378. return;
  379. }
  380. ASSERT_NOT_REACHED();
  381. } else {
  382. s_interrupt_handler[interrupt_number] = &handler;
  383. }
  384. }
  385. void unregister_generic_interrupt_handler(u8 interrupt_number, GenericInterruptHandler& handler)
  386. {
  387. ASSERT(s_interrupt_handler[interrupt_number] != nullptr);
  388. if (s_interrupt_handler[interrupt_number]->type() == HandlerType::UnhandledInterruptHandler) {
  389. dbg() << "Trying to unregister unused handler (?)";
  390. return;
  391. }
  392. if (s_interrupt_handler[interrupt_number]->is_shared_handler() && !s_interrupt_handler[interrupt_number]->is_sharing_with_others()) {
  393. ASSERT(s_interrupt_handler[interrupt_number]->type() == HandlerType::SharedIRQHandler);
  394. static_cast<SharedIRQHandler*>(s_interrupt_handler[interrupt_number])->unregister_handler(handler);
  395. if (!static_cast<SharedIRQHandler*>(s_interrupt_handler[interrupt_number])->sharing_devices_count()) {
  396. revert_to_unused_handler(interrupt_number);
  397. }
  398. return;
  399. }
  400. if (!s_interrupt_handler[interrupt_number]->is_shared_handler()) {
  401. ASSERT(s_interrupt_handler[interrupt_number]->type() == HandlerType::IRQHandler);
  402. revert_to_unused_handler(interrupt_number);
  403. return;
  404. }
  405. ASSERT_NOT_REACHED();
  406. }
  407. void register_interrupt_handler(u8 index, void (*f)())
  408. {
  409. s_idt[index].low = 0x00080000 | LSW((f));
  410. s_idt[index].high = ((u32)(f)&0xffff0000) | 0x8e00;
  411. }
  412. void register_user_callable_interrupt_handler(u8 index, void (*f)())
  413. {
  414. s_idt[index].low = 0x00080000 | LSW((f));
  415. s_idt[index].high = ((u32)(f)&0xffff0000) | 0xef00;
  416. }
  417. void flush_idt()
  418. {
  419. asm("lidt %0" ::"m"(s_idtr));
  420. }
  421. void idt_init()
  422. {
  423. s_idtr.address = s_idt;
  424. s_idtr.limit = 0x100 * 8 - 1;
  425. for (u8 i = 0xff; i > 0x10; --i)
  426. register_interrupt_handler(i, unimp_trap);
  427. register_interrupt_handler(0x00, divide_error_asm_entry);
  428. register_interrupt_handler(0x01, _exception1);
  429. register_interrupt_handler(0x02, _exception2);
  430. register_interrupt_handler(0x03, _exception3);
  431. register_interrupt_handler(0x04, _exception4);
  432. register_interrupt_handler(0x05, _exception5);
  433. register_interrupt_handler(0x06, illegal_instruction_asm_entry);
  434. register_interrupt_handler(0x07, fpu_exception_asm_entry);
  435. register_interrupt_handler(0x08, _exception8);
  436. register_interrupt_handler(0x09, _exception9);
  437. register_interrupt_handler(0x0a, _exception10);
  438. register_interrupt_handler(0x0b, _exception11);
  439. register_interrupt_handler(0x0c, _exception12);
  440. register_interrupt_handler(0x0d, general_protection_fault_asm_entry);
  441. register_interrupt_handler(0x0e, page_fault_asm_entry);
  442. register_interrupt_handler(0x0f, _exception15);
  443. register_interrupt_handler(0x10, _exception16);
  444. register_interrupt_handler(0x50, interrupt_0_asm_entry);
  445. register_interrupt_handler(0x51, interrupt_1_asm_entry);
  446. register_interrupt_handler(0x52, interrupt_2_asm_entry);
  447. register_interrupt_handler(0x53, interrupt_3_asm_entry);
  448. register_interrupt_handler(0x54, interrupt_4_asm_entry);
  449. register_interrupt_handler(0x55, interrupt_5_asm_entry);
  450. register_interrupt_handler(0x56, interrupt_6_asm_entry);
  451. register_interrupt_handler(0x57, interrupt_7_asm_entry);
  452. register_interrupt_handler(0x58, interrupt_8_asm_entry);
  453. register_interrupt_handler(0x59, interrupt_9_asm_entry);
  454. register_interrupt_handler(0x5a, interrupt_10_asm_entry);
  455. register_interrupt_handler(0x5b, interrupt_11_asm_entry);
  456. register_interrupt_handler(0x5c, interrupt_12_asm_entry);
  457. register_interrupt_handler(0x5d, interrupt_13_asm_entry);
  458. register_interrupt_handler(0x5e, interrupt_14_asm_entry);
  459. register_interrupt_handler(0x5f, interrupt_15_asm_entry);
  460. register_interrupt_handler(0x60, interrupt_16_asm_entry);
  461. register_interrupt_handler(0x61, interrupt_17_asm_entry);
  462. register_interrupt_handler(0x62, interrupt_18_asm_entry);
  463. register_interrupt_handler(0x63, interrupt_19_asm_entry);
  464. register_interrupt_handler(0x64, interrupt_20_asm_entry);
  465. register_interrupt_handler(0x65, interrupt_21_asm_entry);
  466. register_interrupt_handler(0x66, interrupt_22_asm_entry);
  467. register_interrupt_handler(0x67, interrupt_23_asm_entry);
  468. register_interrupt_handler(0x68, interrupt_24_asm_entry);
  469. register_interrupt_handler(0x69, interrupt_25_asm_entry);
  470. register_interrupt_handler(0x6a, interrupt_26_asm_entry);
  471. register_interrupt_handler(0x6b, interrupt_27_asm_entry);
  472. register_interrupt_handler(0x6c, interrupt_28_asm_entry);
  473. register_interrupt_handler(0x6d, interrupt_29_asm_entry);
  474. register_interrupt_handler(0x6e, interrupt_30_asm_entry);
  475. register_interrupt_handler(0x6f, interrupt_31_asm_entry);
  476. register_interrupt_handler(0x70, interrupt_32_asm_entry);
  477. register_interrupt_handler(0x71, interrupt_33_asm_entry);
  478. register_interrupt_handler(0x72, interrupt_34_asm_entry);
  479. register_interrupt_handler(0x73, interrupt_35_asm_entry);
  480. register_interrupt_handler(0x74, interrupt_36_asm_entry);
  481. register_interrupt_handler(0x75, interrupt_37_asm_entry);
  482. register_interrupt_handler(0x76, interrupt_38_asm_entry);
  483. register_interrupt_handler(0x77, interrupt_39_asm_entry);
  484. register_interrupt_handler(0x78, interrupt_40_asm_entry);
  485. register_interrupt_handler(0x79, interrupt_41_asm_entry);
  486. register_interrupt_handler(0x7a, interrupt_42_asm_entry);
  487. register_interrupt_handler(0x7b, interrupt_43_asm_entry);
  488. register_interrupt_handler(0x7c, interrupt_44_asm_entry);
  489. register_interrupt_handler(0x7d, interrupt_45_asm_entry);
  490. register_interrupt_handler(0x7e, interrupt_46_asm_entry);
  491. register_interrupt_handler(0x7f, interrupt_47_asm_entry);
  492. register_interrupt_handler(0x80, interrupt_48_asm_entry);
  493. register_interrupt_handler(0x81, interrupt_49_asm_entry);
  494. register_interrupt_handler(0x82, interrupt_50_asm_entry);
  495. register_interrupt_handler(0x83, interrupt_51_asm_entry);
  496. register_interrupt_handler(0x84, interrupt_52_asm_entry);
  497. register_interrupt_handler(0x85, interrupt_53_asm_entry);
  498. register_interrupt_handler(0x86, interrupt_54_asm_entry);
  499. register_interrupt_handler(0x87, interrupt_55_asm_entry);
  500. register_interrupt_handler(0x88, interrupt_56_asm_entry);
  501. register_interrupt_handler(0x89, interrupt_57_asm_entry);
  502. register_interrupt_handler(0x8a, interrupt_58_asm_entry);
  503. register_interrupt_handler(0x8b, interrupt_59_asm_entry);
  504. register_interrupt_handler(0x8c, interrupt_60_asm_entry);
  505. register_interrupt_handler(0x8d, interrupt_61_asm_entry);
  506. register_interrupt_handler(0x8e, interrupt_62_asm_entry);
  507. register_interrupt_handler(0x8f, interrupt_63_asm_entry);
  508. register_interrupt_handler(0x90, interrupt_64_asm_entry);
  509. register_interrupt_handler(0x91, interrupt_65_asm_entry);
  510. register_interrupt_handler(0x92, interrupt_66_asm_entry);
  511. register_interrupt_handler(0x93, interrupt_67_asm_entry);
  512. register_interrupt_handler(0x94, interrupt_68_asm_entry);
  513. register_interrupt_handler(0x95, interrupt_69_asm_entry);
  514. register_interrupt_handler(0x96, interrupt_70_asm_entry);
  515. register_interrupt_handler(0x97, interrupt_71_asm_entry);
  516. register_interrupt_handler(0x98, interrupt_72_asm_entry);
  517. register_interrupt_handler(0x99, interrupt_73_asm_entry);
  518. register_interrupt_handler(0x9a, interrupt_74_asm_entry);
  519. register_interrupt_handler(0x9b, interrupt_75_asm_entry);
  520. register_interrupt_handler(0x9c, interrupt_76_asm_entry);
  521. register_interrupt_handler(0x9d, interrupt_77_asm_entry);
  522. register_interrupt_handler(0x9e, interrupt_78_asm_entry);
  523. register_interrupt_handler(0x9f, interrupt_79_asm_entry);
  524. register_interrupt_handler(0xa0, interrupt_80_asm_entry);
  525. register_interrupt_handler(0xa1, interrupt_81_asm_entry);
  526. register_interrupt_handler(0xa2, interrupt_82_asm_entry);
  527. register_interrupt_handler(0xa3, interrupt_83_asm_entry);
  528. register_interrupt_handler(0xa4, interrupt_84_asm_entry);
  529. register_interrupt_handler(0xa5, interrupt_85_asm_entry);
  530. register_interrupt_handler(0xa6, interrupt_86_asm_entry);
  531. register_interrupt_handler(0xa7, interrupt_87_asm_entry);
  532. register_interrupt_handler(0xa8, interrupt_88_asm_entry);
  533. register_interrupt_handler(0xa9, interrupt_89_asm_entry);
  534. register_interrupt_handler(0xaa, interrupt_90_asm_entry);
  535. register_interrupt_handler(0xab, interrupt_91_asm_entry);
  536. register_interrupt_handler(0xac, interrupt_92_asm_entry);
  537. register_interrupt_handler(0xad, interrupt_93_asm_entry);
  538. register_interrupt_handler(0xae, interrupt_94_asm_entry);
  539. register_interrupt_handler(0xaf, interrupt_95_asm_entry);
  540. register_interrupt_handler(0xb0, interrupt_96_asm_entry);
  541. register_interrupt_handler(0xb1, interrupt_97_asm_entry);
  542. register_interrupt_handler(0xb2, interrupt_98_asm_entry);
  543. register_interrupt_handler(0xb3, interrupt_99_asm_entry);
  544. register_interrupt_handler(0xb4, interrupt_100_asm_entry);
  545. register_interrupt_handler(0xb5, interrupt_101_asm_entry);
  546. register_interrupt_handler(0xb6, interrupt_102_asm_entry);
  547. register_interrupt_handler(0xb7, interrupt_103_asm_entry);
  548. register_interrupt_handler(0xb8, interrupt_104_asm_entry);
  549. register_interrupt_handler(0xb9, interrupt_105_asm_entry);
  550. register_interrupt_handler(0xba, interrupt_106_asm_entry);
  551. register_interrupt_handler(0xbb, interrupt_107_asm_entry);
  552. register_interrupt_handler(0xbc, interrupt_108_asm_entry);
  553. register_interrupt_handler(0xbd, interrupt_109_asm_entry);
  554. register_interrupt_handler(0xbe, interrupt_110_asm_entry);
  555. register_interrupt_handler(0xbf, interrupt_111_asm_entry);
  556. register_interrupt_handler(0xc0, interrupt_112_asm_entry);
  557. register_interrupt_handler(0xc1, interrupt_113_asm_entry);
  558. register_interrupt_handler(0xc2, interrupt_114_asm_entry);
  559. register_interrupt_handler(0xc3, interrupt_115_asm_entry);
  560. register_interrupt_handler(0xc4, interrupt_116_asm_entry);
  561. register_interrupt_handler(0xc5, interrupt_117_asm_entry);
  562. register_interrupt_handler(0xc6, interrupt_118_asm_entry);
  563. register_interrupt_handler(0xc7, interrupt_119_asm_entry);
  564. register_interrupt_handler(0xc8, interrupt_120_asm_entry);
  565. register_interrupt_handler(0xc9, interrupt_121_asm_entry);
  566. register_interrupt_handler(0xca, interrupt_122_asm_entry);
  567. register_interrupt_handler(0xcb, interrupt_123_asm_entry);
  568. register_interrupt_handler(0xcc, interrupt_124_asm_entry);
  569. register_interrupt_handler(0xcd, interrupt_125_asm_entry);
  570. register_interrupt_handler(0xce, interrupt_126_asm_entry);
  571. register_interrupt_handler(0xcf, interrupt_127_asm_entry);
  572. dbg() << "Installing Unhandled Handlers";
  573. for (u8 i = 0; i < GENERIC_INTERRUPT_HANDLERS_COUNT; ++i) {
  574. new UnhandledInterruptHandler(i);
  575. }
  576. flush_idt();
  577. }
  578. void load_task_register(u16 selector)
  579. {
  580. asm("ltr %0" ::"r"(selector));
  581. }
  582. u32 g_in_irq;
  583. void handle_interrupt(RegisterState regs)
  584. {
  585. clac();
  586. ++g_in_irq;
  587. ASSERT(regs.isr_number >= IRQ_VECTOR_BASE && regs.isr_number <= (IRQ_VECTOR_BASE + GENERIC_INTERRUPT_HANDLERS_COUNT));
  588. u8 irq = (u8)(regs.isr_number - 0x50);
  589. ASSERT(s_interrupt_handler[irq]);
  590. s_interrupt_handler[irq]->handle_interrupt(regs);
  591. s_interrupt_handler[irq]->increment_invoking_counter();
  592. --g_in_irq;
  593. s_interrupt_handler[irq]->eoi();
  594. }
  595. void sse_init()
  596. {
  597. asm volatile(
  598. "mov %cr0, %eax\n"
  599. "andl $0xfffffffb, %eax\n"
  600. "orl $0x2, %eax\n"
  601. "mov %eax, %cr0\n"
  602. "mov %cr4, %eax\n"
  603. "orl $0x600, %eax\n"
  604. "mov %eax, %cr4\n");
  605. }
  606. bool g_cpu_supports_nx;
  607. bool g_cpu_supports_pae;
  608. bool g_cpu_supports_pge;
  609. bool g_cpu_supports_rdrand;
  610. bool g_cpu_supports_smap;
  611. bool g_cpu_supports_smep;
  612. bool g_cpu_supports_sse;
  613. bool g_cpu_supports_tsc;
  614. bool g_cpu_supports_umip;
  615. void cpu_detect()
  616. {
  617. CPUID processor_info(0x1);
  618. g_cpu_supports_pae = (processor_info.edx() & (1 << 6));
  619. g_cpu_supports_pge = (processor_info.edx() & (1 << 13));
  620. g_cpu_supports_sse = (processor_info.edx() & (1 << 25));
  621. g_cpu_supports_tsc = (processor_info.edx() & (1 << 4));
  622. g_cpu_supports_rdrand = (processor_info.ecx() & (1 << 30));
  623. CPUID extended_processor_info(0x80000001);
  624. g_cpu_supports_nx = (extended_processor_info.edx() & (1 << 20));
  625. CPUID extended_features(0x7);
  626. g_cpu_supports_smap = (extended_features.ebx() & (1 << 20));
  627. g_cpu_supports_smep = (extended_features.ebx() & (1 << 7));
  628. g_cpu_supports_umip = (extended_features.ecx() & (1 << 2));
  629. }
  630. void stac()
  631. {
  632. if (!g_cpu_supports_smap)
  633. return;
  634. asm volatile("stac" ::
  635. : "cc");
  636. }
  637. void clac()
  638. {
  639. if (!g_cpu_supports_smap)
  640. return;
  641. asm volatile("clac" ::
  642. : "cc");
  643. }
  644. void cpu_setup()
  645. {
  646. cpu_detect();
  647. if (g_cpu_supports_sse) {
  648. sse_init();
  649. klog() << "x86: SSE support enabled";
  650. }
  651. asm volatile(
  652. "movl %%cr0, %%eax\n"
  653. "orl $0x00010000, %%eax\n"
  654. "movl %%eax, %%cr0\n" ::
  655. : "%eax", "memory");
  656. klog() << "x86: WP support enabled";
  657. if (g_cpu_supports_pge) {
  658. // Turn on CR4.PGE so the CPU will respect the G bit in page tables.
  659. asm volatile(
  660. "mov %cr4, %eax\n"
  661. "orl $0x80, %eax\n"
  662. "mov %eax, %cr4\n");
  663. klog() << "x86: PGE support enabled";
  664. } else {
  665. klog() << "x86: PGE support not detected";
  666. }
  667. if (g_cpu_supports_nx) {
  668. // Turn on IA32_EFER.NXE
  669. asm volatile(
  670. "movl $0xc0000080, %ecx\n"
  671. "rdmsr\n"
  672. "orl $0x800, %eax\n"
  673. "wrmsr\n");
  674. klog() << "x86: NX support enabled";
  675. } else {
  676. klog() << "x86: NX support not detected";
  677. }
  678. if (g_cpu_supports_smep) {
  679. // Turn on CR4.SMEP
  680. asm volatile(
  681. "mov %cr4, %eax\n"
  682. "orl $0x100000, %eax\n"
  683. "mov %eax, %cr4\n");
  684. klog() << "x86: SMEP support enabled";
  685. } else {
  686. klog() << "x86: SMEP support not detected";
  687. }
  688. if (g_cpu_supports_smap) {
  689. // Turn on CR4.SMAP
  690. klog() << "x86: Enabling SMAP";
  691. asm volatile(
  692. "mov %cr4, %eax\n"
  693. "orl $0x200000, %eax\n"
  694. "mov %eax, %cr4\n");
  695. klog() << "x86: SMAP support enabled";
  696. } else {
  697. klog() << "x86: SMAP support not detected";
  698. }
  699. if (g_cpu_supports_umip) {
  700. asm volatile(
  701. "mov %cr4, %eax\n"
  702. "orl $0x800, %eax\n"
  703. "mov %eax, %cr4\n");
  704. klog() << "x86: UMIP support enabled";
  705. }
  706. if (g_cpu_supports_tsc) {
  707. asm volatile(
  708. "mov %cr4, %eax\n"
  709. "orl $0x4, %eax\n"
  710. "mov %eax, %cr4\n");
  711. klog() << "x86: RDTSC support restricted";
  712. }
  713. if (g_cpu_supports_rdrand) {
  714. klog() << "x86: Using RDRAND for good randomness";
  715. } else {
  716. klog() << "x86: No RDRAND support detected. Randomness will be shitty";
  717. }
  718. }
  719. u32 read_cr3()
  720. {
  721. u32 cr3;
  722. asm("movl %%cr3, %%eax"
  723. : "=a"(cr3));
  724. return cr3;
  725. }
  726. void write_cr3(u32 cr3)
  727. {
  728. asm volatile("movl %%eax, %%cr3" ::"a"(cr3)
  729. : "memory");
  730. }
  731. }
  732. #ifdef DEBUG
  733. void __assertion_failed(const char* msg, const char* file, unsigned line, const char* func)
  734. {
  735. asm volatile("cli");
  736. klog() << "ASSERTION FAILED: " << msg << "\n"
  737. << file << ":" << line << " in " << func;
  738. // Switch back to the current process's page tables if there are any.
  739. // Otherwise stack walking will be a disaster.
  740. if (Process::current)
  741. MM.enter_process_paging_scope(*Process::current);
  742. Kernel::dump_backtrace();
  743. asm volatile("hlt");
  744. for (;;)
  745. ;
  746. }
  747. #endif
  748. NonMaskableInterruptDisabler::NonMaskableInterruptDisabler()
  749. {
  750. IO::out8(0x70, IO::in8(0x70) | 0x80);
  751. }
  752. NonMaskableInterruptDisabler::~NonMaskableInterruptDisabler()
  753. {
  754. IO::out8(0x70, IO::in8(0x70) & 0x7F);
  755. }