Processor.h 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451
  1. /*
  2. * Copyright (c) 2018-2021, Andreas Kling <kling@serenityos.org>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #pragma once
  7. #include <AK/Array.h>
  8. #include <AK/Concepts.h>
  9. #include <AK/Function.h>
  10. #include <AK/Types.h>
  11. #include <Kernel/Arch/x86/ASM_wrapper.h>
  12. #include <Kernel/Arch/x86/CPUID.h>
  13. #include <Kernel/Arch/x86/DescriptorTable.h>
  14. #include <Kernel/Arch/x86/PageDirectory.h>
  15. #include <Kernel/Arch/x86/TSS.h>
  16. #include <Kernel/Forward.h>
  17. namespace Kernel {
  18. class ProcessorInfo;
  19. class SchedulerPerProcessorData;
  20. struct MemoryManagerData;
  21. struct ProcessorMessageEntry;
  22. #if ARCH(X86_64)
  23. # define MSR_FS_BASE 0xc0000100
  24. # define MSR_GS_BASE 0xc0000101
  25. #endif
  26. // FIXME: Find a better place for these
  27. extern "C" void thread_context_first_enter(void);
  28. extern "C" void exit_kernel_thread(void);
  29. extern "C" void do_assume_context(Thread* thread, u32 flags);
  30. struct [[gnu::aligned(16)]] FPUState
  31. {
  32. u8 buffer[512];
  33. };
  34. struct ProcessorMessage {
  35. using CallbackFunction = Function<void()>;
  36. enum Type {
  37. FlushTlb,
  38. Callback,
  39. };
  40. Type type;
  41. Atomic<u32> refs;
  42. union {
  43. ProcessorMessage* next; // only valid while in the pool
  44. alignas(CallbackFunction) u8 callback_storage[sizeof(CallbackFunction)];
  45. struct {
  46. const PageDirectory* page_directory;
  47. u8* ptr;
  48. size_t page_count;
  49. } flush_tlb;
  50. };
  51. volatile bool async;
  52. ProcessorMessageEntry* per_proc_entries;
  53. CallbackFunction& callback_value()
  54. {
  55. return *bit_cast<CallbackFunction*>(&callback_storage);
  56. }
  57. void invoke_callback()
  58. {
  59. VERIFY(type == Type::Callback);
  60. callback_value()();
  61. }
  62. };
  63. struct ProcessorMessageEntry {
  64. ProcessorMessageEntry* next;
  65. ProcessorMessage* msg;
  66. };
  67. struct DeferredCallEntry {
  68. using HandlerFunction = Function<void()>;
  69. DeferredCallEntry* next;
  70. alignas(HandlerFunction) u8 handler_storage[sizeof(HandlerFunction)];
  71. bool was_allocated;
  72. HandlerFunction& handler_value()
  73. {
  74. return *bit_cast<HandlerFunction*>(&handler_storage);
  75. }
  76. void invoke_handler()
  77. {
  78. handler_value()();
  79. }
  80. };
  81. class Processor;
  82. // Note: We only support 8 processors at most at the moment,
  83. // so allocate 8 slots of inline capacity in the container.
  84. using ProcessorContainer = Array<Processor*, 8>;
  85. class Processor {
  86. friend class ProcessorInfo;
  87. AK_MAKE_NONCOPYABLE(Processor);
  88. AK_MAKE_NONMOVABLE(Processor);
  89. Processor* m_self;
  90. DescriptorTablePointer m_gdtr;
  91. Descriptor m_gdt[256];
  92. u32 m_gdt_length;
  93. u32 m_cpu;
  94. u32 m_in_irq;
  95. Atomic<u32, AK::MemoryOrder::memory_order_relaxed> m_in_critical;
  96. static Atomic<u32> s_idle_cpu_mask;
  97. TSS m_tss;
  98. static FPUState s_clean_fpu_state;
  99. CPUFeature m_features;
  100. static Atomic<u32> g_total_processors;
  101. u8 m_physical_address_bit_width;
  102. ProcessorInfo* m_info;
  103. MemoryManagerData* m_mm_data;
  104. SchedulerPerProcessorData* m_scheduler_data;
  105. Thread* m_current_thread;
  106. Thread* m_idle_thread;
  107. Atomic<ProcessorMessageEntry*> m_message_queue;
  108. bool m_invoke_scheduler_async;
  109. bool m_scheduler_initialized;
  110. Atomic<bool> m_halt_requested;
  111. DeferredCallEntry* m_pending_deferred_calls; // in reverse order
  112. DeferredCallEntry* m_free_deferred_call_pool_entry;
  113. DeferredCallEntry m_deferred_call_pool[5];
  114. void gdt_init();
  115. void write_raw_gdt_entry(u16 selector, u32 low, u32 high);
  116. void write_gdt_entry(u16 selector, Descriptor& descriptor);
  117. static ProcessorContainer& processors();
  118. static void smp_return_to_pool(ProcessorMessage& msg);
  119. static ProcessorMessage& smp_get_from_pool();
  120. static void smp_cleanup_message(ProcessorMessage& msg);
  121. bool smp_queue_message(ProcessorMessage& msg);
  122. static void smp_unicast_message(u32 cpu, ProcessorMessage& msg, bool async);
  123. static void smp_broadcast_message(ProcessorMessage& msg);
  124. static void smp_broadcast_wait_sync(ProcessorMessage& msg);
  125. static void smp_broadcast_halt();
  126. void deferred_call_pool_init();
  127. void deferred_call_execute_pending();
  128. DeferredCallEntry* deferred_call_get_free();
  129. void deferred_call_return_to_pool(DeferredCallEntry*);
  130. void deferred_call_queue_entry(DeferredCallEntry*);
  131. void cpu_detect();
  132. void cpu_setup();
  133. String features_string() const;
  134. public:
  135. Processor() = default;
  136. void early_initialize(u32 cpu);
  137. void initialize(u32 cpu);
  138. void detect_hypervisor();
  139. void idle_begin()
  140. {
  141. s_idle_cpu_mask.fetch_or(1u << m_cpu, AK::MemoryOrder::memory_order_relaxed);
  142. }
  143. void idle_end()
  144. {
  145. s_idle_cpu_mask.fetch_and(~(1u << m_cpu), AK::MemoryOrder::memory_order_relaxed);
  146. }
  147. static u32 count()
  148. {
  149. // NOTE: because this value never changes once all APs are booted,
  150. // we can safely bypass loading it atomically.
  151. return *g_total_processors.ptr();
  152. }
  153. ALWAYS_INLINE static void wait_check()
  154. {
  155. Processor::current().smp_process_pending_messages();
  156. // TODO: pause
  157. }
  158. [[noreturn]] static void halt();
  159. static void flush_entire_tlb_local()
  160. {
  161. write_cr3(read_cr3());
  162. }
  163. static void flush_tlb_local(VirtualAddress vaddr, size_t page_count);
  164. static void flush_tlb(const PageDirectory*, VirtualAddress, size_t);
  165. Descriptor& get_gdt_entry(u16 selector);
  166. void flush_gdt();
  167. const DescriptorTablePointer& get_gdtr();
  168. static Processor& by_id(u32 cpu);
  169. static size_t processor_count() { return processors().size(); }
  170. template<IteratorFunction<Processor&> Callback>
  171. static inline IterationDecision for_each(Callback callback)
  172. {
  173. auto& procs = processors();
  174. size_t count = procs.size();
  175. for (size_t i = 0; i < count; i++) {
  176. if (callback(*procs[i]) == IterationDecision::Break)
  177. return IterationDecision::Break;
  178. }
  179. return IterationDecision::Continue;
  180. }
  181. template<VoidFunction<Processor&> Callback>
  182. static inline IterationDecision for_each(Callback callback)
  183. {
  184. auto& procs = processors();
  185. size_t count = procs.size();
  186. for (size_t i = 0; i < count; i++) {
  187. if (procs[i] != nullptr)
  188. callback(*procs[i]);
  189. }
  190. return IterationDecision::Continue;
  191. }
  192. ALWAYS_INLINE u8 physical_address_bit_width() const { return m_physical_address_bit_width; }
  193. ALWAYS_INLINE ProcessorInfo& info() { return *m_info; }
  194. ALWAYS_INLINE static Processor& current()
  195. {
  196. return *(Processor*)read_gs_ptr(__builtin_offsetof(Processor, m_self));
  197. }
  198. ALWAYS_INLINE static bool is_initialized()
  199. {
  200. return
  201. #if ARCH(I386)
  202. get_gs() == GDT_SELECTOR_PROC &&
  203. #endif
  204. read_gs_u32(__builtin_offsetof(Processor, m_self)) != 0;
  205. }
  206. ALWAYS_INLINE void set_scheduler_data(SchedulerPerProcessorData& scheduler_data)
  207. {
  208. m_scheduler_data = &scheduler_data;
  209. }
  210. ALWAYS_INLINE SchedulerPerProcessorData& get_scheduler_data() const
  211. {
  212. return *m_scheduler_data;
  213. }
  214. ALWAYS_INLINE void set_mm_data(MemoryManagerData& mm_data)
  215. {
  216. m_mm_data = &mm_data;
  217. }
  218. ALWAYS_INLINE MemoryManagerData& get_mm_data() const
  219. {
  220. return *m_mm_data;
  221. }
  222. ALWAYS_INLINE void set_idle_thread(Thread& idle_thread)
  223. {
  224. m_idle_thread = &idle_thread;
  225. }
  226. ALWAYS_INLINE static Thread* current_thread()
  227. {
  228. // If we were to use Processor::current here, we'd have to
  229. // disable interrupts to prevent a race where we may get pre-empted
  230. // right after getting the Processor structure and then get moved
  231. // to another processor, which would lead us to get the wrong thread.
  232. // To avoid having to disable interrupts, we can just read the field
  233. // directly in an atomic fashion, similar to Processor::current.
  234. return (Thread*)read_gs_ptr(__builtin_offsetof(Processor, m_current_thread));
  235. }
  236. ALWAYS_INLINE static void set_current_thread(Thread& current_thread)
  237. {
  238. // See comment in Processor::current_thread
  239. write_gs_u32(__builtin_offsetof(Processor, m_current_thread), FlatPtr(&current_thread));
  240. }
  241. ALWAYS_INLINE static Thread* idle_thread()
  242. {
  243. // See comment in Processor::current_thread
  244. return (Thread*)read_gs_ptr(__builtin_offsetof(Processor, m_idle_thread));
  245. }
  246. ALWAYS_INLINE u32 get_id() const
  247. {
  248. // NOTE: This variant should only be used when iterating over all
  249. // Processor instances, or when it's guaranteed that the thread
  250. // cannot move to another processor in between calling Processor::current
  251. // and Processor::get_id, or if this fact is not important.
  252. // All other cases should use Processor::id instead!
  253. return m_cpu;
  254. }
  255. ALWAYS_INLINE static u32 id()
  256. {
  257. // See comment in Processor::current_thread
  258. return read_gs_ptr(__builtin_offsetof(Processor, m_cpu));
  259. }
  260. ALWAYS_INLINE static bool is_bootstrap_processor()
  261. {
  262. return Processor::id() == 0;
  263. }
  264. ALWAYS_INLINE u32 raise_irq()
  265. {
  266. return m_in_irq++;
  267. }
  268. ALWAYS_INLINE void restore_irq(u32 prev_irq)
  269. {
  270. VERIFY(prev_irq <= m_in_irq);
  271. if (!prev_irq) {
  272. u32 prev_critical = 0;
  273. if (m_in_critical.compare_exchange_strong(prev_critical, 1)) {
  274. m_in_irq = prev_irq;
  275. deferred_call_execute_pending();
  276. auto prev_raised = m_in_critical.exchange(prev_critical);
  277. VERIFY(prev_raised == prev_critical + 1);
  278. check_invoke_scheduler();
  279. } else if (prev_critical == 0) {
  280. check_invoke_scheduler();
  281. }
  282. } else {
  283. m_in_irq = prev_irq;
  284. }
  285. }
  286. ALWAYS_INLINE u32& in_irq()
  287. {
  288. return m_in_irq;
  289. }
  290. ALWAYS_INLINE void restore_in_critical(u32 critical)
  291. {
  292. m_in_critical = critical;
  293. }
  294. ALWAYS_INLINE void enter_critical(u32& prev_flags)
  295. {
  296. prev_flags = cpu_flags();
  297. cli();
  298. m_in_critical++;
  299. }
  300. ALWAYS_INLINE void leave_critical(u32 prev_flags)
  301. {
  302. cli(); // Need to prevent IRQs from interrupting us here!
  303. VERIFY(m_in_critical > 0);
  304. if (m_in_critical == 1) {
  305. if (!m_in_irq) {
  306. deferred_call_execute_pending();
  307. VERIFY(m_in_critical == 1);
  308. }
  309. m_in_critical--;
  310. if (!m_in_irq)
  311. check_invoke_scheduler();
  312. } else {
  313. m_in_critical--;
  314. }
  315. if (prev_flags & 0x200)
  316. sti();
  317. else
  318. cli();
  319. }
  320. ALWAYS_INLINE u32 clear_critical(u32& prev_flags, bool enable_interrupts)
  321. {
  322. prev_flags = cpu_flags();
  323. u32 prev_crit = m_in_critical.exchange(0, AK::MemoryOrder::memory_order_acquire);
  324. if (!m_in_irq)
  325. check_invoke_scheduler();
  326. if (enable_interrupts)
  327. sti();
  328. return prev_crit;
  329. }
  330. ALWAYS_INLINE void restore_critical(u32 prev_crit, u32 prev_flags)
  331. {
  332. m_in_critical.store(prev_crit, AK::MemoryOrder::memory_order_release);
  333. VERIFY(!prev_crit || !(prev_flags & 0x200));
  334. if (prev_flags & 0x200)
  335. sti();
  336. else
  337. cli();
  338. }
  339. ALWAYS_INLINE u32 in_critical() { return m_in_critical.load(); }
  340. ALWAYS_INLINE const FPUState& clean_fpu_state() const
  341. {
  342. return s_clean_fpu_state;
  343. }
  344. static void smp_enable();
  345. bool smp_process_pending_messages();
  346. static void smp_broadcast(Function<void()>, bool async);
  347. static void smp_unicast(u32 cpu, Function<void()>, bool async);
  348. static void smp_broadcast_flush_tlb(const PageDirectory*, VirtualAddress, size_t);
  349. static u32 smp_wake_n_idle_processors(u32 wake_count);
  350. static void deferred_call_queue(Function<void()> callback);
  351. ALWAYS_INLINE bool has_feature(CPUFeature f) const
  352. {
  353. return (static_cast<u32>(m_features) & static_cast<u32>(f)) != 0;
  354. }
  355. void check_invoke_scheduler();
  356. void invoke_scheduler_async() { m_invoke_scheduler_async = true; }
  357. void enter_trap(TrapFrame& trap, bool raise_irq);
  358. void exit_trap(TrapFrame& trap);
  359. [[noreturn]] void initialize_context_switching(Thread& initial_thread);
  360. NEVER_INLINE void switch_context(Thread*& from_thread, Thread*& to_thread);
  361. [[noreturn]] static void assume_context(Thread& thread, FlatPtr flags);
  362. FlatPtr init_context(Thread& thread, bool leave_crit);
  363. static Vector<FlatPtr> capture_stack_trace(Thread& thread, size_t max_frames = 0);
  364. String platform_string() const;
  365. };
  366. }