2014-05-10 03:11:18 +01:00
|
|
|
// Copyright 2014 Citra Emulator Project / PPSSPP Project
|
2014-12-17 05:38:14 +00:00
|
|
|
// Licensed under GPLv2 or any later version
|
2014-11-19 08:49:13 +00:00
|
|
|
// Refer to the license.txt file included.
|
2014-05-10 03:11:18 +01:00
|
|
|
|
|
|
|
#pragma once
|
|
|
|
|
2018-10-26 02:07:15 +01:00
|
|
|
#include <array>
|
2018-10-13 22:24:51 +01:00
|
|
|
#include <atomic>
|
2019-02-01 17:19:20 +00:00
|
|
|
#include <functional>
|
2018-10-13 21:41:34 +01:00
|
|
|
#include <memory>
|
2018-10-11 20:19:45 +01:00
|
|
|
#include <string>
|
2018-10-26 15:27:13 +01:00
|
|
|
#include <unordered_map>
|
2018-10-17 19:06:47 +01:00
|
|
|
#include <vector>
|
2015-05-06 08:06:12 +01:00
|
|
|
#include "common/common_types.h"
|
2018-10-26 02:07:15 +01:00
|
|
|
#include "core/hle/kernel/memory.h"
|
2018-10-12 20:47:06 +01:00
|
|
|
#include "core/hle/result.h"
|
2019-06-25 23:39:11 +01:00
|
|
|
#include "core/memory.h"
|
2014-05-10 03:11:18 +01:00
|
|
|
|
2018-10-25 15:51:00 +01:00
|
|
|
namespace ConfigMem {
|
|
|
|
class Handler;
|
|
|
|
}
|
|
|
|
|
2018-10-25 16:23:52 +01:00
|
|
|
namespace SharedPage {
|
|
|
|
class Handler;
|
|
|
|
}
|
|
|
|
|
2018-11-21 03:48:19 +00:00
|
|
|
namespace Memory {
|
|
|
|
class MemorySystem;
|
|
|
|
}
|
|
|
|
|
2019-02-01 16:54:52 +00:00
|
|
|
namespace Core {
|
|
|
|
class Timing;
|
|
|
|
}
|
|
|
|
|
2019-07-22 13:10:47 +01:00
|
|
|
namespace IPCDebugger {
|
|
|
|
class Recorder;
|
|
|
|
}
|
|
|
|
|
2014-05-20 23:13:25 +01:00
|
|
|
namespace Kernel {
|
|
|
|
|
2018-10-11 20:19:45 +01:00
|
|
|
class AddressArbiter;
|
2018-10-11 20:48:16 +01:00
|
|
|
class Event;
|
2018-10-11 21:00:09 +01:00
|
|
|
class Mutex;
|
2018-10-12 20:21:32 +01:00
|
|
|
class CodeSet;
|
2018-10-12 20:33:36 +01:00
|
|
|
class Process;
|
2018-10-12 20:47:06 +01:00
|
|
|
class Thread;
|
2018-10-12 21:12:08 +01:00
|
|
|
class Semaphore;
|
2018-10-12 21:26:23 +01:00
|
|
|
class Timer;
|
2018-10-13 00:00:16 +01:00
|
|
|
class ClientPort;
|
|
|
|
class ServerPort;
|
2018-10-13 21:11:20 +01:00
|
|
|
class ClientSession;
|
|
|
|
class ServerSession;
|
2018-10-13 21:41:34 +01:00
|
|
|
class ResourceLimitList;
|
2018-10-13 22:08:37 +01:00
|
|
|
class SharedMemory;
|
2018-10-23 14:57:59 +01:00
|
|
|
class ThreadManager;
|
2018-10-23 19:17:30 +01:00
|
|
|
class TimerManager;
|
2018-10-25 15:51:00 +01:00
|
|
|
class VMManager;
|
2018-11-21 17:01:19 +00:00
|
|
|
struct AddressMapping;
|
2018-10-11 20:48:16 +01:00
|
|
|
|
|
|
|
enum class ResetType {
|
|
|
|
OneShot,
|
|
|
|
Sticky,
|
|
|
|
Pulse,
|
|
|
|
};
|
2018-10-11 20:19:45 +01:00
|
|
|
|
2018-10-13 22:08:37 +01:00
|
|
|
/// Permissions for mapped shared memory blocks
|
|
|
|
enum class MemoryPermission : u32 {
|
|
|
|
None = 0,
|
|
|
|
Read = (1u << 0),
|
|
|
|
Write = (1u << 1),
|
|
|
|
ReadWrite = (Read | Write),
|
|
|
|
Execute = (1u << 2),
|
|
|
|
ReadExecute = (Read | Execute),
|
|
|
|
WriteExecute = (Write | Execute),
|
|
|
|
ReadWriteExecute = (Read | Write | Execute),
|
|
|
|
DontCare = (1u << 28)
|
|
|
|
};
|
|
|
|
|
|
|
|
enum class MemoryRegion : u16 {
|
|
|
|
APPLICATION = 1,
|
|
|
|
SYSTEM = 2,
|
|
|
|
BASE = 3,
|
|
|
|
};
|
|
|
|
|
2022-12-11 08:08:58 +00:00
|
|
|
union CoreVersion {
|
|
|
|
CoreVersion(u32 version) : raw(version) {}
|
|
|
|
CoreVersion(u32 major_ver, u32 minor_ver, u32 revision_ver) {
|
|
|
|
revision.Assign(revision_ver);
|
|
|
|
minor.Assign(minor_ver);
|
|
|
|
major.Assign(major_ver);
|
|
|
|
}
|
|
|
|
|
|
|
|
u32 raw;
|
|
|
|
BitField<8, 8, u32> revision;
|
|
|
|
BitField<16, 8, u32> minor;
|
|
|
|
BitField<24, 8, u32> major;
|
|
|
|
};
|
|
|
|
|
2018-10-11 19:49:52 +01:00
|
|
|
class KernelSystem {
|
|
|
|
public:
|
2019-02-01 17:19:20 +00:00
|
|
|
explicit KernelSystem(Memory::MemorySystem& memory, Core::Timing& timing,
|
2020-02-21 18:31:32 +00:00
|
|
|
std::function<void()> prepare_reschedule_callback, u32 system_mode,
|
2020-02-29 18:48:27 +00:00
|
|
|
u32 num_cores, u8 n3ds_mode);
|
2018-10-11 19:49:52 +01:00
|
|
|
~KernelSystem();
|
2018-10-11 20:19:45 +01:00
|
|
|
|
2019-04-06 06:41:43 +01:00
|
|
|
using PortPair = std::pair<std::shared_ptr<ServerPort>, std::shared_ptr<ClientPort>>;
|
|
|
|
using SessionPair = std::pair<std::shared_ptr<ServerSession>, std::shared_ptr<ClientSession>>;
|
2019-04-06 06:36:50 +01:00
|
|
|
|
2018-10-11 20:19:45 +01:00
|
|
|
/**
|
|
|
|
* Creates an address arbiter.
|
|
|
|
*
|
|
|
|
* @param name Optional name used for debugging.
|
|
|
|
* @returns The created AddressArbiter.
|
|
|
|
*/
|
2019-03-23 20:04:19 +00:00
|
|
|
std::shared_ptr<AddressArbiter> CreateAddressArbiter(std::string name = "Unknown");
|
2018-10-11 20:48:16 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Creates an event
|
|
|
|
* @param reset_type ResetType describing how to create event
|
|
|
|
* @param name Optional name of event
|
|
|
|
*/
|
2019-03-23 20:04:19 +00:00
|
|
|
std::shared_ptr<Event> CreateEvent(ResetType reset_type, std::string name = "Unknown");
|
2018-10-11 21:00:09 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Creates a mutex.
|
|
|
|
* @param initial_locked Specifies if the mutex should be locked initially
|
|
|
|
* @param name Optional name of mutex
|
|
|
|
* @return Pointer to new Mutex object
|
|
|
|
*/
|
2019-03-23 20:04:19 +00:00
|
|
|
std::shared_ptr<Mutex> CreateMutex(bool initial_locked, std::string name = "Unknown");
|
2018-10-12 20:21:32 +01:00
|
|
|
|
2019-03-23 20:04:19 +00:00
|
|
|
std::shared_ptr<CodeSet> CreateCodeSet(std::string name, u64 program_id);
|
2018-10-12 20:33:36 +01:00
|
|
|
|
2019-03-23 20:04:19 +00:00
|
|
|
std::shared_ptr<Process> CreateProcess(std::shared_ptr<CodeSet> code_set);
|
2018-10-12 20:47:06 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Creates and returns a new thread. The new thread is immediately scheduled
|
|
|
|
* @param name The friendly name desired for the thread
|
|
|
|
* @param entry_point The address at which the thread should start execution
|
|
|
|
* @param priority The thread's priority
|
|
|
|
* @param arg User data to pass to the thread
|
|
|
|
* @param processor_id The ID(s) of the processors on which the thread is desired to be run
|
|
|
|
* @param stack_top The address of the thread's stack top
|
|
|
|
* @param owner_process The parent process for the thread
|
|
|
|
* @return A shared pointer to the newly created thread
|
|
|
|
*/
|
2019-03-23 20:04:19 +00:00
|
|
|
ResultVal<std::shared_ptr<Thread>> CreateThread(std::string name, VAddr entry_point,
|
|
|
|
u32 priority, u32 arg, s32 processor_id,
|
2020-01-12 00:24:44 +00:00
|
|
|
VAddr stack_top,
|
|
|
|
std::shared_ptr<Process> owner_process);
|
2018-10-12 21:12:08 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Creates a semaphore.
|
|
|
|
* @param initial_count Number of slots reserved for other threads
|
|
|
|
* @param max_count Maximum number of slots the semaphore can have
|
|
|
|
* @param name Optional name of semaphore
|
|
|
|
* @return The created semaphore
|
|
|
|
*/
|
2019-03-23 20:04:19 +00:00
|
|
|
ResultVal<std::shared_ptr<Semaphore>> CreateSemaphore(s32 initial_count, s32 max_count,
|
|
|
|
std::string name = "Unknown");
|
2018-10-12 21:26:23 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Creates a timer
|
|
|
|
* @param reset_type ResetType describing how to create the timer
|
|
|
|
* @param name Optional name of timer
|
|
|
|
* @return The created Timer
|
|
|
|
*/
|
2019-03-23 20:04:19 +00:00
|
|
|
std::shared_ptr<Timer> CreateTimer(ResetType reset_type, std::string name = "Unknown");
|
2018-10-13 00:00:16 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Creates a pair of ServerPort and an associated ClientPort.
|
|
|
|
*
|
|
|
|
* @param max_sessions Maximum number of sessions to the port
|
|
|
|
* @param name Optional name of the ports
|
|
|
|
* @return The created port tuple
|
|
|
|
*/
|
2019-04-06 06:36:50 +01:00
|
|
|
PortPair CreatePortPair(u32 max_sessions, std::string name = "UnknownPort");
|
2018-10-13 21:11:20 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Creates a pair of ServerSession and an associated ClientSession.
|
|
|
|
* @param name Optional name of the ports.
|
|
|
|
* @param client_port Optional The ClientPort that spawned this session.
|
|
|
|
* @return The created session tuple
|
|
|
|
*/
|
2019-04-06 06:41:43 +01:00
|
|
|
SessionPair CreateSessionPair(const std::string& name = "Unknown",
|
|
|
|
std::shared_ptr<ClientPort> client_port = nullptr);
|
2018-10-13 21:41:34 +01:00
|
|
|
|
|
|
|
ResourceLimitList& ResourceLimit();
|
|
|
|
const ResourceLimitList& ResourceLimit() const;
|
|
|
|
|
2018-10-13 22:08:37 +01:00
|
|
|
/**
|
|
|
|
* Creates a shared memory object.
|
|
|
|
* @param owner_process Process that created this shared memory object.
|
|
|
|
* @param size Size of the memory block. Must be page-aligned.
|
|
|
|
* @param permissions Permission restrictions applied to the process which created the block.
|
|
|
|
* @param other_permissions Permission restrictions applied to other processes mapping the
|
|
|
|
* block.
|
|
|
|
* @param address The address from which to map the Shared Memory.
|
|
|
|
* @param region If the address is 0, the shared memory will be allocated in this region of the
|
|
|
|
* linear heap.
|
|
|
|
* @param name Optional object name, used for debugging purposes.
|
|
|
|
*/
|
2019-03-23 20:04:19 +00:00
|
|
|
ResultVal<std::shared_ptr<SharedMemory>> CreateSharedMemory(
|
|
|
|
Process* owner_process, u32 size, MemoryPermission permissions,
|
|
|
|
MemoryPermission other_permissions, VAddr address = 0,
|
|
|
|
MemoryRegion region = MemoryRegion::BASE, std::string name = "Unknown");
|
2018-10-13 22:08:37 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Creates a shared memory object from a block of memory managed by an HLE applet.
|
|
|
|
* @param offset The offset into the heap block that the SharedMemory will map.
|
|
|
|
* @param size Size of the memory block. Must be page-aligned.
|
|
|
|
* @param permissions Permission restrictions applied to the process which created the block.
|
|
|
|
* @param other_permissions Permission restrictions applied to other processes mapping the
|
|
|
|
* block.
|
|
|
|
* @param name Optional object name, used for debugging purposes.
|
|
|
|
*/
|
2019-03-23 20:04:19 +00:00
|
|
|
std::shared_ptr<SharedMemory> CreateSharedMemoryForApplet(u32 offset, u32 size,
|
|
|
|
MemoryPermission permissions,
|
|
|
|
MemoryPermission other_permissions,
|
|
|
|
std::string name = "Unknown Applet");
|
2018-10-13 22:08:37 +01:00
|
|
|
|
2018-10-13 22:24:51 +01:00
|
|
|
u32 GenerateObjectID();
|
|
|
|
|
2018-10-17 19:06:47 +01:00
|
|
|
/// Retrieves a process from the current list of processes.
|
2019-03-23 20:04:19 +00:00
|
|
|
std::shared_ptr<Process> GetProcessById(u32 process_id) const;
|
2018-10-17 19:06:47 +01:00
|
|
|
|
2019-03-23 20:04:19 +00:00
|
|
|
std::shared_ptr<Process> GetCurrentProcess() const;
|
|
|
|
void SetCurrentProcess(std::shared_ptr<Process> process);
|
2020-02-21 18:31:32 +00:00
|
|
|
void SetCurrentProcessForCPU(std::shared_ptr<Process> process, u32 core_id);
|
2018-10-17 20:23:56 +01:00
|
|
|
|
2020-01-05 16:35:01 +00:00
|
|
|
void SetCurrentMemoryPageTable(std::shared_ptr<Memory::PageTable> page_table);
|
2019-06-25 23:39:11 +01:00
|
|
|
|
2020-02-21 18:31:32 +00:00
|
|
|
void SetCPUs(std::vector<std::shared_ptr<ARM_Interface>> cpu);
|
2019-06-25 23:39:11 +01:00
|
|
|
|
2020-04-22 06:44:58 +01:00
|
|
|
void SetRunningCPU(ARM_Interface* cpu);
|
2020-02-21 18:31:32 +00:00
|
|
|
|
|
|
|
ThreadManager& GetThreadManager(u32 core_id);
|
|
|
|
const ThreadManager& GetThreadManager(u32 core_id) const;
|
|
|
|
|
|
|
|
ThreadManager& GetCurrentThreadManager();
|
|
|
|
const ThreadManager& GetCurrentThreadManager() const;
|
2018-10-23 14:57:59 +01:00
|
|
|
|
2018-10-23 19:17:30 +01:00
|
|
|
TimerManager& GetTimerManager();
|
|
|
|
const TimerManager& GetTimerManager() const;
|
|
|
|
|
2018-10-25 15:51:00 +01:00
|
|
|
void MapSharedPages(VMManager& address_space);
|
|
|
|
|
2018-10-25 16:23:52 +01:00
|
|
|
SharedPage::Handler& GetSharedPageHandler();
|
|
|
|
const SharedPage::Handler& GetSharedPageHandler() const;
|
|
|
|
|
2019-07-22 13:10:47 +01:00
|
|
|
IPCDebugger::Recorder& GetIPCRecorder();
|
|
|
|
const IPCDebugger::Recorder& GetIPCRecorder() const;
|
|
|
|
|
2020-01-12 00:24:44 +00:00
|
|
|
std::shared_ptr<MemoryRegionInfo> GetMemoryRegion(MemoryRegion region);
|
2018-10-26 02:07:15 +01:00
|
|
|
|
2018-11-21 17:01:19 +00:00
|
|
|
void HandleSpecialMapping(VMManager& address_space, const AddressMapping& mapping);
|
|
|
|
|
2020-01-12 00:24:44 +00:00
|
|
|
std::array<std::shared_ptr<MemoryRegionInfo>, 3> memory_regions{};
|
2018-10-26 02:07:15 +01:00
|
|
|
|
2018-10-26 15:27:13 +01:00
|
|
|
/// Adds a port to the named port table
|
2019-03-23 20:04:19 +00:00
|
|
|
void AddNamedPort(std::string name, std::shared_ptr<ClientPort> port);
|
2018-10-26 15:27:13 +01:00
|
|
|
|
2019-02-01 17:19:20 +00:00
|
|
|
void PrepareReschedule() {
|
|
|
|
prepare_reschedule_callback();
|
|
|
|
}
|
|
|
|
|
2020-02-21 18:31:32 +00:00
|
|
|
u32 NewThreadId();
|
|
|
|
|
|
|
|
void ResetThreadIDs();
|
|
|
|
|
2018-10-26 15:27:13 +01:00
|
|
|
/// Map of named ports managed by the kernel, which can be retrieved using the ConnectToPort
|
2019-03-23 20:04:19 +00:00
|
|
|
std::unordered_map<std::string, std::shared_ptr<ClientPort>> named_ports;
|
2018-10-26 15:27:13 +01:00
|
|
|
|
2020-04-22 06:44:58 +01:00
|
|
|
ARM_Interface* current_cpu = nullptr;
|
2019-06-25 23:39:11 +01:00
|
|
|
|
2018-11-21 03:48:19 +00:00
|
|
|
Memory::MemorySystem& memory;
|
|
|
|
|
2019-02-01 16:54:52 +00:00
|
|
|
Core::Timing& timing;
|
|
|
|
|
2018-10-13 21:41:34 +01:00
|
|
|
private:
|
2020-02-29 18:48:27 +00:00
|
|
|
void MemoryInit(u32 mem_type, u8 n3ds_mode);
|
2018-10-25 15:51:00 +01:00
|
|
|
|
2019-02-01 17:19:20 +00:00
|
|
|
std::function<void()> prepare_reschedule_callback;
|
|
|
|
|
2018-10-13 21:41:34 +01:00
|
|
|
std::unique_ptr<ResourceLimitList> resource_limits;
|
2018-10-13 22:24:51 +01:00
|
|
|
std::atomic<u32> next_object_id{0};
|
2018-10-17 18:47:42 +01:00
|
|
|
|
2018-11-04 14:29:28 +00:00
|
|
|
// Note: keep the member order below in order to perform correct destruction.
|
|
|
|
// Thread manager is destructed before process list in order to Stop threads and clear thread
|
|
|
|
// info from their parent processes first. Timer manager is destructed after process list
|
|
|
|
// because timers are destructed along with process list and they need to clear info from the
|
|
|
|
// timer manager.
|
|
|
|
// TODO (wwylele): refactor the cleanup sequence to make this less complicated and sensitive.
|
|
|
|
|
2018-11-04 09:24:37 +00:00
|
|
|
std::unique_ptr<TimerManager> timer_manager;
|
|
|
|
|
2018-10-17 18:47:42 +01:00
|
|
|
// TODO(Subv): Start the process ids from 10 for now, as lower PIDs are
|
|
|
|
// reserved for low-level services
|
|
|
|
u32 next_process_id = 10;
|
2018-10-17 19:06:47 +01:00
|
|
|
|
|
|
|
// Lists all processes that exist in the current session.
|
2019-03-23 20:04:19 +00:00
|
|
|
std::vector<std::shared_ptr<Process>> process_list;
|
2018-10-17 20:23:56 +01:00
|
|
|
|
2019-03-23 20:04:19 +00:00
|
|
|
std::shared_ptr<Process> current_process;
|
2020-02-21 18:31:32 +00:00
|
|
|
std::vector<std::shared_ptr<Process>> stored_processes;
|
2018-10-23 14:57:59 +01:00
|
|
|
|
2020-02-21 18:31:32 +00:00
|
|
|
std::vector<std::unique_ptr<ThreadManager>> thread_managers;
|
2018-11-04 14:29:28 +00:00
|
|
|
|
2020-01-04 22:39:54 +00:00
|
|
|
std::shared_ptr<ConfigMem::Handler> config_mem_handler;
|
|
|
|
std::shared_ptr<SharedPage::Handler> shared_page_handler;
|
2019-07-22 13:10:47 +01:00
|
|
|
|
|
|
|
std::unique_ptr<IPCDebugger::Recorder> ipc_recorder;
|
2019-08-11 00:20:09 +01:00
|
|
|
|
2020-02-21 18:31:32 +00:00
|
|
|
u32 next_thread_id;
|
2020-03-07 21:23:08 +00:00
|
|
|
|
2019-08-11 00:20:09 +01:00
|
|
|
friend class boost::serialization::access;
|
|
|
|
template <class Archive>
|
|
|
|
void serialize(Archive& ar, const unsigned int file_version);
|
2018-10-11 19:49:52 +01:00
|
|
|
};
|
2014-06-11 03:43:50 +01:00
|
|
|
|
2017-07-21 05:52:50 +01:00
|
|
|
} // namespace Kernel
|