core.h 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298
  1. // Copyright 2014 Citra Emulator Project
  2. // Licensed under GPLv2 or any later version
  3. // Refer to the license.txt file included.
  4. #pragma once
  5. #include <array>
  6. #include <map>
  7. #include <memory>
  8. #include <string>
  9. #include <thread>
  10. #include "common/common_types.h"
  11. #include "core/arm/exclusive_monitor.h"
  12. #include "core/core_cpu.h"
  13. #include "core/hle/kernel/kernel.h"
  14. #include "core/hle/kernel/object.h"
  15. #include "core/hle/kernel/scheduler.h"
  16. #include "core/loader/loader.h"
  17. #include "core/memory.h"
  18. #include "core/perf_stats.h"
  19. #include "core/telemetry_session.h"
  20. #include "file_sys/vfs_real.h"
  21. #include "hle/service/filesystem/filesystem.h"
  22. #include "video_core/debug_utils/debug_utils.h"
  23. #include "video_core/gpu.h"
  24. namespace Core::Frontend {
  25. class EmuWindow;
  26. }
  27. namespace Service::SM {
  28. class ServiceManager;
  29. }
  30. namespace VideoCore {
  31. class RendererBase;
  32. }
  33. namespace Core {
  34. class ARM_Interface;
  35. class System {
  36. public:
  37. System(const System&) = delete;
  38. System& operator=(const System&) = delete;
  39. System(System&&) = delete;
  40. System& operator=(System&&) = delete;
  41. ~System();
  42. /**
  43. * Gets the instance of the System singleton class.
  44. * @returns Reference to the instance of the System singleton class.
  45. */
  46. static System& GetInstance() {
  47. return s_instance;
  48. }
  49. /// Enumeration representing the return values of the System Initialize and Load process.
  50. enum class ResultStatus : u32 {
  51. Success, ///< Succeeded
  52. ErrorNotInitialized, ///< Error trying to use core prior to initialization
  53. ErrorGetLoader, ///< Error finding the correct application loader
  54. ErrorSystemMode, ///< Error determining the system mode
  55. ErrorSystemFiles, ///< Error in finding system files
  56. ErrorSharedFont, ///< Error in finding shared font
  57. ErrorVideoCore, ///< Error in the video core
  58. ErrorUnknown, ///< Any other error
  59. ErrorLoader, ///< The base for loader errors (too many to repeat)
  60. };
  61. /**
  62. * Run the core CPU loop
  63. * This function runs the core for the specified number of CPU instructions before trying to
  64. * update hardware. This is much faster than SingleStep (and should be equivalent), as the CPU
  65. * is not required to do a full dispatch with each instruction. NOTE: the number of instructions
  66. * requested is not guaranteed to run, as this will be interrupted preemptively if a hardware
  67. * update is requested (e.g. on a thread switch).
  68. * @param tight_loop If false, the CPU single-steps.
  69. * @return Result status, indicating whether or not the operation succeeded.
  70. */
  71. ResultStatus RunLoop(bool tight_loop = true);
  72. /**
  73. * Step the CPU one instruction
  74. * @return Result status, indicating whether or not the operation succeeded.
  75. */
  76. ResultStatus SingleStep();
  77. /**
  78. * Invalidate the CPU instruction caches
  79. * This function should only be used by GDB Stub to support breakpoints, memory updates and
  80. * step/continue commands.
  81. */
  82. void InvalidateCpuInstructionCaches() {
  83. for (auto& cpu : cpu_cores) {
  84. cpu->ArmInterface().ClearInstructionCache();
  85. }
  86. }
  87. /// Shutdown the emulated system.
  88. void Shutdown();
  89. /**
  90. * Load an executable application.
  91. * @param emu_window Reference to the host-system window used for video output and keyboard
  92. * input.
  93. * @param filepath String path to the executable application to load on the host file system.
  94. * @returns ResultStatus code, indicating if the operation succeeded.
  95. */
  96. ResultStatus Load(Frontend::EmuWindow& emu_window, const std::string& filepath);
  97. /**
  98. * Indicates if the emulated system is powered on (all subsystems initialized and able to run an
  99. * application).
  100. * @returns True if the emulated system is powered on, otherwise false.
  101. */
  102. bool IsPoweredOn() const {
  103. return cpu_barrier && cpu_barrier->IsAlive();
  104. }
  105. /**
  106. * Returns a reference to the telemetry session for this emulation session.
  107. * @returns Reference to the telemetry session.
  108. */
  109. Core::TelemetrySession& TelemetrySession() const {
  110. return *telemetry_session;
  111. }
  112. /// Prepare the core emulation for a reschedule
  113. void PrepareReschedule();
  114. /// Gets and resets core performance statistics
  115. PerfStats::Results GetAndResetPerfStats();
  116. /// Gets an ARM interface to the CPU core that is currently running
  117. ARM_Interface& CurrentArmInterface() {
  118. return CurrentCpuCore().ArmInterface();
  119. }
  120. /// Gets the index of the currently running CPU core
  121. size_t CurrentCoreIndex() {
  122. return CurrentCpuCore().CoreIndex();
  123. }
  124. /// Gets an ARM interface to the CPU core with the specified index
  125. ARM_Interface& ArmInterface(size_t core_index);
  126. /// Gets a CPU interface to the CPU core with the specified index
  127. Cpu& CpuCore(size_t core_index);
  128. /// Gets a mutable reference to the GPU interface
  129. Tegra::GPU& GPU() {
  130. return *gpu_core;
  131. }
  132. /// Gets an immutable reference to the GPU interface.
  133. const Tegra::GPU& GPU() const {
  134. return *gpu_core;
  135. }
  136. /// Gets a mutable reference to the renderer.
  137. VideoCore::RendererBase& Renderer() {
  138. return *renderer;
  139. }
  140. /// Gets an immutable reference to the renderer.
  141. const VideoCore::RendererBase& Renderer() const {
  142. return *renderer;
  143. }
  144. /// Gets the scheduler for the CPU core that is currently running
  145. Kernel::Scheduler& CurrentScheduler() {
  146. return *CurrentCpuCore().Scheduler();
  147. }
  148. /// Gets the exclusive monitor
  149. ExclusiveMonitor& Monitor() {
  150. return *cpu_exclusive_monitor;
  151. }
  152. /// Gets the scheduler for the CPU core with the specified index
  153. const std::shared_ptr<Kernel::Scheduler>& Scheduler(size_t core_index);
  154. /// Gets the current process
  155. Kernel::SharedPtr<Kernel::Process>& CurrentProcess() {
  156. return current_process;
  157. }
  158. /// Provides a reference to the kernel instance.
  159. Kernel::KernelCore& Kernel();
  160. /// Provides a constant reference to the kernel instance.
  161. const Kernel::KernelCore& Kernel() const;
  162. /// Gets the name of the current game
  163. Loader::ResultStatus GetGameName(std::string& out) const {
  164. if (app_loader == nullptr)
  165. return Loader::ResultStatus::ErrorNotInitialized;
  166. return app_loader->ReadTitle(out);
  167. }
  168. PerfStats perf_stats;
  169. FrameLimiter frame_limiter;
  170. void SetStatus(ResultStatus new_status, const char* details = nullptr) {
  171. status = new_status;
  172. if (details) {
  173. status_details = details;
  174. }
  175. }
  176. const std::string& GetStatusDetails() const {
  177. return status_details;
  178. }
  179. Loader::AppLoader& GetAppLoader() const {
  180. return *app_loader;
  181. }
  182. Service::SM::ServiceManager& ServiceManager();
  183. const Service::SM::ServiceManager& ServiceManager() const;
  184. void SetGPUDebugContext(std::shared_ptr<Tegra::DebugContext> context) {
  185. debug_context = std::move(context);
  186. }
  187. std::shared_ptr<Tegra::DebugContext> GetGPUDebugContext() const {
  188. return debug_context;
  189. }
  190. void SetFilesystem(FileSys::VirtualFilesystem vfs) {
  191. virtual_filesystem = std::move(vfs);
  192. }
  193. FileSys::VirtualFilesystem GetFilesystem() const {
  194. return virtual_filesystem;
  195. }
  196. private:
  197. System();
  198. /// Returns the currently running CPU core
  199. Cpu& CurrentCpuCore();
  200. /**
  201. * Initialize the emulated system.
  202. * @param emu_window Reference to the host-system window used for video output and keyboard
  203. * input.
  204. * @return ResultStatus code, indicating if the operation succeeded.
  205. */
  206. ResultStatus Init(Frontend::EmuWindow& emu_window);
  207. Kernel::KernelCore kernel;
  208. /// RealVfsFilesystem instance
  209. FileSys::VirtualFilesystem virtual_filesystem;
  210. /// AppLoader used to load the current executing application
  211. std::unique_ptr<Loader::AppLoader> app_loader;
  212. std::unique_ptr<VideoCore::RendererBase> renderer;
  213. std::unique_ptr<Tegra::GPU> gpu_core;
  214. std::shared_ptr<Tegra::DebugContext> debug_context;
  215. Kernel::SharedPtr<Kernel::Process> current_process;
  216. std::shared_ptr<ExclusiveMonitor> cpu_exclusive_monitor;
  217. std::shared_ptr<CpuBarrier> cpu_barrier;
  218. std::array<std::shared_ptr<Cpu>, NUM_CPU_CORES> cpu_cores;
  219. std::array<std::unique_ptr<std::thread>, NUM_CPU_CORES - 1> cpu_core_threads;
  220. size_t active_core{}; ///< Active core, only used in single thread mode
  221. /// Service manager
  222. std::shared_ptr<Service::SM::ServiceManager> service_manager;
  223. /// Telemetry session for this emulation session
  224. std::unique_ptr<Core::TelemetrySession> telemetry_session;
  225. static System s_instance;
  226. ResultStatus status = ResultStatus::Success;
  227. std::string status_details = "";
  228. /// Map of guest threads to CPU cores
  229. std::map<std::thread::id, std::shared_ptr<Cpu>> thread_to_cpu;
  230. };
  231. inline ARM_Interface& CurrentArmInterface() {
  232. return System::GetInstance().CurrentArmInterface();
  233. }
  234. inline TelemetrySession& Telemetry() {
  235. return System::GetInstance().TelemetrySession();
  236. }
  237. inline Kernel::SharedPtr<Kernel::Process>& CurrentProcess() {
  238. return System::GetInstance().CurrentProcess();
  239. }
  240. } // namespace Core