summaryrefslogtreecommitdiffstats
path: root/src/core/hle/kernel/kernel.h
blob: 850436eb3ecf236108bc609698c95aa547587280 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
// Copyright 2021 yuzu Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.

#pragma once

#include <array>
#include <memory>
#include <string>
#include <unordered_map>
#include <vector>
#include "core/arm/cpu_interrupt_handler.h"
#include "core/hardware_properties.h"
#include "core/hle/kernel/k_auto_object.h"
#include "core/hle/kernel/k_slab_heap.h"
#include "core/hle/kernel/memory_types.h"
#include "core/hle/kernel/object.h"

namespace Core {
class CPUInterruptHandler;
class ExclusiveMonitor;
class System;
} // namespace Core

namespace Core::Timing {
class CoreTiming;
struct EventType;
} // namespace Core::Timing

namespace Kernel {

class ClientPort;
class GlobalSchedulerContext;
class HandleTable;
class KAutoObjectWithListContainer;
class KEvent;
class KLinkedListNode;
class KMemoryManager;
class KResourceLimit;
class KScheduler;
class KSharedMemory;
class KThread;
class KWritableEvent;
class PhysicalCore;
class Process;
class ServiceThread;
class Synchronization;
class TimeManager;

template <typename T>
class KSlabHeap;

using EmuThreadHandle = uintptr_t;
constexpr EmuThreadHandle EmuThreadHandleInvalid{};
constexpr EmuThreadHandle EmuThreadHandleReserved{1ULL << 63};

/// Represents a single instance of the kernel.
class KernelCore {
private:
    using NamedPortTable = std::unordered_map<std::string, std::shared_ptr<ClientPort>>;

public:
    /// Constructs an instance of the kernel using the given System
    /// instance as a context for any necessary system-related state,
    /// such as threads, CPU core state, etc.
    ///
    /// @post After execution of the constructor, the provided System
    ///       object *must* outlive the kernel instance itself.
    ///
    explicit KernelCore(Core::System& system);
    ~KernelCore();

    KernelCore(const KernelCore&) = delete;
    KernelCore& operator=(const KernelCore&) = delete;

    KernelCore(KernelCore&&) = delete;
    KernelCore& operator=(KernelCore&&) = delete;

    /// Sets if emulation is multicore or single core, must be set before Initialize
    void SetMulticore(bool is_multicore);

    /// Resets the kernel to a clean slate for use.
    void Initialize();

    /// Initializes the CPU cores.
    void InitializeCores();

    /// Clears all resources in use by the kernel instance.
    void Shutdown();

    /// Retrieves a shared pointer to the system resource limit instance.
    std::shared_ptr<KResourceLimit> GetSystemResourceLimit() const;

    /// Retrieves a shared pointer to a Thread instance within the thread wakeup handle table.
    KScopedAutoObject<KThread> RetrieveThreadFromGlobalHandleTable(Handle handle) const;

    /// Adds the given shared pointer to an internal list of active processes.
    void AppendNewProcess(Process* process);

    /// Makes the given process the new current process.
    void MakeCurrentProcess(Process* process);

    /// Retrieves a pointer to the current process.
    Process* CurrentProcess();

    /// Retrieves a const pointer to the current process.
    const Process* CurrentProcess() const;

    /// Retrieves the list of processes.
    const std::vector<Process*>& GetProcessList() const;

    /// Gets the sole instance of the global scheduler
    Kernel::GlobalSchedulerContext& GlobalSchedulerContext();

    /// Gets the sole instance of the global scheduler
    const Kernel::GlobalSchedulerContext& GlobalSchedulerContext() const;

    /// Gets the sole instance of the Scheduler assoviated with cpu core 'id'
    Kernel::KScheduler& Scheduler(std::size_t id);

    /// Gets the sole instance of the Scheduler assoviated with cpu core 'id'
    const Kernel::KScheduler& Scheduler(std::size_t id) const;

    /// Gets the an instance of the respective physical CPU core.
    Kernel::PhysicalCore& PhysicalCore(std::size_t id);

    /// Gets the an instance of the respective physical CPU core.
    const Kernel::PhysicalCore& PhysicalCore(std::size_t id) const;

    /// Gets the sole instance of the Scheduler at the current running core.
    Kernel::KScheduler* CurrentScheduler();

    /// Gets the an instance of the current physical CPU core.
    Kernel::PhysicalCore& CurrentPhysicalCore();

    /// Gets the an instance of the current physical CPU core.
    const Kernel::PhysicalCore& CurrentPhysicalCore() const;

    /// Gets the an instance of the TimeManager Interface.
    Kernel::TimeManager& TimeManager();

    /// Gets the an instance of the TimeManager Interface.
    const Kernel::TimeManager& TimeManager() const;

    /// Stops execution of 'id' core, in order to reschedule a new thread.
    void PrepareReschedule(std::size_t id);

    Core::ExclusiveMonitor& GetExclusiveMonitor();

    const Core::ExclusiveMonitor& GetExclusiveMonitor() const;

    KAutoObjectWithListContainer& ObjectListContainer();

    const KAutoObjectWithListContainer& ObjectListContainer() const;

    std::array<Core::CPUInterruptHandler, Core::Hardware::NUM_CPU_CORES>& Interrupts();

    const std::array<Core::CPUInterruptHandler, Core::Hardware::NUM_CPU_CORES>& Interrupts() const;

    void InvalidateAllInstructionCaches();

    void InvalidateCpuInstructionCacheRange(VAddr addr, std::size_t size);

