PowerStateSwitchTask.cpp 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  1. /*
  2. * Copyright (c) 2023, kleines Filmröllchen <filmroellchen@serenityos.org>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include <AK/Platform.h>
  7. #if ARCH(X86_64)
  8. # include <Kernel/Arch/x86_64/I8042Reboot.h>
  9. # include <Kernel/Arch/x86_64/Shutdown.h>
  10. #elif ARCH(AARCH64)
  11. # include <Kernel/Arch/aarch64/RPi/Watchdog.h>
  12. #endif
  13. #include <AK/StringView.h>
  14. #include <Kernel/Arch/PowerState.h>
  15. #include <Kernel/FileSystem/FileSystem.h>
  16. #include <Kernel/FileSystem/VirtualFileSystem.h>
  17. #include <Kernel/Firmware/ACPI/Parser.h>
  18. #include <Kernel/Library/Panic.h>
  19. #include <Kernel/Sections.h>
  20. #include <Kernel/TTY/ConsoleManagement.h>
  21. #include <Kernel/Tasks/FinalizerTask.h>
  22. #include <Kernel/Tasks/PowerStateSwitchTask.h>
  23. #include <Kernel/Tasks/Process.h>
  24. #include <Kernel/Tasks/Scheduler.h>
  25. namespace Kernel {
  26. Thread* g_power_state_switch_task;
  27. bool g_in_system_shutdown { false };
  28. void PowerStateSwitchTask::power_state_switch_task(void* raw_entry_data)
  29. {
  30. Thread::current()->set_priority(THREAD_PRIORITY_HIGH);
  31. auto entry_data = bit_cast<PowerStateCommand>(raw_entry_data);
  32. switch (entry_data) {
  33. case PowerStateCommand::Shutdown:
  34. MUST(PowerStateSwitchTask::perform_shutdown());
  35. break;
  36. case PowerStateCommand::Reboot:
  37. MUST(PowerStateSwitchTask::perform_reboot());
  38. break;
  39. default:
  40. PANIC("Unknown power state command: {}", to_underlying(entry_data));
  41. }
  42. // Although common, the system may not halt through this task.
  43. // Clear the power state switch task so that it can be spawned again.
  44. g_power_state_switch_task = nullptr;
  45. }
  46. void PowerStateSwitchTask::spawn(PowerStateCommand command)
  47. {
  48. VERIFY(g_power_state_switch_task == nullptr);
  49. auto [_, power_state_switch_task_thread] = MUST(Process::create_kernel_process(
  50. "Power State Switch Task"sv, power_state_switch_task, bit_cast<void*>(command)));
  51. g_power_state_switch_task = move(power_state_switch_task_thread);
  52. }
  53. ErrorOr<void> PowerStateSwitchTask::perform_reboot()
  54. {
  55. dbgln("acquiring FS locks...");
  56. FileSystem::lock_all();
  57. dbgln("syncing mounted filesystems...");
  58. FileSystem::sync();
  59. dbgln("attempting reboot via ACPI");
  60. if (ACPI::is_enabled())
  61. ACPI::Parser::the()->try_acpi_reboot();
  62. arch_specific_reboot();
  63. dbgln("reboot attempts failed, applications will stop responding.");
  64. dmesgln("Reboot can't be completed. It's safe to turn off the computer!");
  65. Processor::halt();
  66. }
  67. ErrorOr<void> PowerStateSwitchTask::perform_shutdown()
  68. {
  69. // We assume that by this point userland has tried as much as possible to shut down everything in an orderly fashion.
  70. // Therefore, we force kill remaining processes, including Kernel processes, except the finalizer and ourselves.
  71. dbgln("Killing remaining processes...");
  72. Optional<Process&> finalizer_process;
  73. Process::all_instances().for_each([&](Process& process) {
  74. if (process.pid() == g_finalizer->process().pid())
  75. finalizer_process = process;
  76. });
  77. VERIFY(finalizer_process.has_value());
  78. // Allow init process and finalizer task to be killed.
  79. g_in_system_shutdown = true;
  80. // Make sure to kill all user processes first, otherwise we might get weird hangups.
  81. TRY(kill_all_user_processes());
  82. size_t alive_process_count = 0;
  83. Process::all_instances().for_each([&](Process& process) {
  84. if (!process.is_kernel_process() && !process.is_dead())
  85. alive_process_count++;
  86. });
  87. // Don't panic here (since we may panic in a bit anyways) but report the probable cause of an unclean shutdown.
  88. if (alive_process_count != 0)
  89. dbgln("We're not the last process alive; proper shutdown may fail!");
  90. ConsoleManagement::the().switch_to_debug();
  91. dbgln("Locking all file systems...");
  92. FileSystem::lock_all();
  93. FileSystem::sync();
  94. dbgln("Unmounting all file systems...");
  95. auto unmount_was_successful = true;
  96. while (unmount_was_successful) {
  97. unmount_was_successful = false;
  98. Vector<Mount&, 16> mounts;
  99. TRY(VirtualFileSystem::the().for_each_mount([&](auto const& mount) -> ErrorOr<void> {
  100. TRY(mounts.try_append(const_cast<Mount&>(mount)));
  101. return {};
  102. }));
  103. if (mounts.is_empty())
  104. break;
  105. auto const remaining_mounts = mounts.size();
  106. while (!mounts.is_empty()) {
  107. auto& mount = mounts.take_last();
  108. mount.guest_fs().flush_writes();
  109. auto mount_path = TRY(mount.absolute_path());
  110. auto& mount_inode = mount.guest();
  111. auto const result = VirtualFileSystem::the().unmount(mount_inode, mount_path->view());
  112. if (result.is_error()) {
  113. dbgln("Error during unmount of {}: {}", mount_path, result.error());
  114. // FIXME: For unknown reasons the root FS stays busy even after everything else has shut down and was unmounted.
  115. // Until we find the underlying issue, allow an unclean shutdown here.
  116. if (remaining_mounts <= 1)
  117. dbgln("BUG! One mount remaining; the root file system may not be unmountable at all. Shutting down anyways.");
  118. } else {
  119. unmount_was_successful = true;
  120. }
  121. }
  122. }
  123. // NOTE: We don't really need to kill kernel processes, because in contrast
  124. // to user processes, kernel processes will simply not make syscalls
  125. // or do some other unexpected behavior.
  126. // Therefore, we just lock the scheduler big lock to ensure nothing happens
  127. // beyond this point forward.
  128. SpinlockLocker lock(g_scheduler_lock);
  129. dbgln("Attempting system shutdown...");
  130. arch_specific_poweroff();
  131. dbgln("shutdown attempts failed, applications will stop responding.");
  132. dmesgln("Shutdown can't be completed. It's safe to turn off the computer!");
  133. Processor::halt();
  134. }
  135. ErrorOr<void> PowerStateSwitchTask::kill_all_user_processes()
  136. {
  137. {
  138. SpinlockLocker lock(g_scheduler_lock);
  139. Process::all_instances().for_each([&](Process& process) {
  140. if (!process.is_kernel_process())
  141. process.die();
  142. });
  143. }
  144. // Although we *could* finalize processes ourselves (g_in_system_shutdown allows this),
  145. // we're nice citizens and let the finalizer task perform final duties before we kill it.
  146. Scheduler::notify_finalizer();
  147. int alive_process_count = 1;
  148. MonotonicTime last_status_time = TimeManagement::the().monotonic_time();
  149. while (alive_process_count > 0) {
  150. Scheduler::yield();
  151. alive_process_count = 0;
  152. Process::all_instances().for_each([&](Process& process) {
  153. if (!process.is_kernel_process() && !process.is_dead())
  154. alive_process_count++;
  155. });
  156. if (TimeManagement::the().monotonic_time() - last_status_time > Duration::from_seconds(2)) {
  157. last_status_time = TimeManagement::the().monotonic_time();
  158. dmesgln("Waiting on {} processes to exit...", alive_process_count);
  159. if constexpr (PROCESS_DEBUG) {
  160. Process::all_instances().for_each_const([&](Process const& process) {
  161. if (!process.is_kernel_process() && !process.is_dead()) {
  162. dbgln("Process (user) {:2} dead={} dying={} ({})",
  163. process.pid(), process.is_dead(), process.is_dying(),
  164. process.name().with([](auto& name) { return name.representable_view(); }));
  165. }
  166. });
  167. }
  168. }
  169. }
  170. return {};
  171. }
  172. }