1 // Copyright 2014 Citra Emulator Project / PPSSPP Project 2 // Licensed under GPLv2 or any later version 3 // Refer to the license.txt file included. 4 5 #pragma once 6 7 #include <array> 8 #include <atomic> 9 #include <functional> 10 #include <memory> 11 #include <string> 12 #include <unordered_map> 13 #include <vector> 14 #include "common/common_types.h" 15 #include "core/hle/kernel/memory.h" 16 #include "core/hle/result.h" 17 #include "core/memory.h" 18 19 namespace ConfigMem { 20 class Handler; 21 } 22 23 namespace SharedPage { 24 class Handler; 25 } 26 27 namespace Memory { 28 class MemorySystem; 29 } 30 31 namespace Core { 32 class Timing; 33 } 34 35 namespace IPCDebugger { 36 class Recorder; 37 } 38 39 namespace Kernel { 40 41 class AddressArbiter; 42 class Event; 43 class Mutex; 44 class CodeSet; 45 class Process; 46 class Thread; 47 class Semaphore; 48 class Timer; 49 class ClientPort; 50 class ServerPort; 51 class ClientSession; 52 class ServerSession; 53 class ResourceLimitList; 54 class SharedMemory; 55 class ThreadManager; 56 class TimerManager; 57 class VMManager; 58 struct AddressMapping; 59 60 enum class ResetType { 61 OneShot, 62 Sticky, 63 Pulse, 64 }; 65 66 /// Permissions for mapped shared memory blocks 67 enum class MemoryPermission : u32 { 68 None = 0, 69 Read = (1u << 0), 70 Write = (1u << 1), 71 ReadWrite = (Read | Write), 72 Execute = (1u << 2), 73 ReadExecute = (Read | Execute), 74 WriteExecute = (Write | Execute), 75 ReadWriteExecute = (Read | Write | Execute), 76 DontCare = (1u << 28) 77 }; 78 79 enum class MemoryRegion : u16 { 80 APPLICATION = 1, 81 SYSTEM = 2, 82 BASE = 3, 83 }; 84 85 class KernelSystem { 86 public: 87 explicit KernelSystem(Memory::MemorySystem& memory, Core::Timing& timing, 88 std::function<void()> prepare_reschedule_callback, u32 system_mode, 89 u32 num_cores, u8 n3ds_mode); 90 ~KernelSystem(); 91 92 using PortPair = std::pair<std::shared_ptr<ServerPort>, std::shared_ptr<ClientPort>>; 93 using SessionPair = std::pair<std::shared_ptr<ServerSession>, std::shared_ptr<ClientSession>>; 94 95 /** 96 * Creates an address arbiter. 97 * 98 * @param name Optional name used for debugging. 99 * @returns The created AddressArbiter. 100 */ 101 std::shared_ptr<AddressArbiter> CreateAddressArbiter(std::string name = "Unknown"); 102 103 /** 104 * Creates an event 105 * @param reset_type ResetType describing how to create event 106 * @param name Optional name of event 107 */ 108 std::shared_ptr<Event> CreateEvent(ResetType reset_type, std::string name = "Unknown"); 109 110 /** 111 * Creates a mutex. 112 * @param initial_locked Specifies if the mutex should be locked initially 113 * @param name Optional name of mutex 114 * @return Pointer to new Mutex object 115 */ 116 std::shared_ptr<Mutex> CreateMutex(bool initial_locked, std::string name = "Unknown"); 117 118 std::shared_ptr<CodeSet> CreateCodeSet(std::string name, u64 program_id); 119 120 std::shared_ptr<Process> CreateProcess(std::shared_ptr<CodeSet> code_set); 121 122 /** 123 * Creates and returns a new thread. The new thread is immediately scheduled 124 * @param name The friendly name desired for the thread 125 * @param entry_point The address at which the thread should start execution 126 * @param priority The thread's priority 127 * @param arg User data to pass to the thread 128 * @param processor_id The ID(s) of the processors on which the thread is desired to be run 129 * @param stack_top The address of the thread's stack top 130 * @param owner_process The parent process for the thread 131 * @return A shared pointer to the newly created thread 132 */ 133 ResultVal<std::shared_ptr<Thread>> CreateThread(std::string name, VAddr entry_point, 134 u32 priority, u32 arg, s32 processor_id, 135 VAddr stack_top, 136 std::shared_ptr<Process> owner_process); 137 138 /** 139 * Creates a semaphore. 140 * @param initial_count Number of slots reserved for other threads 141 * @param max_count Maximum number of slots the semaphore can have 142 * @param name Optional name of semaphore 143 * @return The created semaphore 144 */ 145 ResultVal<std::shared_ptr<Semaphore>> CreateSemaphore(s32 initial_count, s32 max_count, 146 std::string name = "Unknown"); 147 148 /** 149 * Creates a timer 150 * @param reset_type ResetType describing how to create the timer 151 * @param name Optional name of timer 152 * @return The created Timer 153 */ 154 std::shared_ptr<Timer> CreateTimer(ResetType reset_type, std::string name = "Unknown"); 155 156 /** 157 * Creates a pair of ServerPort and an associated ClientPort. 158 * 159 * @param max_sessions Maximum number of sessions to the port 160 * @param name Optional name of the ports 161 * @return The created port tuple 162 */ 163 PortPair CreatePortPair(u32 max_sessions, std::string name = "UnknownPort"); 164 165 /** 166 * Creates a pair of ServerSession and an associated ClientSession. 167 * @param name Optional name of the ports. 168 * @param client_port Optional The ClientPort that spawned this session. 169 * @return The created session tuple 170 */ 171 SessionPair CreateSessionPair(const std::string& name = "Unknown", 172 std::shared_ptr<ClientPort> client_port = nullptr); 173 174 ResourceLimitList& ResourceLimit(); 175 const ResourceLimitList& ResourceLimit() const; 176 177 /** 178 * Creates a shared memory object. 179 * @param owner_process Process that created this shared memory object. 180 * @param size Size of the memory block. Must be page-aligned. 181 * @param permissions Permission restrictions applied to the process which created the block. 182 * @param other_permissions Permission restrictions applied to other processes mapping the 183 * block. 184 * @param address The address from which to map the Shared Memory. 185 * @param region If the address is 0, the shared memory will be allocated in this region of the 186 * linear heap. 187 * @param name Optional object name, used for debugging purposes. 188 */ 189 ResultVal<std::shared_ptr<SharedMemory>> CreateSharedMemory( 190 Process* owner_process, u32 size, MemoryPermission permissions, 191 MemoryPermission other_permissions, VAddr address = 0, 192 MemoryRegion region = MemoryRegion::BASE, std::string name = "Unknown"); 193 194 /** 195 * Creates a shared memory object from a block of memory managed by an HLE applet. 196 * @param offset The offset into the heap block that the SharedMemory will map. 197 * @param size Size of the memory block. Must be page-aligned. 198 * @param permissions Permission restrictions applied to the process which created the block. 199 * @param other_permissions Permission restrictions applied to other processes mapping the 200 * block. 201 * @param name Optional object name, used for debugging purposes. 202 */ 203 std::shared_ptr<SharedMemory> CreateSharedMemoryForApplet(u32 offset, u32 size, 204 MemoryPermission permissions, 205 MemoryPermission other_permissions, 206 std::string name = "Unknown Applet"); 207 208 u32 GenerateObjectID(); 209 210 /// Retrieves a process from the current list of processes. 211 std::shared_ptr<Process> GetProcessById(u32 process_id) const; 212 213 std::shared_ptr<Process> GetCurrentProcess() const; 214 void SetCurrentProcess(std::shared_ptr<Process> process); 215 void SetCurrentProcessForCPU(std::shared_ptr<Process> process, u32 core_id); 216 217 void SetCurrentMemoryPageTable(std::shared_ptr<Memory::PageTable> page_table); 218 219 void SetCPUs(std::vector<std::shared_ptr<ARM_Interface>> cpu); 220 221 void SetRunningCPU(ARM_Interface* cpu); 222 223 ThreadManager& GetThreadManager(u32 core_id); 224 const ThreadManager& GetThreadManager(u32 core_id) const; 225 226 ThreadManager& GetCurrentThreadManager(); 227 const ThreadManager& GetCurrentThreadManager() const; 228 229 TimerManager& GetTimerManager(); 230 const TimerManager& GetTimerManager() const; 231 232 void MapSharedPages(VMManager& address_space); 233 234 SharedPage::Handler& GetSharedPageHandler(); 235 const SharedPage::Handler& GetSharedPageHandler() const; 236 237 IPCDebugger::Recorder& GetIPCRecorder(); 238 const IPCDebugger::Recorder& GetIPCRecorder() const; 239 240 std::shared_ptr<MemoryRegionInfo> GetMemoryRegion(MemoryRegion region); 241 242 void HandleSpecialMapping(VMManager& address_space, const AddressMapping& mapping); 243 244 std::array<std::shared_ptr<MemoryRegionInfo>, 3> memory_regions{}; 245 246 /// Adds a port to the named port table 247 void AddNamedPort(std::string name, std::shared_ptr<ClientPort> port); 248 PrepareReschedule()249 void PrepareReschedule() { 250 prepare_reschedule_callback(); 251 } 252 253 u32 NewThreadId(); 254 255 void ResetThreadIDs(); 256 257 /// Map of named ports managed by the kernel, which can be retrieved using the ConnectToPort 258 std::unordered_map<std::string, std::shared_ptr<ClientPort>> named_ports; 259 260 ARM_Interface* current_cpu = nullptr; 261 262 Memory::MemorySystem& memory; 263 264 Core::Timing& timing; 265 266 private: 267 void MemoryInit(u32 mem_type, u8 n3ds_mode); 268 269 std::function<void()> prepare_reschedule_callback; 270 271 std::unique_ptr<ResourceLimitList> resource_limits; 272 std::atomic<u32> next_object_id{0}; 273 274 // Note: keep the member order below in order to perform correct destruction. 275 // Thread manager is destructed before process list in order to Stop threads and clear thread 276 // info from their parent processes first. Timer manager is destructed after process list 277 // because timers are destructed along with process list and they need to clear info from the 278 // timer manager. 279 // TODO (wwylele): refactor the cleanup sequence to make this less complicated and sensitive. 280 281 std::unique_ptr<TimerManager> timer_manager; 282 283 // TODO(Subv): Start the process ids from 10 for now, as lower PIDs are 284 // reserved for low-level services 285 u32 next_process_id = 10; 286 287 // Lists all processes that exist in the current session. 288 std::vector<std::shared_ptr<Process>> process_list; 289 290 std::shared_ptr<Process> current_process; 291 std::vector<std::shared_ptr<Process>> stored_processes; 292 293 std::vector<std::unique_ptr<ThreadManager>> thread_managers; 294 295 std::shared_ptr<ConfigMem::Handler> config_mem_handler; 296 std::shared_ptr<SharedPage::Handler> shared_page_handler; 297 298 std::unique_ptr<IPCDebugger::Recorder> ipc_recorder; 299 300 u32 next_thread_id; 301 302 friend class boost::serialization::access; 303 template <class Archive> 304 void serialize(Archive& ar, const unsigned int file_version); 305 }; 306 307 } // namespace Kernel 308