    /// Adds a port to the named port table
    void AddNamedPort(std::string name, std::shared_ptr<ClientPort> port);

    /// Finds a port within the named port table with the given name.
    NamedPortTable::iterator FindNamedPort(const std::string& name);

    /// Finds a port within the named port table with the given name.
    NamedPortTable::const_iterator FindNamedPort(const std::string& name) const;

    /// Determines whether or not the given port is a valid named port.
    bool IsValidNamedPort(NamedPortTable::const_iterator port) const;

    /// Gets the current host_thread/guest_thread pointer.
    KThread* GetCurrentEmuThread() const;

    /// Gets the current host_thread handle.
    u32 GetCurrentHostThreadID() const;

    /// Register the current thread as a CPU Core Thread.
    void RegisterCoreThread(std::size_t core_id);

    /// Register the current thread as a non CPU core thread.
    void RegisterHostThread();

    /// Gets the virtual memory manager for the kernel.
    KMemoryManager& MemoryManager();

    /// Gets the virtual memory manager for the kernel.
    const KMemoryManager& MemoryManager() const;

    /// Gets the slab heap allocated for user space pages.
    KSlabHeap<Page>& GetUserSlabHeapPages();

    /// Gets the slab heap allocated for user space pages.
    const KSlabHeap<Page>& GetUserSlabHeapPages() const;

    /// Gets the shared memory object for HID services.
    Kernel::KSharedMemory& GetHidSharedMem();

    /// Gets the shared memory object for HID services.
    const Kernel::KSharedMemory& GetHidSharedMem() const;

    /// Gets the shared memory object for font services.
    Kernel::KSharedMemory& GetFontSharedMem();

    /// Gets the shared memory object for font services.
    const Kernel::KSharedMemory& GetFontSharedMem() const;

    /// Gets the shared memory object for IRS services.
    Kernel::KSharedMemory& GetIrsSharedMem();

    /// Gets the shared memory object for IRS services.
    const Kernel::KSharedMemory& GetIrsSharedMem() const;

    /// Gets the shared memory object for Time services.
    Kernel::KSharedMemory& GetTimeSharedMem();

    /// Gets the shared memory object for Time services.
    const Kernel::KSharedMemory& GetTimeSharedMem() const;

    /// Suspend/unsuspend the OS.
    void Suspend(bool in_suspention);

    /// Exceptional exit the OS.
    void ExceptionalExit();

    bool IsMulticore() const;

    void EnterSVCProfile();

    void ExitSVCProfile();

    /**
     * Creates an HLE service thread, which are used to execute service routines asynchronously.
     * While these are allocated per ServerSession, these need to be owned and managed outside
     * of ServerSession to avoid a circular dependency.
     * @param name String name for the ServerSession creating this thread, used for debug
     * purposes.
     * @returns The a weak pointer newly created service thread.
     */
    std::weak_ptr<Kernel::ServiceThread> CreateServiceThread(const std::string& name);

    /**
     * Releases a HLE service thread, instructing KernelCore to free it. This should be called when
     * the ServerSession associated with the thread is destroyed.
     * @param service_thread Service thread to release.
     */
    void ReleaseServiceThread(std::weak_ptr<Kernel::ServiceThread> service_thread);

    /// Workaround for single-core mode when preempting threads while idle.
    bool IsPhantomModeForSingleCore() const;
    void SetIsPhantomModeForSingleCore(bool value);

    Core::System& System();
    const Core::System& System() const;

    /// Gets the slab heap for the specified kernel object type.
    template <typename T>
    KSlabHeap<T>& SlabHeap() {
        if constexpr (std::is_same_v<T, Process>) {
            return slab_heap_container->process;
        } else if constexpr (std::is_same_v<T, KThread>) {
            return slab_heap_container->thread;
        } else if constexpr (std::is_same_v<T, KEvent>) {
            return slab_heap_container->event;
        } else if constexpr (std::is_same_v<T, KSharedMemory>) {
            return slab_heap_container->shared_memory;
        } else if constexpr (std::is_same_v<T, KLinkedListNode>) {
            return slab_heap_container->linked_list_node;
        } else if constexpr (std::is_same_v<T, KWritableEvent>) {
            return slab_heap_container->writeable_event;
        }
    }

private:
    friend class Object;
    friend class Process;
    friend class KThread;

    /// Creates a new object ID, incrementing the internal object ID counter.
    u32 CreateNewObjectID();

    /// Creates a new process ID, incrementing the internal process ID counter;
    u64 CreateNewKernelProcessID();

    /// Creates a new process ID, incrementing the internal process ID counter;
    u64 CreateNewUserProcessID();

    /// Creates a new thread ID, incrementing the internal thread ID counter.
    u64 CreateNewThreadID();

    /// Provides a reference to the global handle table.
    Kernel::HandleTable& GlobalHandleTable();

    /// Provides a const reference to the global handle table.
    const Kernel::HandleTable& GlobalHandleTable() const;

    struct Impl;
    std::unique_ptr<Impl> impl;

    bool exception_exited{};

private:
    /// Helper to encapsulate all slab heaps in a single heap allocated container
    struct SlabHeapContainer {
        KSlabHeap<Process> process;
        KSlabHeap<KThread> thread;
        KSlabHeap<KEvent> event;
        KSlabHeap<KSharedMemory> shared_memory;
        KSlabHeap<KLinkedListNode> linked_list_node;
        KSlabHeap<KWritableEvent> writeable_event;
    };

    std::unique_ptr<SlabHeapContainer> slab_heap_container;
};

} // namespace Kernel