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