summaryrefslogtreecommitdiffstats
path: root/src/core/hle/kernel
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/core/hle/kernel/client_port.cpp10
-rw-r--r--src/core/hle/kernel/client_port.h2
-rw-r--r--src/core/hle/kernel/client_session.h2
-rw-r--r--src/core/hle/kernel/kernel.cpp2
-rw-r--r--src/core/hle/kernel/object.cpp1
-rw-r--r--src/core/hle/kernel/object.h1
-rw-r--r--src/core/hle/kernel/process.cpp5
-rw-r--r--src/core/hle/kernel/process.h2
-rw-r--r--src/core/hle/kernel/readable_event.h2
-rw-r--r--src/core/hle/kernel/resource_limit.h2
-rw-r--r--src/core/hle/kernel/scheduler.cpp1
-rw-r--r--src/core/hle/kernel/server_port.cpp7
-rw-r--r--src/core/hle/kernel/server_port.h9
-rw-r--r--src/core/hle/kernel/server_session.cpp11
-rw-r--r--src/core/hle/kernel/server_session.h9
-rw-r--r--src/core/hle/kernel/shared_memory.h2
-rw-r--r--src/core/hle/kernel/svc.cpp491
-rw-r--r--src/core/hle/kernel/svc.h6
-rw-r--r--src/core/hle/kernel/svc_wrap.h359
-rw-r--r--src/core/hle/kernel/thread.cpp5
-rw-r--r--src/core/hle/kernel/thread.h8
-rw-r--r--src/core/hle/kernel/transfer_memory.cpp22
-rw-r--r--src/core/hle/kernel/transfer_memory.h20
-rw-r--r--src/core/hle/kernel/vm_manager.cpp80
-rw-r--r--src/core/hle/kernel/vm_manager.h49
-rw-r--r--src/core/hle/kernel/writable_event.h2
26 files changed, 726 insertions, 384 deletions
diff --git a/src/core/hle/kernel/client_port.cpp b/src/core/hle/kernel/client_port.cpp
index aa432658e..744b1697d 100644
--- a/src/core/hle/kernel/client_port.cpp
+++ b/src/core/hle/kernel/client_port.cpp
@@ -2,8 +2,6 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
-#include <tuple>
-
#include "core/hle/kernel/client_port.h"
#include "core/hle/kernel/client_session.h"
#include "core/hle/kernel/errors.h"
@@ -31,18 +29,18 @@ ResultVal<SharedPtr<ClientSession>> ClientPort::Connect() {
active_sessions++;
// Create a new session pair, let the created sessions inherit the parent port's HLE handler.
- auto sessions = ServerSession::CreateSessionPair(kernel, server_port->GetName(), this);
+ auto [server, client] = ServerSession::CreateSessionPair(kernel, server_port->GetName(), this);
if (server_port->HasHLEHandler()) {
- server_port->GetHLEHandler()->ClientConnected(std::get<SharedPtr<ServerSession>>(sessions));
+ server_port->GetHLEHandler()->ClientConnected(server);
} else {
- server_port->AppendPendingSession(std::get<SharedPtr<ServerSession>>(sessions));
+ server_port->AppendPendingSession(server);
}
// Wake the threads waiting on the ServerPort
server_port->WakeupAllWaitingThreads();
- return MakeResult(std::get<SharedPtr<ClientSession>>(sessions));
+ return MakeResult(client);
}
void ClientPort::ConnectionClosed() {
diff --git a/src/core/hle/kernel/client_port.h b/src/core/hle/kernel/client_port.h
index 6cd607206..4921ad4f0 100644
--- a/src/core/hle/kernel/client_port.h
+++ b/src/core/hle/kernel/client_port.h
@@ -25,7 +25,7 @@ public:
return name;
}
- static const HandleType HANDLE_TYPE = HandleType::ClientPort;
+ static constexpr HandleType HANDLE_TYPE = HandleType::ClientPort;
HandleType GetHandleType() const override {
return HANDLE_TYPE;
}
diff --git a/src/core/hle/kernel/client_session.h b/src/core/hle/kernel/client_session.h
index b1f39aad7..09cdff588 100644
--- a/src/core/hle/kernel/client_session.h
+++ b/src/core/hle/kernel/client_session.h
@@ -29,7 +29,7 @@ public:
return name;
}
- static const HandleType HANDLE_TYPE = HandleType::ClientSession;
+ static constexpr HandleType HANDLE_TYPE = HandleType::ClientSession;
HandleType GetHandleType() const override {
return HANDLE_TYPE;
}
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp
index 3f14bfa86..4d58e7c69 100644
--- a/src/core/hle/kernel/kernel.cpp
+++ b/src/core/hle/kernel/kernel.cpp
@@ -21,6 +21,7 @@
#include "core/hle/kernel/thread.h"
#include "core/hle/lock.h"
#include "core/hle/result.h"
+#include "core/memory.h"
namespace Kernel {
@@ -181,6 +182,7 @@ void KernelCore::AppendNewProcess(SharedPtr<Process> process) {
void KernelCore::MakeCurrentProcess(Process* process) {
impl->current_process = process;
+ Memory::SetCurrentPageTable(&process->VMManager().page_table);
}
Process* KernelCore::CurrentProcess() {
diff --git a/src/core/hle/kernel/object.cpp b/src/core/hle/kernel/object.cpp
index 217144efc..10431e94c 100644
--- a/src/core/hle/kernel/object.cpp
+++ b/src/core/hle/kernel/object.cpp
@@ -24,7 +24,6 @@ bool Object::IsWaitable() const {
case HandleType::WritableEvent:
case HandleType::SharedMemory:
case HandleType::TransferMemory:
- case HandleType::AddressArbiter:
case HandleType::ResourceLimit:
case HandleType::ClientPort:
case HandleType::ClientSession:
diff --git a/src/core/hle/kernel/object.h b/src/core/hle/kernel/object.h
index 3f6baa094..332876c27 100644
--- a/src/core/hle/kernel/object.h
+++ b/src/core/hle/kernel/object.h
@@ -25,7 +25,6 @@ enum class HandleType : u32 {
TransferMemory,
Thread,
Process,
- AddressArbiter,
ResourceLimit,
ClientPort,
ServerPort,
diff --git a/src/core/hle/kernel/process.cpp b/src/core/hle/kernel/process.cpp
index 041267318..4e94048da 100644
--- a/src/core/hle/kernel/process.cpp
+++ b/src/core/hle/kernel/process.cpp
@@ -32,9 +32,6 @@ namespace {
* @param priority The priority to give the main thread
*/
void SetupMainThread(Process& owner_process, KernelCore& kernel, VAddr entry_point, u32 priority) {
- // Setup page table so we can write to memory
- Memory::SetCurrentPageTable(&owner_process.VMManager().page_table);
-
// Initialize new "main" thread
const VAddr stack_top = owner_process.VMManager().GetTLSIORegionEndAddress();
auto thread_res = Thread::Create(kernel, "main", entry_point, priority, 0,
@@ -109,6 +106,8 @@ ResultCode Process::LoadFromMetadata(const FileSys::ProgramMetadata& metadata) {
is_64bit_process = metadata.Is64BitProgram();
vm_manager.Reset(metadata.GetAddressSpaceType());
+ // Ensure that the potentially resized page table is seen by CPU backends.
+ Memory::SetCurrentPageTable(&vm_manager.page_table);
const auto& caps = metadata.GetKernelCapabilities();
const auto capability_init_result =
diff --git a/src/core/hle/kernel/process.h b/src/core/hle/kernel/process.h
index f060f2a3b..dda52f4c0 100644
--- a/src/core/hle/kernel/process.h
+++ b/src/core/hle/kernel/process.h
@@ -85,7 +85,7 @@ public:
return name;
}
- static const HandleType HANDLE_TYPE = HandleType::Process;
+ static constexpr HandleType HANDLE_TYPE = HandleType::Process;
HandleType GetHandleType() const override {
return HANDLE_TYPE;
}
diff --git a/src/core/hle/kernel/readable_event.h b/src/core/hle/kernel/readable_event.h
index 2eb9dcbb7..84215f572 100644
--- a/src/core/hle/kernel/readable_event.h
+++ b/src/core/hle/kernel/readable_event.h
@@ -31,7 +31,7 @@ public:
return reset_type;
}
- static const HandleType HANDLE_TYPE = HandleType::ReadableEvent;
+ static constexpr HandleType HANDLE_TYPE = HandleType::ReadableEvent;
HandleType GetHandleType() const override {
return HANDLE_TYPE;
}
diff --git a/src/core/hle/kernel/resource_limit.h b/src/core/hle/kernel/resource_limit.h
index 70e09858a..2613a6bb5 100644
--- a/src/core/hle/kernel/resource_limit.h
+++ b/src/core/hle/kernel/resource_limit.h
@@ -41,7 +41,7 @@ public:
return GetTypeName();
}
- static const HandleType HANDLE_TYPE = HandleType::ResourceLimit;
+ static constexpr HandleType HANDLE_TYPE = HandleType::ResourceLimit;
HandleType GetHandleType() const override {
return HANDLE_TYPE;
}
diff --git a/src/core/hle/kernel/scheduler.cpp b/src/core/hle/kernel/scheduler.cpp
index ac501bf7f..e8447b69a 100644
--- a/src/core/hle/kernel/scheduler.cpp
+++ b/src/core/hle/kernel/scheduler.cpp
@@ -101,7 +101,6 @@ void Scheduler::SwitchContext(Thread* new_thread) {
auto* const thread_owner_process = current_thread->GetOwnerProcess();
if (previous_process != thread_owner_process) {
system.Kernel().MakeCurrentProcess(thread_owner_process);
- Memory::SetCurrentPageTable(&thread_owner_process->VMManager().page_table);
}
cpu_core.LoadContext(new_thread->GetContext());
diff --git a/src/core/hle/kernel/server_port.cpp b/src/core/hle/kernel/server_port.cpp
index 708fdf9e1..02e7c60e6 100644
--- a/src/core/hle/kernel/server_port.cpp
+++ b/src/core/hle/kernel/server_port.cpp
@@ -39,9 +39,8 @@ void ServerPort::Acquire(Thread* thread) {
ASSERT_MSG(!ShouldWait(thread), "object unavailable!");
}
-std::tuple<SharedPtr<ServerPort>, SharedPtr<ClientPort>> ServerPort::CreatePortPair(
- KernelCore& kernel, u32 max_sessions, std::string name) {
-
+ServerPort::PortPair ServerPort::CreatePortPair(KernelCore& kernel, u32 max_sessions,
+ std::string name) {
SharedPtr<ServerPort> server_port(new ServerPort(kernel));
SharedPtr<ClientPort> client_port(new ClientPort(kernel));
@@ -51,7 +50,7 @@ std::tuple<SharedPtr<ServerPort>, SharedPtr<ClientPort>> ServerPort::CreatePortP
client_port->max_sessions = max_sessions;
client_port->active_sessions = 0;
- return std::make_tuple(std::move(server_port), std::move(client_port));
+ return std::make_pair(std::move(server_port), std::move(client_port));
}
} // namespace Kernel
diff --git a/src/core/hle/kernel/server_port.h b/src/core/hle/kernel/server_port.h
index 76293cb8b..dc88a1ebd 100644
--- a/src/core/hle/kernel/server_port.h
+++ b/src/core/hle/kernel/server_port.h
@@ -6,7 +6,7 @@
#include <memory>
#include <string>
-#include <tuple>
+#include <utility>
#include <vector>
#include "common/common_types.h"
#include "core/hle/kernel/object.h"
@@ -23,6 +23,7 @@ class SessionRequestHandler;
class ServerPort final : public WaitObject {
public:
using HLEHandler = std::shared_ptr<SessionRequestHandler>;
+ using PortPair = std::pair<SharedPtr<ServerPort>, SharedPtr<ClientPort>>;
/**
* Creates a pair of ServerPort and an associated ClientPort.
@@ -32,8 +33,8 @@ public:
* @param name Optional name of the ports
* @return The created port tuple
*/
- static std::tuple<SharedPtr<ServerPort>, SharedPtr<ClientPort>> CreatePortPair(
- KernelCore& kernel, u32 max_sessions, std::string name = "UnknownPort");
+ static PortPair CreatePortPair(KernelCore& kernel, u32 max_sessions,
+ std::string name = "UnknownPort");
std::string GetTypeName() const override {
return "ServerPort";
@@ -42,7 +43,7 @@ public:
return name;
}
- static const HandleType HANDLE_TYPE = HandleType::ServerPort;
+ static constexpr HandleType HANDLE_TYPE = HandleType::ServerPort;
HandleType GetHandleType() const override {
return HANDLE_TYPE;
}
diff --git a/src/core/hle/kernel/server_session.cpp b/src/core/hle/kernel/server_session.cpp
index 40cec143e..696a82cd9 100644
--- a/src/core/hle/kernel/server_session.cpp
+++ b/src/core/hle/kernel/server_session.cpp
@@ -28,11 +28,9 @@ ServerSession::~ServerSession() {
// the emulated application.
// Decrease the port's connection count.
- if (parent->port)
+ if (parent->port) {
parent->port->ConnectionClosed();
-
- // TODO(Subv): Wake up all the ClientSession's waiting threads and set
- // the SendSyncRequest result to 0xC920181A.
+ }
parent->server = nullptr;
}
@@ -74,9 +72,6 @@ void ServerSession::ClientDisconnected() {
handler->ClientDisconnected(this);
}
- // TODO(Subv): Force a wake up of all the ServerSession's waiting threads and set
- // their WaitSynchronization result to 0xC920181A.
-
// Clean up the list of client threads with pending requests, they are unneeded now that the
// client endpoint is closed.
pending_requesting_threads.clear();
@@ -204,6 +199,6 @@ ServerSession::SessionPair ServerSession::CreateSessionPair(KernelCore& kernel,
client_session->parent = parent;
server_session->parent = parent;
- return std::make_tuple(std::move(server_session), std::move(client_session));
+ return std::make_pair(std::move(server_session), std::move(client_session));
}
} // namespace Kernel
diff --git a/src/core/hle/kernel/server_session.h b/src/core/hle/kernel/server_session.h
index 79b84bade..738df30f8 100644
--- a/src/core/hle/kernel/server_session.h
+++ b/src/core/hle/kernel/server_session.h
@@ -6,6 +6,7 @@
#include <memory>
#include <string>
+#include <utility>
#include <vector>
#include "core/hle/kernel/object.h"
@@ -41,7 +42,11 @@ public:
return "ServerSession";
}
- static const HandleType HANDLE_TYPE = HandleType::ServerSession;
+ std::string GetName() const override {
+ return name;
+ }
+
+ static constexpr HandleType HANDLE_TYPE = HandleType::ServerSession;
HandleType GetHandleType() const override {
return HANDLE_TYPE;
}
@@ -54,7 +59,7 @@ public:
return parent.get();
}
- using SessionPair = std::tuple<SharedPtr<ServerSession>, SharedPtr<ClientSession>>;
+ using SessionPair = std::pair<SharedPtr<ServerSession>, SharedPtr<ClientSession>>;
/**
* Creates a pair of ServerSession and an associated ClientSession.
diff --git a/src/core/hle/kernel/shared_memory.h b/src/core/hle/kernel/shared_memory.h
index 37e18c443..c2b6155e1 100644
--- a/src/core/hle/kernel/shared_memory.h
+++ b/src/core/hle/kernel/shared_memory.h
@@ -76,7 +76,7 @@ public:
return name;
}
- static const HandleType HANDLE_TYPE = HandleType::SharedMemory;
+ static constexpr HandleType HANDLE_TYPE = HandleType::SharedMemory;
HandleType GetHandleType() const override {
return HANDLE_TYPE;
}
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp
index ab10db3df..d48a2203a 100644
--- a/src/core/hle/kernel/svc.cpp
+++ b/src/core/hle/kernel/svc.cpp
@@ -131,16 +131,15 @@ enum class ResourceLimitValueType {
LimitValue,
};
-ResultVal<s64> RetrieveResourceLimitValue(Handle resource_limit, u32 resource_type,
- ResourceLimitValueType value_type) {
+ResultVal<s64> RetrieveResourceLimitValue(Core::System& system, Handle resource_limit,
+ u32 resource_type, ResourceLimitValueType value_type) {
const auto type = static_cast<ResourceType>(resource_type);
if (!IsValidResourceType(type)) {
LOG_ERROR(Kernel_SVC, "Invalid resource limit type: '{}'", resource_type);
return ERR_INVALID_ENUM_VALUE;
}
- const auto& kernel = Core::System::GetInstance().Kernel();
- const auto* const current_process = kernel.CurrentProcess();
+ const auto* const current_process = system.Kernel().CurrentProcess();
ASSERT(current_process != nullptr);
const auto resource_limit_object =
@@ -160,7 +159,7 @@ ResultVal<s64> RetrieveResourceLimitValue(Handle resource_limit, u32 resource_ty
} // Anonymous namespace
/// Set the process heap to a given Size. It can both extend and shrink the heap.
-static ResultCode SetHeapSize(VAddr* heap_addr, u64 heap_size) {
+static ResultCode SetHeapSize(Core::System& system, VAddr* heap_addr, u64 heap_size) {
LOG_TRACE(Kernel_SVC, "called, heap_size=0x{:X}", heap_size);
// Size must be a multiple of 0x200000 (2MB) and be equal to or less than 8GB.
@@ -175,7 +174,7 @@ static ResultCode SetHeapSize(VAddr* heap_addr, u64 heap_size) {
return ERR_INVALID_SIZE;
}
- auto& vm_manager = Core::System::GetInstance().Kernel().CurrentProcess()->VMManager();
+ auto& vm_manager = system.Kernel().CurrentProcess()->VMManager();
const auto alloc_result = vm_manager.SetHeapSize(heap_size);
if (alloc_result.Failed()) {
return alloc_result.Code();
@@ -185,7 +184,7 @@ static ResultCode SetHeapSize(VAddr* heap_addr, u64 heap_size) {
return RESULT_SUCCESS;
}
-static ResultCode SetMemoryPermission(VAddr addr, u64 size, u32 prot) {
+static ResultCode SetMemoryPermission(Core::System& system, VAddr addr, u64 size, u32 prot) {
LOG_TRACE(Kernel_SVC, "called, addr=0x{:X}, size=0x{:X}, prot=0x{:X}", addr, size, prot);
if (!Common::Is4KBAligned(addr)) {
@@ -217,7 +216,7 @@ static ResultCode SetMemoryPermission(VAddr addr, u64 size, u32 prot) {
return ERR_INVALID_MEMORY_PERMISSIONS;
}
- auto* const current_process = Core::CurrentProcess();
+ auto* const current_process = system.Kernel().CurrentProcess();
auto& vm_manager = current_process->VMManager();
if (!vm_manager.IsWithinAddressSpace(addr, size)) {
@@ -242,7 +241,8 @@ static ResultCode SetMemoryPermission(VAddr addr, u64 size, u32 prot) {
return vm_manager.ReprotectRange(addr, size, converted_permissions);
}
-static ResultCode SetMemoryAttribute(VAddr address, u64 size, u32 mask, u32 attribute) {
+static ResultCode SetMemoryAttribute(Core::System& system, VAddr address, u64 size, u32 mask,
+ u32 attribute) {
LOG_DEBUG(Kernel_SVC,
"called, address=0x{:016X}, size=0x{:X}, mask=0x{:08X}, attribute=0x{:08X}", address,
size, mask, attribute);
@@ -280,7 +280,7 @@ static ResultCode SetMemoryAttribute(VAddr address, u64 size, u32 mask, u32 attr
return ERR_INVALID_COMBINATION;
}
- auto& vm_manager = Core::CurrentProcess()->VMManager();
+ auto& vm_manager = system.Kernel().CurrentProcess()->VMManager();
if (!vm_manager.IsWithinAddressSpace(address, size)) {
LOG_ERROR(Kernel_SVC,
"Given address (0x{:016X}) is outside the bounds of the address space.", address);
@@ -291,11 +291,11 @@ static ResultCode SetMemoryAttribute(VAddr address, u64 size, u32 mask, u32 attr
}
/// Maps a memory range into a different range.
-static ResultCode MapMemory(VAddr dst_addr, VAddr src_addr, u64 size) {
+static ResultCode MapMemory(Core::System& system, VAddr dst_addr, VAddr src_addr, u64 size) {
LOG_TRACE(Kernel_SVC, "called, dst_addr=0x{:X}, src_addr=0x{:X}, size=0x{:X}", dst_addr,
src_addr, size);
- auto& vm_manager = Core::CurrentProcess()->VMManager();
+ auto& vm_manager = system.Kernel().CurrentProcess()->VMManager();
const auto result = MapUnmapMemorySanityChecks(vm_manager, dst_addr, src_addr, size);
if (result.IsError()) {
@@ -306,11 +306,11 @@ static ResultCode MapMemory(VAddr dst_addr, VAddr src_addr, u64 size) {
}
/// Unmaps a region that was previously mapped with svcMapMemory
-static ResultCode UnmapMemory(VAddr dst_addr, VAddr src_addr, u64 size) {
+static ResultCode UnmapMemory(Core::System& system, VAddr dst_addr, VAddr src_addr, u64 size) {
LOG_TRACE(Kernel_SVC, "called, dst_addr=0x{:X}, src_addr=0x{:X}, size=0x{:X}", dst_addr,
src_addr, size);
- auto& vm_manager = Core::CurrentProcess()->VMManager();
+ auto& vm_manager = system.Kernel().CurrentProcess()->VMManager();
const auto result = MapUnmapMemorySanityChecks(vm_manager, dst_addr, src_addr, size);
if (result.IsError()) {
@@ -321,7 +321,8 @@ static ResultCode UnmapMemory(VAddr dst_addr, VAddr src_addr, u64 size) {
}
/// Connect to an OS service given the port name, returns the handle to the port to out
-static ResultCode ConnectToNamedPort(Handle* out_handle, VAddr port_name_address) {
+static ResultCode ConnectToNamedPort(Core::System& system, Handle* out_handle,
+ VAddr port_name_address) {
if (!Memory::IsValidVirtualAddress(port_name_address)) {
LOG_ERROR(Kernel_SVC,
"Port Name Address is not a valid virtual address, port_name_address=0x{:016X}",
@@ -340,8 +341,8 @@ static ResultCode ConnectToNamedPort(Handle* out_handle, VAddr port_name_address
LOG_TRACE(Kernel_SVC, "called port_name={}", port_name);
- auto& kernel = Core::System::GetInstance().Kernel();
- auto it = kernel.FindNamedPort(port_name);
+ auto& kernel = system.Kernel();
+ const auto it = kernel.FindNamedPort(port_name);
if (!kernel.IsValidNamedPort(it)) {
LOG_WARNING(Kernel_SVC, "tried to connect to unknown port: {}", port_name);
return ERR_NOT_FOUND;
@@ -353,14 +354,14 @@ static ResultCode ConnectToNamedPort(Handle* out_handle, VAddr port_name_address
CASCADE_RESULT(client_session, client_port->Connect());
// Return the client session
- auto& handle_table = Core::CurrentProcess()->GetHandleTable();
+ auto& handle_table = kernel.CurrentProcess()->GetHandleTable();
CASCADE_RESULT(*out_handle, handle_table.Create(client_session));
return RESULT_SUCCESS;
}
/// Makes a blocking IPC call to an OS service.
-static ResultCode SendSyncRequest(Handle handle) {
- const auto& handle_table = Core::CurrentProcess()->GetHandleTable();
+static ResultCode SendSyncRequest(Core::System& system, Handle handle) {
+ const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable();
SharedPtr<ClientSession> session = handle_table.Get<ClientSession>(handle);
if (!session) {
LOG_ERROR(Kernel_SVC, "called with invalid handle=0x{:08X}", handle);
@@ -369,18 +370,18 @@ static ResultCode SendSyncRequest(Handle handle) {
LOG_TRACE(Kernel_SVC, "called handle=0x{:08X}({})", handle, session->GetName());
- Core::System::GetInstance().PrepareReschedule();
+ system.PrepareReschedule();
// TODO(Subv): svcSendSyncRequest should put the caller thread to sleep while the server
// responds and cause a reschedule.
- return session->SendSyncRequest(GetCurrentThread());
+ return session->SendSyncRequest(system.CurrentScheduler().GetCurrentThread());
}
/// Get the ID for the specified thread.
-static ResultCode GetThreadId(u64* thread_id, Handle thread_handle) {
+static ResultCode GetThreadId(Core::System& system, u64* thread_id, Handle thread_handle) {
LOG_TRACE(Kernel_SVC, "called thread=0x{:08X}", thread_handle);
- const auto& handle_table = Core::CurrentProcess()->GetHandleTable();
+ const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable();
const SharedPtr<Thread> thread = handle_table.Get<Thread>(thread_handle);
if (!thread) {
LOG_ERROR(Kernel_SVC, "Thread handle does not exist, handle=0x{:08X}", thread_handle);
@@ -392,10 +393,10 @@ static ResultCode GetThreadId(u64* thread_id, Handle thread_handle) {
}
/// Gets the ID of the specified process or a specified thread's owning process.
-static ResultCode GetProcessId(u64* process_id, Handle handle) {
+static ResultCode GetProcessId(Core::System& system, u64* process_id, Handle handle) {
LOG_DEBUG(Kernel_SVC, "called handle=0x{:08X}", handle);
- const auto& handle_table = Core::CurrentProcess()->GetHandleTable();
+ const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable();
const SharedPtr<Process> process = handle_table.Get<Process>(handle);
if (process) {
*process_id = process->GetProcessID();
@@ -437,8 +438,8 @@ static bool DefaultThreadWakeupCallback(ThreadWakeupReason reason, SharedPtr<Thr
};
/// Wait for the given handles to synchronize, timeout after the specified nanoseconds
-static ResultCode WaitSynchronization(Handle* index, VAddr handles_address, u64 handle_count,
- s64 nano_seconds) {
+static ResultCode WaitSynchronization(Core::System& system, Handle* index, VAddr handles_address,
+ u64 handle_count, s64 nano_seconds) {
LOG_TRACE(Kernel_SVC, "called handles_address=0x{:X}, handle_count={}, nano_seconds={}",
handles_address, handle_count, nano_seconds);
@@ -457,11 +458,11 @@ static ResultCode WaitSynchronization(Handle* index, VAddr handles_address, u64
return ERR_OUT_OF_RANGE;
}
- auto* const thread = GetCurrentThread();
+ auto* const thread = system.CurrentScheduler().GetCurrentThread();
using ObjectPtr = Thread::ThreadWaitObjects::value_type;
Thread::ThreadWaitObjects objects(handle_count);
- const auto& handle_table = Core::CurrentProcess()->GetHandleTable();
+ const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable();
for (u64 i = 0; i < handle_count; ++i) {
const Handle handle = Memory::Read32(handles_address + i * sizeof(Handle));
@@ -507,16 +508,16 @@ static ResultCode WaitSynchronization(Handle* index, VAddr handles_address, u64
thread->WakeAfterDelay(nano_seconds);
thread->SetWakeupCallback(DefaultThreadWakeupCallback);
- Core::System::GetInstance().CpuCore(thread->GetProcessorID()).PrepareReschedule();
+ system.CpuCore(thread->GetProcessorID()).PrepareReschedule();
return RESULT_TIMEOUT;
}
/// Resumes a thread waiting on WaitSynchronization
-static ResultCode CancelSynchronization(Handle thread_handle) {
+static ResultCode CancelSynchronization(Core::System& system, Handle thread_handle) {
LOG_TRACE(Kernel_SVC, "called thread=0x{:X}", thread_handle);
- const auto& handle_table = Core::CurrentProcess()->GetHandleTable();
+ const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable();
const SharedPtr<Thread> thread = handle_table.Get<Thread>(thread_handle);
if (!thread) {
LOG_ERROR(Kernel_SVC, "Thread handle does not exist, thread_handle=0x{:08X}",
@@ -531,8 +532,8 @@ static ResultCode CancelSynchronization(Handle thread_handle) {
}
/// Attempts to locks a mutex, creating it if it does not already exist
-static ResultCode ArbitrateLock(Handle holding_thread_handle, VAddr mutex_addr,
- Handle requesting_thread_handle) {
+static ResultCode ArbitrateLock(Core::System& system, Handle holding_thread_handle,
+ VAddr mutex_addr, Handle requesting_thread_handle) {
LOG_TRACE(Kernel_SVC,
"called holding_thread_handle=0x{:08X}, mutex_addr=0x{:X}, "
"requesting_current_thread_handle=0x{:08X}",
@@ -549,13 +550,13 @@ static ResultCode ArbitrateLock(Handle holding_thread_handle, VAddr mutex_addr,
return ERR_INVALID_ADDRESS;
}
- auto* const current_process = Core::System::GetInstance().Kernel().CurrentProcess();
+ auto* const current_process = system.Kernel().CurrentProcess();
return current_process->GetMutex().TryAcquire(mutex_addr, holding_thread_handle,
requesting_thread_handle);
}
/// Unlock a mutex
-static ResultCode ArbitrateUnlock(VAddr mutex_addr) {
+static ResultCode ArbitrateUnlock(Core::System& system, VAddr mutex_addr) {
LOG_TRACE(Kernel_SVC, "called mutex_addr=0x{:X}", mutex_addr);
if (Memory::IsKernelVirtualAddress(mutex_addr)) {
@@ -569,7 +570,7 @@ static ResultCode ArbitrateUnlock(VAddr mutex_addr) {
return ERR_INVALID_ADDRESS;
}
- auto* const current_process = Core::System::GetInstance().Kernel().CurrentProcess();
+ auto* const current_process = system.Kernel().CurrentProcess();
return current_process->GetMutex().Release(mutex_addr);
}
@@ -592,7 +593,7 @@ struct BreakReason {
};
/// Break program execution
-static void Break(u32 reason, u64 info1, u64 info2) {
+static void Break(Core::System& system, u32 reason, u64 info1, u64 info2) {
BreakReason break_reason{reason};
bool has_dumped_buffer{};
@@ -670,22 +671,24 @@ static void Break(u32 reason, u64 info1, u64 info2) {
Debug_Emulated,
"Emulated program broke execution! reason=0x{:016X}, info1=0x{:016X}, info2=0x{:016X}",
reason, info1, info2);
+
handle_debug_buffer(info1, info2);
- Core::System::GetInstance()
- .ArmInterface(static_cast<std::size_t>(GetCurrentThread()->GetProcessorID()))
- .LogBacktrace();
+
+ auto* const current_thread = system.CurrentScheduler().GetCurrentThread();
+ const auto thread_processor_id = current_thread->GetProcessorID();
+ system.ArmInterface(static_cast<std::size_t>(thread_processor_id)).LogBacktrace();
ASSERT(false);
- Core::CurrentProcess()->PrepareForTermination();
+ system.Kernel().CurrentProcess()->PrepareForTermination();
// Kill the current thread
- GetCurrentThread()->Stop();
- Core::System::GetInstance().PrepareReschedule();
+ current_thread->Stop();
+ system.PrepareReschedule();
}
}
/// Used to output a message on a debug hardware unit - does nothing on a retail unit
-static void OutputDebugString(VAddr address, u64 len) {
+static void OutputDebugString([[maybe_unused]] Core::System& system, VAddr address, u64 len) {
if (len == 0) {
return;
}
@@ -696,7 +699,8 @@ static void OutputDebugString(VAddr address, u64 len) {
}
/// Gets system/memory information for the current process
-static ResultCode GetInfo(u64* result, u64 info_id, u64 handle, u64 info_sub_id) {
+static ResultCode GetInfo(Core::System& system, u64* result, u64 info_id, u64 handle,
+ u64 info_sub_id) {
LOG_TRACE(Kernel_SVC, "called info_id=0x{:X}, info_sub_id=0x{:X}, handle=0x{:08X}", info_id,
info_sub_id, handle);
@@ -754,7 +758,8 @@ static ResultCode GetInfo(u64* result, u64 info_id, u64 handle, u64 info_sub_id)
return ERR_INVALID_ENUM_VALUE;
}
- const auto& current_process_handle_table = Core::CurrentProcess()->GetHandleTable();
+ const auto& current_process_handle_table =
+ system.Kernel().CurrentProcess()->GetHandleTable();
const auto process = current_process_handle_table.Get<Process>(static_cast<Handle>(handle));
if (!process) {
return ERR_INVALID_HANDLE;
@@ -844,7 +849,7 @@ static ResultCode GetInfo(u64* result, u64 info_id, u64 handle, u64 info_sub_id)
return ERR_INVALID_COMBINATION;
}
- Process* const current_process = Core::CurrentProcess();
+ Process* const current_process = system.Kernel().CurrentProcess();
HandleTable& handle_table = current_process->GetHandleTable();
const auto resource_limit = current_process->GetResourceLimit();
if (!resource_limit) {
@@ -875,7 +880,7 @@ static ResultCode GetInfo(u64* result, u64 info_id, u64 handle, u64 info_sub_id)
return ERR_INVALID_COMBINATION;
}
- *result = Core::CurrentProcess()->GetRandomEntropy(info_sub_id);
+ *result = system.Kernel().CurrentProcess()->GetRandomEntropy(info_sub_id);
return RESULT_SUCCESS;
case GetInfoType::PrivilegedProcessId:
@@ -892,15 +897,14 @@ static ResultCode GetInfo(u64* result, u64 info_id, u64 handle, u64 info_sub_id)
return ERR_INVALID_COMBINATION;
}
- const auto thread =
- Core::CurrentProcess()->GetHandleTable().Get<Thread>(static_cast<Handle>(handle));
+ const auto thread = system.Kernel().CurrentProcess()->GetHandleTable().Get<Thread>(
+ static_cast<Handle>(handle));
if (!thread) {
LOG_ERROR(Kernel_SVC, "Thread handle does not exist, handle=0x{:08X}",
static_cast<Handle>(handle));
return ERR_INVALID_HANDLE;
}
- const auto& system = Core::System::GetInstance();
const auto& core_timing = system.CoreTiming();
const auto& scheduler = system.CurrentScheduler();
const auto* const current_thread = scheduler.GetCurrentThread();
@@ -927,13 +931,13 @@ static ResultCode GetInfo(u64* result, u64 info_id, u64 handle, u64 info_sub_id)
}
/// Sets the thread activity
-static ResultCode SetThreadActivity(Handle handle, u32 activity) {
+static ResultCode SetThreadActivity(Core::System& system, Handle handle, u32 activity) {
LOG_DEBUG(Kernel_SVC, "called, handle=0x{:08X}, activity=0x{:08X}", handle, activity);
if (activity > static_cast<u32>(ThreadActivity::Paused)) {
return ERR_INVALID_ENUM_VALUE;
}
- const auto* current_process = Core::CurrentProcess();
+ const auto* current_process = system.Kernel().CurrentProcess();
const SharedPtr<Thread> thread = current_process->GetHandleTable().Get<Thread>(handle);
if (!thread) {
LOG_ERROR(Kernel_SVC, "Thread handle does not exist, handle=0x{:08X}", handle);
@@ -950,7 +954,7 @@ static ResultCode SetThreadActivity(Handle handle, u32 activity) {
return ERR_INVALID_HANDLE;
}
- if (thread == GetCurrentThread()) {
+ if (thread == system.CurrentScheduler().GetCurrentThread()) {
LOG_ERROR(Kernel_SVC, "The thread handle specified is the current running thread");
return ERR_BUSY;
}
@@ -960,10 +964,10 @@ static ResultCode SetThreadActivity(Handle handle, u32 activity) {
}
/// Gets the thread context
-static ResultCode GetThreadContext(VAddr thread_context, Handle handle) {
+static ResultCode GetThreadContext(Core::System& system, VAddr thread_context, Handle handle) {
LOG_DEBUG(Kernel_SVC, "called, context=0x{:08X}, thread=0x{:X}", thread_context, handle);
- const auto* current_process = Core::CurrentProcess();
+ const auto* current_process = system.Kernel().CurrentProcess();
const SharedPtr<Thread> thread = current_process->GetHandleTable().Get<Thread>(handle);
if (!thread) {
LOG_ERROR(Kernel_SVC, "Thread handle does not exist, handle=0x{:08X}", handle);
@@ -980,7 +984,7 @@ static ResultCode GetThreadContext(VAddr thread_context, Handle handle) {
return ERR_INVALID_HANDLE;
}
- if (thread == GetCurrentThread()) {
+ if (thread == system.CurrentScheduler().GetCurrentThread()) {
LOG_ERROR(Kernel_SVC, "The thread handle specified is the current running thread");
return ERR_BUSY;
}
@@ -1001,10 +1005,10 @@ static ResultCode GetThreadContext(VAddr thread_context, Handle handle) {
}
/// Gets the priority for the specified thread
-static ResultCode GetThreadPriority(u32* priority, Handle handle) {
+static ResultCode GetThreadPriority(Core::System& system, u32* priority, Handle handle) {
LOG_TRACE(Kernel_SVC, "called");
- const auto& handle_table = Core::CurrentProcess()->GetHandleTable();
+ const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable();
const SharedPtr<Thread> thread = handle_table.Get<Thread>(handle);
if (!thread) {
LOG_ERROR(Kernel_SVC, "Thread handle does not exist, handle=0x{:08X}", handle);
@@ -1016,7 +1020,7 @@ static ResultCode GetThreadPriority(u32* priority, Handle handle) {
}
/// Sets the priority for the specified thread
-static ResultCode SetThreadPriority(Handle handle, u32 priority) {
+static ResultCode SetThreadPriority(Core::System& system, Handle handle, u32 priority) {
LOG_TRACE(Kernel_SVC, "called");
if (priority > THREADPRIO_LOWEST) {
@@ -1027,7 +1031,7 @@ static ResultCode SetThreadPriority(Handle handle, u32 priority) {
return ERR_INVALID_THREAD_PRIORITY;
}
- const auto* const current_process = Core::CurrentProcess();
+ const auto* const current_process = system.Kernel().CurrentProcess();
SharedPtr<Thread> thread = current_process->GetHandleTable().Get<Thread>(handle);
if (!thread) {
@@ -1037,18 +1041,18 @@ static ResultCode SetThreadPriority(Handle handle, u32 priority) {
thread->SetPriority(priority);
- Core::System::GetInstance().CpuCore(thread->GetProcessorID()).PrepareReschedule();
+ system.CpuCore(thread->GetProcessorID()).PrepareReschedule();
return RESULT_SUCCESS;
}
/// Get which CPU core is executing the current thread
-static u32 GetCurrentProcessorNumber() {
+static u32 GetCurrentProcessorNumber(Core::System& system) {
LOG_TRACE(Kernel_SVC, "called");
- return GetCurrentThread()->GetProcessorID();
+ return system.CurrentScheduler().GetCurrentThread()->GetProcessorID();
}
-static ResultCode MapSharedMemory(Handle shared_memory_handle, VAddr addr, u64 size,
- u32 permissions) {
+static ResultCode MapSharedMemory(Core::System& system, Handle shared_memory_handle, VAddr addr,
+ u64 size, u32 permissions) {
LOG_TRACE(Kernel_SVC,
"called, shared_memory_handle=0x{:X}, addr=0x{:X}, size=0x{:X}, permissions=0x{:08X}",
shared_memory_handle, addr, size, permissions);
@@ -1082,7 +1086,7 @@ static ResultCode MapSharedMemory(Handle shared_memory_handle, VAddr addr, u64 s
return ERR_INVALID_MEMORY_PERMISSIONS;
}
- auto* const current_process = Core::CurrentProcess();
+ auto* const current_process = system.Kernel().CurrentProcess();
auto shared_memory = current_process->GetHandleTable().Get<SharedMemory>(shared_memory_handle);
if (!shared_memory) {
LOG_ERROR(Kernel_SVC, "Shared memory does not exist, shared_memory_handle=0x{:08X}",
@@ -1100,7 +1104,8 @@ static ResultCode MapSharedMemory(Handle shared_memory_handle, VAddr addr, u64 s
return shared_memory->Map(*current_process, addr, permissions_type, MemoryPermission::DontCare);
}
-static ResultCode UnmapSharedMemory(Handle shared_memory_handle, VAddr addr, u64 size) {
+static ResultCode UnmapSharedMemory(Core::System& system, Handle shared_memory_handle, VAddr addr,
+ u64 size) {
LOG_WARNING(Kernel_SVC, "called, shared_memory_handle=0x{:08X}, addr=0x{:X}, size=0x{:X}",
shared_memory_handle, addr, size);
@@ -1125,7 +1130,7 @@ static ResultCode UnmapSharedMemory(Handle shared_memory_handle, VAddr addr, u64
return ERR_INVALID_ADDRESS_STATE;
}
- auto* const current_process = Core::CurrentProcess();
+ auto* const current_process = system.Kernel().CurrentProcess();
auto shared_memory = current_process->GetHandleTable().Get<SharedMemory>(shared_memory_handle);
if (!shared_memory) {
LOG_ERROR(Kernel_SVC, "Shared memory does not exist, shared_memory_handle=0x{:08X}",
@@ -1143,10 +1148,11 @@ static ResultCode UnmapSharedMemory(Handle shared_memory_handle, VAddr addr, u64
return shared_memory->Unmap(*current_process, addr, size);
}
-static ResultCode QueryProcessMemory(VAddr memory_info_address, VAddr page_info_address,
- Handle process_handle, VAddr address) {
+static ResultCode QueryProcessMemory(Core::System& system, VAddr memory_info_address,
+ VAddr page_info_address, Handle process_handle,
+ VAddr address) {
LOG_TRACE(Kernel_SVC, "called process=0x{:08X} address={:X}", process_handle, address);
- const auto& handle_table = Core::CurrentProcess()->GetHandleTable();
+ const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable();
SharedPtr<Process> process = handle_table.Get<Process>(process_handle);
if (!process) {
LOG_ERROR(Kernel_SVC, "Process handle does not exist, process_handle=0x{:08X}",
@@ -1172,20 +1178,156 @@ static ResultCode QueryProcessMemory(VAddr memory_info_address, VAddr page_info_
return RESULT_SUCCESS;
}
-static ResultCode QueryMemory(VAddr memory_info_address, VAddr page_info_address,
- VAddr query_address) {
+static ResultCode QueryMemory(Core::System& system, VAddr memory_info_address,
+ VAddr page_info_address, VAddr query_address) {
LOG_TRACE(Kernel_SVC,
"called, memory_info_address=0x{:016X}, page_info_address=0x{:016X}, "
"query_address=0x{:016X}",
memory_info_address, page_info_address, query_address);
- return QueryProcessMemory(memory_info_address, page_info_address, CurrentProcess,
+ return QueryProcessMemory(system, memory_info_address, page_info_address, CurrentProcess,
query_address);
}
+static ResultCode MapProcessCodeMemory(Core::System& system, Handle process_handle, u64 dst_address,
+ u64 src_address, u64 size) {
+ LOG_DEBUG(Kernel_SVC,
+ "called. process_handle=0x{:08X}, dst_address=0x{:016X}, "
+ "src_address=0x{:016X}, size=0x{:016X}",
+ process_handle, dst_address, src_address, size);
+
+ if (!Common::Is4KBAligned(src_address)) {
+ LOG_ERROR(Kernel_SVC, "src_address is not page-aligned (src_address=0x{:016X}).",
+ src_address);
+ return ERR_INVALID_ADDRESS;
+ }
+
+ if (!Common::Is4KBAligned(dst_address)) {
+ LOG_ERROR(Kernel_SVC, "dst_address is not page-aligned (dst_address=0x{:016X}).",
+ dst_address);
+ return ERR_INVALID_ADDRESS;
+ }
+
+ if (size == 0 || !Common::Is4KBAligned(size)) {
+ LOG_ERROR(Kernel_SVC, "Size is zero or not page-aligned (size=0x{:016X})", size);
+ return ERR_INVALID_SIZE;
+ }
+
+ if (!IsValidAddressRange(dst_address, size)) {
+ LOG_ERROR(Kernel_SVC,
+ "Destination address range overflows the address space (dst_address=0x{:016X}, "
+ "size=0x{:016X}).",
+ dst_address, size);
+ return ERR_INVALID_ADDRESS_STATE;
+ }
+
+ if (!IsValidAddressRange(src_address, size)) {
+ LOG_ERROR(Kernel_SVC,
+ "Source address range overflows the address space (src_address=0x{:016X}, "
+ "size=0x{:016X}).",
+ src_address, size);
+ return ERR_INVALID_ADDRESS_STATE;
+ }
+
+ const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable();
+ auto process = handle_table.Get<Process>(process_handle);
+ if (!process) {
+ LOG_ERROR(Kernel_SVC, "Invalid process handle specified (handle=0x{:08X}).",
+ process_handle);
+ return ERR_INVALID_HANDLE;
+ }
+
+ auto& vm_manager = process->VMManager();
+ if (!vm_manager.IsWithinAddressSpace(src_address, size)) {
+ LOG_ERROR(Kernel_SVC,
+ "Source address range is not within the address space (src_address=0x{:016X}, "
+ "size=0x{:016X}).",
+ src_address, size);
+ return ERR_INVALID_ADDRESS_STATE;
+ }
+
+ if (!vm_manager.IsWithinASLRRegion(dst_address, size)) {
+ LOG_ERROR(Kernel_SVC,
+ "Destination address range is not within the ASLR region (dst_address=0x{:016X}, "
+ "size=0x{:016X}).",
+ dst_address, size);
+ return ERR_INVALID_MEMORY_RANGE;
+ }
+
+ return vm_manager.MapCodeMemory(dst_address, src_address, size);
+}
+
+ResultCode UnmapProcessCodeMemory(Core::System& system, Handle process_handle, u64 dst_address,
+ u64 src_address, u64 size) {
+ LOG_DEBUG(Kernel_SVC,
+ "called. process_handle=0x{:08X}, dst_address=0x{:016X}, src_address=0x{:016X}, "
+ "size=0x{:016X}",
+ process_handle, dst_address, src_address, size);
+
+ if (!Common::Is4KBAligned(dst_address)) {
+ LOG_ERROR(Kernel_SVC, "dst_address is not page-aligned (dst_address=0x{:016X}).",
+ dst_address);
+ return ERR_INVALID_ADDRESS;
+ }
+
+ if (!Common::Is4KBAligned(src_address)) {
+ LOG_ERROR(Kernel_SVC, "src_address is not page-aligned (src_address=0x{:016X}).",
+ src_address);
+ return ERR_INVALID_ADDRESS;
+ }
+
+ if (size == 0 || Common::Is4KBAligned(size)) {
+ LOG_ERROR(Kernel_SVC, "Size is zero or not page-aligned (size=0x{:016X}).", size);
+ return ERR_INVALID_SIZE;
+ }
+
+ if (!IsValidAddressRange(dst_address, size)) {
+ LOG_ERROR(Kernel_SVC,
+ "Destination address range overflows the address space (dst_address=0x{:016X}, "
+ "size=0x{:016X}).",
+ dst_address, size);
+ return ERR_INVALID_ADDRESS_STATE;
+ }
+
+ if (!IsValidAddressRange(src_address, size)) {
+ LOG_ERROR(Kernel_SVC,
+ "Source address range overflows the address space (src_address=0x{:016X}, "
+ "size=0x{:016X}).",
+ src_address, size);
+ return ERR_INVALID_ADDRESS_STATE;
+ }
+
+ const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable();
+ auto process = handle_table.Get<Process>(process_handle);
+ if (!process) {
+ LOG_ERROR(Kernel_SVC, "Invalid process handle specified (handle=0x{:08X}).",
+ process_handle);
+ return ERR_INVALID_HANDLE;
+ }
+
+ auto& vm_manager = process->VMManager();
+ if (!vm_manager.IsWithinAddressSpace(src_address, size)) {
+ LOG_ERROR(Kernel_SVC,
+ "Source address range is not within the address space (src_address=0x{:016X}, "
+ "size=0x{:016X}).",
+ src_address, size);
+ return ERR_INVALID_ADDRESS_STATE;
+ }
+
+ if (!vm_manager.IsWithinASLRRegion(dst_address, size)) {
+ LOG_ERROR(Kernel_SVC,
+ "Destination address range is not within the ASLR region (dst_address=0x{:016X}, "
+ "size=0x{:016X}).",
+ dst_address, size);
+ return ERR_INVALID_MEMORY_RANGE;
+ }
+
+ return vm_manager.UnmapCodeMemory(dst_address, src_address, size);
+}
+
/// Exits the current process
-static void ExitProcess() {
- auto* current_process = Core::CurrentProcess();
+static void ExitProcess(Core::System& system) {
+ auto* current_process = system.Kernel().CurrentProcess();
LOG_INFO(Kernel_SVC, "Process {} exiting", current_process->GetProcessID());
ASSERT_MSG(current_process->GetStatus() == ProcessStatus::Running,
@@ -1194,20 +1336,20 @@ static void ExitProcess() {
current_process->PrepareForTermination();
// Kill the current thread
- GetCurrentThread()->Stop();
+ system.CurrentScheduler().GetCurrentThread()->Stop();
- Core::System::GetInstance().PrepareReschedule();
+ system.PrepareReschedule();
}
/// Creates a new thread
-static ResultCode CreateThread(Handle* out_handle, VAddr entry_point, u64 arg, VAddr stack_top,
- u32 priority, s32 processor_id) {
+static ResultCode CreateThread(Core::System& system, Handle* out_handle, VAddr entry_point, u64 arg,
+ VAddr stack_top, u32 priority, s32 processor_id) {
LOG_TRACE(Kernel_SVC,
"called entrypoint=0x{:08X}, arg=0x{:08X}, stacktop=0x{:08X}, "
"threadpriority=0x{:08X}, processorid=0x{:08X} : created handle=0x{:08X}",
entry_point, arg, stack_top, priority, processor_id, *out_handle);
- auto* const current_process = Core::CurrentProcess();
+ auto* const current_process = system.Kernel().CurrentProcess();
if (processor_id == THREADPROCESSORID_IDEAL) {
// Set the target CPU to the one specified by the process.
@@ -1239,7 +1381,7 @@ static ResultCode CreateThread(Handle* out_handle, VAddr entry_point, u64 arg, V
}
const std::string name = fmt::format("thread-{:X}", entry_point);
- auto& kernel = Core::System::GetInstance().Kernel();
+ auto& kernel = system.Kernel();
CASCADE_RESULT(SharedPtr<Thread> thread,
Thread::Create(kernel, name, entry_point, priority, arg, processor_id, stack_top,
*current_process));
@@ -1253,16 +1395,16 @@ static ResultCode CreateThread(Handle* out_handle, VAddr entry_point, u64 arg, V
thread->SetGuestHandle(*new_guest_handle);
*out_handle = *new_guest_handle;
- Core::System::GetInstance().CpuCore(thread->GetProcessorID()).PrepareReschedule();
+ system.CpuCore(thread->GetProcessorID()).PrepareReschedule();
return RESULT_SUCCESS;
}
/// Starts the thread for the provided handle
-static ResultCode StartThread(Handle thread_handle) {
+static ResultCode StartThread(Core::System& system, Handle thread_handle) {
LOG_TRACE(Kernel_SVC, "called thread=0x{:08X}", thread_handle);
- const auto& handle_table = Core::CurrentProcess()->GetHandleTable();
+ const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable();
const SharedPtr<Thread> thread = handle_table.Get<Thread>(thread_handle);
if (!thread) {
LOG_ERROR(Kernel_SVC, "Thread handle does not exist, thread_handle=0x{:08X}",
@@ -1275,16 +1417,14 @@ static ResultCode StartThread(Handle thread_handle) {
thread->ResumeFromWait();
if (thread->GetStatus() == ThreadStatus::Ready) {
- Core::System::GetInstance().CpuCore(thread->GetProcessorID()).PrepareReschedule();
+ system.CpuCore(thread->GetProcessorID()).PrepareReschedule();
}
return RESULT_SUCCESS;
}
/// Called when a thread exits
-static void ExitThread() {
- auto& system = Core::System::GetInstance();
-
+static void ExitThread(Core::System& system) {
LOG_TRACE(Kernel_SVC, "called, pc=0x{:08X}", system.CurrentArmInterface().GetPC());
auto* const current_thread = system.CurrentScheduler().GetCurrentThread();
@@ -1294,7 +1434,7 @@ static void ExitThread() {
}
/// Sleep the current thread
-static void SleepThread(s64 nanoseconds) {
+static void SleepThread(Core::System& system, s64 nanoseconds) {
LOG_TRACE(Kernel_SVC, "called nanoseconds={}", nanoseconds);
enum class SleepType : s64 {
@@ -1303,7 +1443,6 @@ static void SleepThread(s64 nanoseconds) {
YieldAndWaitForLoadBalancing = -2,
};
- auto& system = Core::System::GetInstance();
auto& scheduler = system.CurrentScheduler();
auto* const current_thread = scheduler.GetCurrentThread();
@@ -1332,14 +1471,29 @@ static void SleepThread(s64 nanoseconds) {
}
/// Wait process wide key atomic
-static ResultCode WaitProcessWideKeyAtomic(VAddr mutex_addr, VAddr condition_variable_addr,
- Handle thread_handle, s64 nano_seconds) {
+static ResultCode WaitProcessWideKeyAtomic(Core::System& system, VAddr mutex_addr,
+ VAddr condition_variable_addr, Handle thread_handle,
+ s64 nano_seconds) {
LOG_TRACE(
Kernel_SVC,
"called mutex_addr={:X}, condition_variable_addr={:X}, thread_handle=0x{:08X}, timeout={}",
mutex_addr, condition_variable_addr, thread_handle, nano_seconds);
- auto* const current_process = Core::System::GetInstance().Kernel().CurrentProcess();
+ if (Memory::IsKernelVirtualAddress(mutex_addr)) {
+ LOG_ERROR(
+ Kernel_SVC,
+ "Given mutex address must not be within the kernel address space. address=0x{:016X}",
+ mutex_addr);
+ return ERR_INVALID_ADDRESS_STATE;
+ }
+
+ if (!Common::IsWordAligned(mutex_addr)) {
+ LOG_ERROR(Kernel_SVC, "Given mutex address must be word-aligned. address=0x{:016X}",
+ mutex_addr);
+ return ERR_INVALID_ADDRESS;
+ }
+
+ auto* const current_process = system.Kernel().CurrentProcess();
const auto& handle_table = current_process->GetHandleTable();
SharedPtr<Thread> thread = handle_table.Get<Thread>(thread_handle);
ASSERT(thread);
@@ -1349,7 +1503,7 @@ static ResultCode WaitProcessWideKeyAtomic(VAddr mutex_addr, VAddr condition_var
return release_result;
}
- SharedPtr<Thread> current_thread = GetCurrentThread();
+ SharedPtr<Thread> current_thread = system.CurrentScheduler().GetCurrentThread();
current_thread->SetCondVarWaitAddress(condition_variable_addr);
current_thread->SetMutexWaitAddress(mutex_addr);
current_thread->SetWaitHandle(thread_handle);
@@ -1360,19 +1514,20 @@ static ResultCode WaitProcessWideKeyAtomic(VAddr mutex_addr, VAddr condition_var
// Note: Deliberately don't attempt to inherit the lock owner's priority.
- Core::System::GetInstance().CpuCore(current_thread->GetProcessorID()).PrepareReschedule();
+ system.CpuCore(current_thread->GetProcessorID()).PrepareReschedule();
return RESULT_SUCCESS;
}
/// Signal process wide key
-static ResultCode SignalProcessWideKey(VAddr condition_variable_addr, s32 target) {
+static ResultCode SignalProcessWideKey(Core::System& system, VAddr condition_variable_addr,
+ s32 target) {
LOG_TRACE(Kernel_SVC, "called, condition_variable_addr=0x{:X}, target=0x{:08X}",
condition_variable_addr, target);
- const auto RetrieveWaitingThreads = [](std::size_t core_index,
- std::vector<SharedPtr<Thread>>& waiting_threads,
- VAddr condvar_addr) {
- const auto& scheduler = Core::System::GetInstance().Scheduler(core_index);
+ const auto RetrieveWaitingThreads = [&system](std::size_t core_index,
+ std::vector<SharedPtr<Thread>>& waiting_threads,
+ VAddr condvar_addr) {
+ const auto& scheduler = system.Scheduler(core_index);
const auto& thread_list = scheduler.GetThreadList();
for (const auto& thread : thread_list) {
@@ -1411,9 +1566,8 @@ static ResultCode SignalProcessWideKey(VAddr condition_variable_addr, s32 target
// liberate Cond Var Thread.
thread->SetCondVarWaitAddress(0);
- std::size_t current_core = Core::System::GetInstance().CurrentCoreIndex();
-
- auto& monitor = Core::System::GetInstance().Monitor();
+ const std::size_t current_core = system.CurrentCoreIndex();
+ auto& monitor = system.Monitor();
// Atomically read the value of the mutex.
u32 mutex_val = 0;
@@ -1442,7 +1596,7 @@ static ResultCode SignalProcessWideKey(VAddr condition_variable_addr, s32 target
thread->SetLockOwner(nullptr);
thread->SetMutexWaitAddress(0);
thread->SetWaitHandle(0);
- Core::System::GetInstance().CpuCore(thread->GetProcessorID()).PrepareReschedule();
+ system.CpuCore(thread->GetProcessorID()).PrepareReschedule();
} else {
// Atomically signal that the mutex now has a waiting thread.
do {
@@ -1458,7 +1612,7 @@ static ResultCode SignalProcessWideKey(VAddr condition_variable_addr, s32 target
// The mutex is already owned by some other thread, make this thread wait on it.
const Handle owner_handle = static_cast<Handle>(mutex_val & Mutex::MutexOwnerMask);
- const auto& handle_table = Core::CurrentProcess()->GetHandleTable();
+ const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable();
auto owner = handle_table.Get<Thread>(owner_handle);
ASSERT(owner);
ASSERT(thread->GetStatus() == ThreadStatus::WaitCondVar);
@@ -1473,14 +1627,17 @@ static ResultCode SignalProcessWideKey(VAddr condition_variable_addr, s32 target
}
// Wait for an address (via Address Arbiter)
-static ResultCode WaitForAddress(VAddr address, u32 type, s32 value, s64 timeout) {
+static ResultCode WaitForAddress(Core::System& system, VAddr address, u32 type, s32 value,
+ s64 timeout) {
LOG_WARNING(Kernel_SVC, "called, address=0x{:X}, type=0x{:X}, value=0x{:X}, timeout={}",
address, type, value, timeout);
+
// If the passed address is a kernel virtual address, return invalid memory state.
if (Memory::IsKernelVirtualAddress(address)) {
LOG_ERROR(Kernel_SVC, "Address is a kernel virtual address, address={:016X}", address);
return ERR_INVALID_ADDRESS_STATE;
}
+
// If the address is not properly aligned to 4 bytes, return invalid address.
if (!Common::IsWordAligned(address)) {
LOG_ERROR(Kernel_SVC, "Address is not word aligned, address={:016X}", address);
@@ -1488,20 +1645,22 @@ static ResultCode WaitForAddress(VAddr address, u32 type, s32 value, s64 timeout
}
const auto arbitration_type = static_cast<AddressArbiter::ArbitrationType>(type);
- auto& address_arbiter =
- Core::System::GetInstance().Kernel().CurrentProcess()->GetAddressArbiter();
+ auto& address_arbiter = system.Kernel().CurrentProcess()->GetAddressArbiter();
return address_arbiter.WaitForAddress(address, arbitration_type, value, timeout);
}
// Signals to an address (via Address Arbiter)
-static ResultCode SignalToAddress(VAddr address, u32 type, s32 value, s32 num_to_wake) {
+static ResultCode SignalToAddress(Core::System& system, VAddr address, u32 type, s32 value,
+ s32 num_to_wake) {
LOG_WARNING(Kernel_SVC, "called, address=0x{:X}, type=0x{:X}, value=0x{:X}, num_to_wake=0x{:X}",
address, type, value, num_to_wake);
+
// If the passed address is a kernel virtual address, return invalid memory state.
if (Memory::IsKernelVirtualAddress(address)) {
LOG_ERROR(Kernel_SVC, "Address is a kernel virtual address, address={:016X}", address);
return ERR_INVALID_ADDRESS_STATE;
}
+
// If the address is not properly aligned to 4 bytes, return invalid address.
if (!Common::IsWordAligned(address)) {
LOG_ERROR(Kernel_SVC, "Address is not word aligned, address={:016X}", address);
@@ -1509,16 +1668,15 @@ static ResultCode SignalToAddress(VAddr address, u32 type, s32 value, s32 num_to
}
const auto signal_type = static_cast<AddressArbiter::SignalType>(type);
- auto& address_arbiter =
- Core::System::GetInstance().Kernel().CurrentProcess()->GetAddressArbiter();
+ auto& address_arbiter = system.Kernel().CurrentProcess()->GetAddressArbiter();
return address_arbiter.SignalToAddress(address, signal_type, value, num_to_wake);
}
/// This returns the total CPU ticks elapsed since the CPU was powered-on
-static u64 GetSystemTick() {
+static u64 GetSystemTick(Core::System& system) {
LOG_TRACE(Kernel_SVC, "called");
- auto& core_timing = Core::System::GetInstance().CoreTiming();
+ auto& core_timing = system.CoreTiming();
const u64 result{core_timing.GetTicks()};
// Advance time to defeat dumb games that busy-wait for the frame to end.
@@ -1528,18 +1686,18 @@ static u64 GetSystemTick() {
}
/// Close a handle
-static ResultCode CloseHandle(Handle handle) {
+static ResultCode CloseHandle(Core::System& system, Handle handle) {
LOG_TRACE(Kernel_SVC, "Closing handle 0x{:08X}", handle);
- auto& handle_table = Core::CurrentProcess()->GetHandleTable();
+ auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable();
return handle_table.Close(handle);
}
/// Clears the signaled state of an event or process.
-static ResultCode ResetSignal(Handle handle) {
+static ResultCode ResetSignal(Core::System& system, Handle handle) {
LOG_DEBUG(Kernel_SVC, "called handle 0x{:08X}", handle);
- const auto& handle_table = Core::CurrentProcess()->GetHandleTable();
+ const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable();
auto event = handle_table.Get<ReadableEvent>(handle);
if (event) {
@@ -1556,7 +1714,8 @@ static ResultCode ResetSignal(Handle handle) {
}
/// Creates a TransferMemory object
-static ResultCode CreateTransferMemory(Handle* handle, VAddr addr, u64 size, u32 permissions) {
+static ResultCode CreateTransferMemory(Core::System& system, Handle* handle, VAddr addr, u64 size,
+ u32 permissions) {
LOG_DEBUG(Kernel_SVC, "called addr=0x{:X}, size=0x{:X}, perms=0x{:08X}", addr, size,
permissions);
@@ -1584,7 +1743,7 @@ static ResultCode CreateTransferMemory(Handle* handle, VAddr addr, u64 size, u32
return ERR_INVALID_MEMORY_PERMISSIONS;
}
- auto& kernel = Core::System::GetInstance().Kernel();
+ auto& kernel = system.Kernel();
auto transfer_mem_handle = TransferMemory::Create(kernel, addr, size, perms);
auto& handle_table = kernel.CurrentProcess()->GetHandleTable();
@@ -1597,7 +1756,8 @@ static ResultCode CreateTransferMemory(Handle* handle, VAddr addr, u64 size, u32
return RESULT_SUCCESS;
}
-static ResultCode MapTransferMemory(Handle handle, VAddr address, u64 size, u32 permission_raw) {
+static ResultCode MapTransferMemory(Core::System& system, Handle handle, VAddr address, u64 size,
+ u32 permission_raw) {
LOG_DEBUG(Kernel_SVC,
"called. handle=0x{:08X}, address=0x{:016X}, size=0x{:016X}, permissions=0x{:08X}",
handle, address, size, permission_raw);
@@ -1631,7 +1791,7 @@ static ResultCode MapTransferMemory(Handle handle, VAddr address, u64 size, u32
return ERR_INVALID_STATE;
}
- const auto& kernel = Core::System::GetInstance().Kernel();
+ const auto& kernel = system.Kernel();
const auto* const current_process = kernel.CurrentProcess();
const auto& handle_table = current_process->GetHandleTable();
@@ -1653,7 +1813,8 @@ static ResultCode MapTransferMemory(Handle handle, VAddr address, u64 size, u32
return transfer_memory->MapMemory(address, size, permissions);
}
-static ResultCode UnmapTransferMemory(Handle handle, VAddr address, u64 size) {
+static ResultCode UnmapTransferMemory(Core::System& system, Handle handle, VAddr address,
+ u64 size) {
LOG_DEBUG(Kernel_SVC, "called. handle=0x{:08X}, address=0x{:016X}, size=0x{:016X}", handle,
address, size);
@@ -1678,7 +1839,7 @@ static ResultCode UnmapTransferMemory(Handle handle, VAddr address, u64 size) {
return ERR_INVALID_ADDRESS_STATE;
}
- const auto& kernel = Core::System::GetInstance().Kernel();
+ const auto& kernel = system.Kernel();
const auto* const current_process = kernel.CurrentProcess();
const auto& handle_table = current_process->GetHandleTable();
@@ -1700,10 +1861,11 @@ static ResultCode UnmapTransferMemory(Handle handle, VAddr address, u64 size) {
return transfer_memory->UnmapMemory(address, size);
}
-static ResultCode GetThreadCoreMask(Handle thread_handle, u32* core, u64* mask) {
+static ResultCode GetThreadCoreMask(Core::System& system, Handle thread_handle, u32* core,
+ u64* mask) {
LOG_TRACE(Kernel_SVC, "called, handle=0x{:08X}", thread_handle);
- const auto& handle_table = Core::CurrentProcess()->GetHandleTable();
+ const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable();
const SharedPtr<Thread> thread = handle_table.Get<Thread>(thread_handle);
if (!thread) {
LOG_ERROR(Kernel_SVC, "Thread handle does not exist, thread_handle=0x{:08X}",
@@ -1717,11 +1879,12 @@ static ResultCode GetThreadCoreMask(Handle thread_handle, u32* core, u64* mask)
return RESULT_SUCCESS;
}
-static ResultCode SetThreadCoreMask(Handle thread_handle, u32 core, u64 mask) {
+static ResultCode SetThreadCoreMask(Core::System& system, Handle thread_handle, u32 core,
+ u64 mask) {
LOG_DEBUG(Kernel_SVC, "called, handle=0x{:08X}, mask=0x{:016X}, core=0x{:X}", thread_handle,
mask, core);
- const auto& handle_table = Core::CurrentProcess()->GetHandleTable();
+ const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable();
const SharedPtr<Thread> thread = handle_table.Get<Thread>(thread_handle);
if (!thread) {
LOG_ERROR(Kernel_SVC, "Thread handle does not exist, thread_handle=0x{:08X}",
@@ -1766,8 +1929,8 @@ static ResultCode SetThreadCoreMask(Handle thread_handle, u32 core, u64 mask) {
return RESULT_SUCCESS;
}
-static ResultCode CreateSharedMemory(Handle* handle, u64 size, u32 local_permissions,
- u32 remote_permissions) {
+static ResultCode CreateSharedMemory(Core::System& system, Handle* handle, u64 size,
+ u32 local_permissions, u32 remote_permissions) {
LOG_TRACE(Kernel_SVC, "called, size=0x{:X}, localPerms=0x{:08X}, remotePerms=0x{:08X}", size,
local_permissions, remote_permissions);
if (size == 0) {
@@ -1803,7 +1966,7 @@ static ResultCode CreateSharedMemory(Handle* handle, u64 size, u32 local_permiss
return ERR_INVALID_MEMORY_PERMISSIONS;
}
- auto& kernel = Core::System::GetInstance().Kernel();
+ auto& kernel = system.Kernel();
auto process = kernel.CurrentProcess();
auto& handle_table = process->GetHandleTable();
auto shared_mem_handle = SharedMemory::Create(kernel, process, size, local_perms, remote_perms);
@@ -1812,10 +1975,10 @@ static ResultCode CreateSharedMemory(Handle* handle, u64 size, u32 local_permiss
return RESULT_SUCCESS;
}
-static ResultCode CreateEvent(Handle* write_handle, Handle* read_handle) {
+static ResultCode CreateEvent(Core::System& system, Handle* write_handle, Handle* read_handle) {
LOG_DEBUG(Kernel_SVC, "called");
- auto& kernel = Core::System::GetInstance().Kernel();
+ auto& kernel = system.Kernel();
const auto [readable_event, writable_event] =
WritableEvent::CreateEventPair(kernel, ResetType::Sticky, "CreateEvent");
@@ -1840,10 +2003,10 @@ static ResultCode CreateEvent(Handle* write_handle, Handle* read_handle) {
return RESULT_SUCCESS;
}
-static ResultCode ClearEvent(Handle handle) {
+static ResultCode ClearEvent(Core::System& system, Handle handle) {
LOG_TRACE(Kernel_SVC, "called, event=0x{:08X}", handle);
- const auto& handle_table = Core::CurrentProcess()->GetHandleTable();
+ const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable();
auto writable_event = handle_table.Get<WritableEvent>(handle);
if (writable_event) {
@@ -1861,10 +2024,10 @@ static ResultCode ClearEvent(Handle handle) {
return ERR_INVALID_HANDLE;
}
-static ResultCode SignalEvent(Handle handle) {
+static ResultCode SignalEvent(Core::System& system, Handle handle) {
LOG_DEBUG(Kernel_SVC, "called. Handle=0x{:08X}", handle);
- HandleTable& handle_table = Core::CurrentProcess()->GetHandleTable();
+ HandleTable& handle_table = system.Kernel().CurrentProcess()->GetHandleTable();
auto writable_event = handle_table.Get<WritableEvent>(handle);
if (!writable_event) {
@@ -1876,7 +2039,7 @@ static ResultCode SignalEvent(Handle handle) {
return RESULT_SUCCESS;
}
-static ResultCode GetProcessInfo(u64* out, Handle process_handle, u32 type) {
+static ResultCode GetProcessInfo(Core::System& system, u64* out, Handle process_handle, u32 type) {
LOG_DEBUG(Kernel_SVC, "called, handle=0x{:08X}, type=0x{:X}", process_handle, type);
// This function currently only allows retrieving a process' status.
@@ -1884,7 +2047,7 @@ static ResultCode GetProcessInfo(u64* out, Handle process_handle, u32 type) {
Status,
};
- const auto& handle_table = Core::CurrentProcess()->GetHandleTable();
+ const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable();
const auto process = handle_table.Get<Process>(process_handle);
if (!process) {
LOG_ERROR(Kernel_SVC, "Process handle does not exist, process_handle=0x{:08X}",
@@ -1902,10 +2065,10 @@ static ResultCode GetProcessInfo(u64* out, Handle process_handle, u32 type) {
return RESULT_SUCCESS;
}
-static ResultCode CreateResourceLimit(Handle* out_handle) {
+static ResultCode CreateResourceLimit(Core::System& system, Handle* out_handle) {
LOG_DEBUG(Kernel_SVC, "called");
- auto& kernel = Core::System::GetInstance().Kernel();
+ auto& kernel = system.Kernel();
auto resource_limit = ResourceLimit::Create(kernel);
auto* const current_process = kernel.CurrentProcess();
@@ -1920,11 +2083,11 @@ static ResultCode CreateResourceLimit(Handle* out_handle) {
return RESULT_SUCCESS;
}
-static ResultCode GetResourceLimitLimitValue(u64* out_value, Handle resource_limit,
- u32 resource_type) {
+static ResultCode GetResourceLimitLimitValue(Core::System& system, u64* out_value,
+ Handle resource_limit, u32 resource_type) {
LOG_DEBUG(Kernel_SVC, "called. Handle={:08X}, Resource type={}", resource_limit, resource_type);
- const auto limit_value = RetrieveResourceLimitValue(resource_limit, resource_type,
+ const auto limit_value = RetrieveResourceLimitValue(system, resource_limit, resource_type,
ResourceLimitValueType::LimitValue);
if (limit_value.Failed()) {
return limit_value.Code();
@@ -1934,11 +2097,11 @@ static ResultCode GetResourceLimitLimitValue(u64* out_value, Handle resource_lim
return RESULT_SUCCESS;
}
-static ResultCode GetResourceLimitCurrentValue(u64* out_value, Handle resource_limit,
- u32 resource_type) {
+static ResultCode GetResourceLimitCurrentValue(Core::System& system, u64* out_value,
+ Handle resource_limit, u32 resource_type) {
LOG_DEBUG(Kernel_SVC, "called. Handle={:08X}, Resource type={}", resource_limit, resource_type);
- const auto current_value = RetrieveResourceLimitValue(resource_limit, resource_type,
+ const auto current_value = RetrieveResourceLimitValue(system, resource_limit, resource_type,
ResourceLimitValueType::CurrentValue);
if (current_value.Failed()) {
return current_value.Code();
@@ -1948,7 +2111,8 @@ static ResultCode GetResourceLimitCurrentValue(u64* out_value, Handle resource_l
return RESULT_SUCCESS;
}
-static ResultCode SetResourceLimitLimitValue(Handle resource_limit, u32 resource_type, u64 value) {
+static ResultCode SetResourceLimitLimitValue(Core::System& system, Handle resource_limit,
+ u32 resource_type, u64 value) {
LOG_DEBUG(Kernel_SVC, "called. Handle={:08X}, Resource type={}, Value={}", resource_limit,
resource_type, value);
@@ -1958,8 +2122,7 @@ static ResultCode SetResourceLimitLimitValue(Handle resource_limit, u32 resource
return ERR_INVALID_ENUM_VALUE;
}
- auto& kernel = Core::System::GetInstance().Kernel();
- auto* const current_process = kernel.CurrentProcess();
+ auto* const current_process = system.Kernel().CurrentProcess();
ASSERT(current_process != nullptr);
auto resource_limit_object =
@@ -1983,8 +2146,8 @@ static ResultCode SetResourceLimitLimitValue(Handle resource_limit, u32 resource
return RESULT_SUCCESS;
}
-static ResultCode GetProcessList(u32* out_num_processes, VAddr out_process_ids,
- u32 out_process_ids_size) {
+static ResultCode GetProcessList(Core::System& system, u32* out_num_processes,
+ VAddr out_process_ids, u32 out_process_ids_size) {
LOG_DEBUG(Kernel_SVC, "called. out_process_ids=0x{:016X}, out_process_ids_size={}",
out_process_ids, out_process_ids_size);
@@ -1996,7 +2159,7 @@ static ResultCode GetProcessList(u32* out_num_processes, VAddr out_process_ids,
return ERR_OUT_OF_RANGE;
}
- const auto& kernel = Core::System::GetInstance().Kernel();
+ const auto& kernel = system.Kernel();
const auto& vm_manager = kernel.CurrentProcess()->VMManager();
const auto total_copy_size = out_process_ids_size * sizeof(u64);
@@ -2020,8 +2183,8 @@ static ResultCode GetProcessList(u32* out_num_processes, VAddr out_process_ids,
return RESULT_SUCCESS;
}
-ResultCode GetThreadList(u32* out_num_threads, VAddr out_thread_ids, u32 out_thread_ids_size,
- Handle debug_handle) {
+ResultCode GetThreadList(Core::System& system, u32* out_num_threads, VAddr out_thread_ids,
+ u32 out_thread_ids_size, Handle debug_handle) {
// TODO: Handle this case when debug events are supported.
UNIMPLEMENTED_IF(debug_handle != InvalidHandle);
@@ -2035,7 +2198,7 @@ ResultCode GetThreadList(u32* out_num_threads, VAddr out_thread_ids, u32 out_thr
return ERR_OUT_OF_RANGE;
}
- const auto* const current_process = Core::System::GetInstance().Kernel().CurrentProcess();
+ const auto* const current_process = system.Kernel().CurrentProcess();
const auto& vm_manager = current_process->VMManager();
const auto total_copy_size = out_thread_ids_size * sizeof(u64);
@@ -2062,7 +2225,7 @@ ResultCode GetThreadList(u32* out_num_threads, VAddr out_thread_ids, u32 out_thr
namespace {
struct FunctionDef {
- using Func = void();
+ using Func = void(Core::System&);
u32 id;
Func* func;
@@ -2190,8 +2353,8 @@ static const FunctionDef SVC_Table[] = {
{0x74, nullptr, "MapProcessMemory"},
{0x75, nullptr, "UnmapProcessMemory"},
{0x76, SvcWrap<QueryProcessMemory>, "QueryProcessMemory"},
- {0x77, nullptr, "MapProcessCodeMemory"},
- {0x78, nullptr, "UnmapProcessCodeMemory"},
+ {0x77, SvcWrap<MapProcessCodeMemory>, "MapProcessCodeMemory"},
+ {0x78, SvcWrap<UnmapProcessCodeMemory>, "UnmapProcessCodeMemory"},
{0x79, nullptr, "CreateProcess"},
{0x7A, nullptr, "StartProcess"},
{0x7B, nullptr, "TerminateProcess"},
@@ -2211,7 +2374,7 @@ static const FunctionDef* GetSVCInfo(u32 func_num) {
MICROPROFILE_DEFINE(Kernel_SVC, "Kernel", "SVC", MP_RGB(70, 200, 70));
-void CallSVC(u32 immediate) {
+void CallSVC(Core::System& system, u32 immediate) {
MICROPROFILE_SCOPE(Kernel_SVC);
// Lock the global kernel mutex when we enter the kernel HLE.
@@ -2220,7 +2383,7 @@ void CallSVC(u32 immediate) {
const FunctionDef* info = GetSVCInfo(immediate);
if (info) {
if (info->func) {
- info->func();
+ info->func(system);
} else {
LOG_CRITICAL(Kernel_SVC, "Unimplemented SVC function {}(..)", info->name);
}
diff --git a/src/core/hle/kernel/svc.h b/src/core/hle/kernel/svc.h
index c37ae0f98..c5539ac1c 100644
--- a/src/core/hle/kernel/svc.h
+++ b/src/core/hle/kernel/svc.h
@@ -6,8 +6,12 @@
#include "common/common_types.h"
+namespace Core {
+class System;
+}
+
namespace Kernel {
-void CallSVC(u32 immediate);
+void CallSVC(Core::System& system, u32 immediate);
} // namespace Kernel
diff --git a/src/core/hle/kernel/svc_wrap.h b/src/core/hle/kernel/svc_wrap.h
index b3733680f..865473c6f 100644
--- a/src/core/hle/kernel/svc_wrap.h
+++ b/src/core/hle/kernel/svc_wrap.h
@@ -11,278 +11,319 @@
namespace Kernel {
-static inline u64 Param(int n) {
- return Core::CurrentArmInterface().GetReg(n);
+static inline u64 Param(const Core::System& system, int n) {
+ return system.CurrentArmInterface().GetReg(n);
}
/**
* HLE a function return from the current ARM userland process
- * @param res Result to return
+ * @param system System context
+ * @param result Result to return
*/
-static inline void FuncReturn(u64 res) {
- Core::CurrentArmInterface().SetReg(0, res);
+static inline void FuncReturn(Core::System& system, u64 result) {
+ system.CurrentArmInterface().SetReg(0, result);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
// Function wrappers that return type ResultCode
-template <ResultCode func(u64)>
-void SvcWrap() {
- FuncReturn(func(Param(0)).raw);
+template <ResultCode func(Core::System&, u64)>
+void SvcWrap(Core::System& system) {
+ FuncReturn(system, func(system, Param(system, 0)).raw);
}
-template <ResultCode func(u32)>
-void SvcWrap() {
- FuncReturn(func(static_cast<u32>(Param(0))).raw);
+template <ResultCode func(Core::System&, u32)>
+void SvcWrap(Core::System& system) {
+ FuncReturn(system, func(system, static_cast<u32>(Param(system, 0))).raw);
}
-template <ResultCode func(u32, u32)>
-void SvcWrap() {
- FuncReturn(func(static_cast<u32>(Param(0)), static_cast<u32>(Param(1))).raw);
+template <ResultCode func(Core::System&, u32, u32)>
+void SvcWrap(Core::System& system) {
+ FuncReturn(
+ system,
+ func(system, static_cast<u32>(Param(system, 0)), static_cast<u32>(Param(system, 1))).raw);
+}
+
+template <ResultCode func(Core::System&, u32, u64, u64, u64)>
+void SvcWrap(Core::System& system) {
+ FuncReturn(system, func(system, static_cast<u32>(Param(system, 0)), Param(system, 1),
+ Param(system, 2), Param(system, 3))
+ .raw);
}
-template <ResultCode func(u32*)>
-void SvcWrap() {
+template <ResultCode func(Core::System&, u32*)>
+void SvcWrap(Core::System& system) {
u32 param = 0;
- const u32 retval = func(&param).raw;
- Core::CurrentArmInterface().SetReg(1, param);
- FuncReturn(retval);
+ const u32 retval = func(system, &param).raw;
+ system.CurrentArmInterface().SetReg(1, param);
+ FuncReturn(system, retval);
}
-template <ResultCode func(u32*, u32)>
-void SvcWrap() {
+template <ResultCode func(Core::System&, u32*, u32)>
+void SvcWrap(Core::System& system) {
u32 param_1 = 0;
- u32 retval = func(&param_1, static_cast<u32>(Param(1))).raw;
- Core::CurrentArmInterface().SetReg(1, param_1);
- FuncReturn(retval);
+ const u32 retval = func(system, &param_1, static_cast<u32>(Param(system, 1))).raw;
+ system.CurrentArmInterface().SetReg(1, param_1);
+ FuncReturn(system, retval);
}
-template <ResultCode func(u32*, u32*)>
-void SvcWrap() {
+template <ResultCode func(Core::System&, u32*, u32*)>
+void SvcWrap(Core::System& system) {
u32 param_1 = 0;
u32 param_2 = 0;
- const u32 retval = func(&param_1, &param_2).raw;
+ const u32 retval = func(system, &param_1, &param_2).raw;
- auto& arm_interface = Core::CurrentArmInterface();
+ auto& arm_interface = system.CurrentArmInterface();
arm_interface.SetReg(1, param_1);
arm_interface.SetReg(2, param_2);
- FuncReturn(retval);
+ FuncReturn(system, retval);
}
-template <ResultCode func(u32*, u64)>
-void SvcWrap() {
+template <ResultCode func(Core::System&, u32*, u64)>
+void SvcWrap(Core::System& system) {
u32 param_1 = 0;
- const u32 retval = func(&param_1, Param(1)).raw;
- Core::CurrentArmInterface().SetReg(1, param_1);
- FuncReturn(retval);
+ const u32 retval = func(system, &param_1, Param(system, 1)).raw;
+ system.CurrentArmInterface().SetReg(1, param_1);
+ FuncReturn(system, retval);
}
-template <ResultCode func(u32*, u64, u32)>
-void SvcWrap() {
+template <ResultCode func(Core::System&, u32*, u64, u32)>
+void SvcWrap(Core::System& system) {
u32 param_1 = 0;
- const u32 retval = func(&param_1, Param(1), static_cast<u32>(Param(2))).raw;
- Core::CurrentArmInterface().SetReg(1, param_1);
- FuncReturn(retval);
+ const u32 retval =
+ func(system, &param_1, Param(system, 1), static_cast<u32>(Param(system, 2))).raw;
+
+ system.CurrentArmInterface().SetReg(1, param_1);
+ FuncReturn(system, retval);
}
-template <ResultCode func(u64*, u32)>
-void SvcWrap() {
+template <ResultCode func(Core::System&, u64*, u32)>
+void SvcWrap(Core::System& system) {
u64 param_1 = 0;
- const u32 retval = func(&param_1, static_cast<u32>(Param(1))).raw;
- Core::CurrentArmInterface().SetReg(1, param_1);
- FuncReturn(retval);
+ const u32 retval = func(system, &param_1, static_cast<u32>(Param(system, 1))).raw;
+
+ system.CurrentArmInterface().SetReg(1, param_1);
+ FuncReturn(system, retval);
}
-template <ResultCode func(u64, s32)>
-void SvcWrap() {
- FuncReturn(func(Param(0), static_cast<s32>(Param(1))).raw);
+template <ResultCode func(Core::System&, u64, s32)>
+void SvcWrap(Core::System& system) {
+ FuncReturn(system, func(system, Param(system, 0), static_cast<s32>(Param(system, 1))).raw);
}
-template <ResultCode func(u64, u32)>
-void SvcWrap() {
- FuncReturn(func(Param(0), static_cast<u32>(Param(1))).raw);
+template <ResultCode func(Core::System&, u64, u32)>
+void SvcWrap(Core::System& system) {
+ FuncReturn(system, func(system, Param(system, 0), static_cast<u32>(Param(system, 1))).raw);
}
-template <ResultCode func(u64*, u64)>
-void SvcWrap() {
+template <ResultCode func(Core::System&, u64*, u64)>
+void SvcWrap(Core::System& system) {
u64 param_1 = 0;
- u32 retval = func(&param_1, Param(1)).raw;
- Core::CurrentArmInterface().SetReg(1, param_1);
- FuncReturn(retval);
+ const u32 retval = func(system, &param_1, Param(system, 1)).raw;
+
+ system.CurrentArmInterface().SetReg(1, param_1);
+ FuncReturn(system, retval);
}
-template <ResultCode func(u64*, u32, u32)>
-void SvcWrap() {
+template <ResultCode func(Core::System&, u64*, u32, u32)>
+void SvcWrap(Core::System& system) {
u64 param_1 = 0;
- u32 retval = func(&param_1, static_cast<u32>(Param(1)), static_cast<u32>(Param(2))).raw;
- Core::CurrentArmInterface().SetReg(1, param_1);
- FuncReturn(retval);
+ const u32 retval = func(system, &param_1, static_cast<u32>(Param(system, 1)),
+ static_cast<u32>(Param(system, 2)))
+ .raw;
+
+ system.CurrentArmInterface().SetReg(1, param_1);
+ FuncReturn(system, retval);
}
-template <ResultCode func(u32, u64)>
-void SvcWrap() {
- FuncReturn(func(static_cast<u32>(Param(0)), Param(1)).raw);
+template <ResultCode func(Core::System&, u32, u64)>
+void SvcWrap(Core::System& system) {
+ FuncReturn(system, func(system, static_cast<u32>(Param(system, 0)), Param(system, 1)).raw);
}
-template <ResultCode func(u32, u32, u64)>
-void SvcWrap() {
- FuncReturn(func(static_cast<u32>(Param(0)), static_cast<u32>(Param(1)), Param(2)).raw);
+template <ResultCode func(Core::System&, u32, u32, u64)>
+void SvcWrap(Core::System& system) {
+ FuncReturn(system, func(system, static_cast<u32>(Param(system, 0)),
+ static_cast<u32>(Param(system, 1)), Param(system, 2))
+ .raw);
}
-template <ResultCode func(u32, u32*, u64*)>
-void SvcWrap() {
+template <ResultCode func(Core::System&, u32, u32*, u64*)>
+void SvcWrap(Core::System& system) {
u32 param_1 = 0;
u64 param_2 = 0;
- ResultCode retval = func(static_cast<u32>(Param(2)), &param_1, &param_2);
- Core::CurrentArmInterface().SetReg(1, param_1);
- Core::CurrentArmInterface().SetReg(2, param_2);
- FuncReturn(retval.raw);
-}
+ const ResultCode retval = func(system, static_cast<u32>(Param(system, 2)), &param_1, &param_2);
-template <ResultCode func(u64, u64, u32, u32)>
-void SvcWrap() {
- FuncReturn(
- func(Param(0), Param(1), static_cast<u32>(Param(2)), static_cast<u32>(Param(3))).raw);
+ system.CurrentArmInterface().SetReg(1, param_1);
+ system.CurrentArmInterface().SetReg(2, param_2);
+ FuncReturn(system, retval.raw);
}
-template <ResultCode func(u64, u64, u32, u64)>
-void SvcWrap() {
- FuncReturn(func(Param(0), Param(1), static_cast<u32>(Param(2)), Param(3)).raw);
+template <ResultCode func(Core::System&, u64, u64, u32, u32)>
+void SvcWrap(Core::System& system) {
+ FuncReturn(system, func(system, Param(system, 0), Param(system, 1),
+ static_cast<u32>(Param(system, 2)), static_cast<u32>(Param(system, 3)))
+ .raw);
}
-template <ResultCode func(u32, u64, u32)>
-void SvcWrap() {
- FuncReturn(func(static_cast<u32>(Param(0)), Param(1), static_cast<u32>(Param(2))).raw);
+template <ResultCode func(Core::System&, u64, u64, u32, u64)>
+void SvcWrap(Core::System& system) {
+ FuncReturn(system, func(system, Param(system, 0), Param(system, 1),
+ static_cast<u32>(Param(system, 2)), Param(system, 3))
+ .raw);
}
-template <ResultCode func(u64, u64, u64)>
-void SvcWrap() {
- FuncReturn(func(Param(0), Param(1), Param(2)).raw);
+template <ResultCode func(Core::System&, u32, u64, u32)>
+void SvcWrap(Core::System& system) {
+ FuncReturn(system, func(system, static_cast<u32>(Param(system, 0)), Param(system, 1),
+ static_cast<u32>(Param(system, 2)))
+ .raw);
}
-template <ResultCode func(u64, u64, u32)>
-void SvcWrap() {
- FuncReturn(func(Param(0), Param(1), static_cast<u32>(Param(2))).raw);
+template <ResultCode func(Core::System&, u64, u64, u64)>
+void SvcWrap(Core::System& system) {
+ FuncReturn(system, func(system, Param(system, 0), Param(system, 1), Param(system, 2)).raw);
}
-template <ResultCode func(u32, u64, u64, u32)>
-void SvcWrap() {
+template <ResultCode func(Core::System&, u64, u64, u32)>
+void SvcWrap(Core::System& system) {
FuncReturn(
- func(static_cast<u32>(Param(0)), Param(1), Param(2), static_cast<u32>(Param(3))).raw);
+ system,
+ func(system, Param(system, 0), Param(system, 1), static_cast<u32>(Param(system, 2))).raw);
}
-template <ResultCode func(u32, u64, u64)>
-void SvcWrap() {
- FuncReturn(func(static_cast<u32>(Param(0)), Param(1), Param(2)).raw);
+template <ResultCode func(Core::System&, u32, u64, u64, u32)>
+void SvcWrap(Core::System& system) {
+ FuncReturn(system, func(system, static_cast<u32>(Param(system, 0)), Param(system, 1),
+ Param(system, 2), static_cast<u32>(Param(system, 3)))
+ .raw);
}
-template <ResultCode func(u32*, u64, u64, s64)>
-void SvcWrap() {
+template <ResultCode func(Core::System&, u32, u64, u64)>
+void SvcWrap(Core::System& system) {
+ FuncReturn(
+ system,
+ func(system, static_cast<u32>(Param(system, 0)), Param(system, 1), Param(system, 2)).raw);
+}
+
+template <ResultCode func(Core::System&, u32*, u64, u64, s64)>
+void SvcWrap(Core::System& system) {
u32 param_1 = 0;
- ResultCode retval =
- func(&param_1, Param(1), static_cast<u32>(Param(2)), static_cast<s64>(Param(3)));
- Core::CurrentArmInterface().SetReg(1, param_1);
- FuncReturn(retval.raw);
+ const u32 retval = func(system, &param_1, Param(system, 1), static_cast<u32>(Param(system, 2)),
+ static_cast<s64>(Param(system, 3)))
+ .raw;
+
+ system.CurrentArmInterface().SetReg(1, param_1);
+ FuncReturn(system, retval);
}
-template <ResultCode func(u64, u64, u32, s64)>
-void SvcWrap() {
- FuncReturn(
- func(Param(0), Param(1), static_cast<u32>(Param(2)), static_cast<s64>(Param(3))).raw);
+template <ResultCode func(Core::System&, u64, u64, u32, s64)>
+void SvcWrap(Core::System& system) {
+ FuncReturn(system, func(system, Param(system, 0), Param(system, 1),
+ static_cast<u32>(Param(system, 2)), static_cast<s64>(Param(system, 3)))
+ .raw);
}
-template <ResultCode func(u64*, u64, u64, u64)>
-void SvcWrap() {
+template <ResultCode func(Core::System&, u64*, u64, u64, u64)>
+void SvcWrap(Core::System& system) {
u64 param_1 = 0;
- u32 retval = func(&param_1, Param(1), Param(2), Param(3)).raw;
- Core::CurrentArmInterface().SetReg(1, param_1);
- FuncReturn(retval);
+ const u32 retval =
+ func(system, &param_1, Param(system, 1), Param(system, 2), Param(system, 3)).raw;
+
+ system.CurrentArmInterface().SetReg(1, param_1);
+ FuncReturn(system, retval);
}
-template <ResultCode func(u32*, u64, u64, u64, u32, s32)>
-void SvcWrap() {
+template <ResultCode func(Core::System&, u32*, u64, u64, u64, u32, s32)>
+void SvcWrap(Core::System& system) {
u32 param_1 = 0;
- u32 retval = func(&param_1, Param(1), Param(2), Param(3), static_cast<u32>(Param(4)),
- static_cast<s32>(Param(5)))
- .raw;
- Core::CurrentArmInterface().SetReg(1, param_1);
- FuncReturn(retval);
+ const u32 retval = func(system, &param_1, Param(system, 1), Param(system, 2), Param(system, 3),
+ static_cast<u32>(Param(system, 4)), static_cast<s32>(Param(system, 5)))
+ .raw;
+
+ system.CurrentArmInterface().SetReg(1, param_1);
+ FuncReturn(system, retval);
}
-template <ResultCode func(u32*, u64, u64, u32)>
-void SvcWrap() {
+template <ResultCode func(Core::System&, u32*, u64, u64, u32)>
+void SvcWrap(Core::System& system) {
u32 param_1 = 0;
- u32 retval = func(&param_1, Param(1), Param(2), static_cast<u32>(Param(3))).raw;
- Core::CurrentArmInterface().SetReg(1, param_1);
- FuncReturn(retval);
+ const u32 retval = func(system, &param_1, Param(system, 1), Param(system, 2),
+ static_cast<u32>(Param(system, 3)))
+ .raw;
+
+ system.CurrentArmInterface().SetReg(1, param_1);
+ FuncReturn(system, retval);
}
-template <ResultCode func(Handle*, u64, u32, u32)>
-void SvcWrap() {
+template <ResultCode func(Core::System&, Handle*, u64, u32, u32)>
+void SvcWrap(Core::System& system) {
u32 param_1 = 0;
- u32 retval =
- func(&param_1, Param(1), static_cast<u32>(Param(2)), static_cast<u32>(Param(3))).raw;
- Core::CurrentArmInterface().SetReg(1, param_1);
- FuncReturn(retval);
+ const u32 retval = func(system, &param_1, Param(system, 1), static_cast<u32>(Param(system, 2)),
+ static_cast<u32>(Param(system, 3)))
+ .raw;
+
+ system.CurrentArmInterface().SetReg(1, param_1);
+ FuncReturn(system, retval);
}
-template <ResultCode func(u64, u32, s32, s64)>
-void SvcWrap() {
- FuncReturn(func(Param(0), static_cast<u32>(Param(1)), static_cast<s32>(Param(2)),
- static_cast<s64>(Param(3)))
- .raw);
+template <ResultCode func(Core::System&, u64, u32, s32, s64)>
+void SvcWrap(Core::System& system) {
+ FuncReturn(system, func(system, Param(system, 0), static_cast<u32>(Param(system, 1)),
+ static_cast<s32>(Param(system, 2)), static_cast<s64>(Param(system, 3)))
+ .raw);
}
-template <ResultCode func(u64, u32, s32, s32)>
-void SvcWrap() {
- FuncReturn(func(Param(0), static_cast<u32>(Param(1)), static_cast<s32>(Param(2)),
- static_cast<s32>(Param(3)))
- .raw);
+template <ResultCode func(Core::System&, u64, u32, s32, s32)>
+void SvcWrap(Core::System& system) {
+ FuncReturn(system, func(system, Param(system, 0), static_cast<u32>(Param(system, 1)),
+ static_cast<s32>(Param(system, 2)), static_cast<s32>(Param(system, 3)))
+ .raw);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
// Function wrappers that return type u32
-template <u32 func()>
-void SvcWrap() {
- FuncReturn(func());
+template <u32 func(Core::System&)>
+void SvcWrap(Core::System& system) {
+ FuncReturn(system, func(system));
}
////////////////////////////////////////////////////////////////////////////////////////////////////
// Function wrappers that return type u64
-template <u64 func()>
-void SvcWrap() {
- FuncReturn(func());
+template <u64 func(Core::System&)>
+void SvcWrap(Core::System& system) {
+ FuncReturn(system, func(system));
}
////////////////////////////////////////////////////////////////////////////////////////////////////
/// Function wrappers that return type void
-template <void func()>
-void SvcWrap() {
- func();
+template <void func(Core::System&)>
+void SvcWrap(Core::System& system) {
+ func(system);
}
-template <void func(s64)>
-void SvcWrap() {
- func(static_cast<s64>(Param(0)));
+template <void func(Core::System&, s64)>
+void SvcWrap(Core::System& system) {
+ func(system, static_cast<s64>(Param(system, 0)));
}
-template <void func(u64, u64 len)>
-void SvcWrap() {
- func(Param(0), Param(1));
+template <void func(Core::System&, u64, u64)>
+void SvcWrap(Core::System& system) {
+ func(system, Param(system, 0), Param(system, 1));
}
-template <void func(u64, u64, u64)>
-void SvcWrap() {
- func(Param(0), Param(1), Param(2));
+template <void func(Core::System&, u64, u64, u64)>
+void SvcWrap(Core::System& system) {
+ func(system, Param(system, 0), Param(system, 1), Param(system, 2));
}
-template <void func(u32, u64, u64)>
-void SvcWrap() {
- func(static_cast<u32>(Param(0)), Param(1), Param(2));
+template <void func(Core::System&, u32, u64, u64)>
+void SvcWrap(Core::System& system) {
+ func(system, static_cast<u32>(Param(system, 0)), Param(system, 1), Param(system, 2));
}
} // namespace Kernel
diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp
index 1b891f632..ca52267b2 100644
--- a/src/core/hle/kernel/thread.cpp
+++ b/src/core/hle/kernel/thread.cpp
@@ -220,11 +220,6 @@ void Thread::SetPriority(u32 priority) {
UpdatePriority();
}
-void Thread::BoostPriority(u32 priority) {
- scheduler->SetThreadPriority(this, priority);
- current_priority = priority;
-}
-
void Thread::SetWaitSynchronizationResult(ResultCode result) {
context.cpu_registers[0] = result.raw;
}
diff --git a/src/core/hle/kernel/thread.h b/src/core/hle/kernel/thread.h
index 73e5d1bb4..32026d7f0 100644
--- a/src/core/hle/kernel/thread.h
+++ b/src/core/hle/kernel/thread.h
@@ -106,7 +106,7 @@ public:
return "Thread";
}
- static const HandleType HANDLE_TYPE = HandleType::Thread;
+ static constexpr HandleType HANDLE_TYPE = HandleType::Thread;
HandleType GetHandleType() const override {
return HANDLE_TYPE;
}
@@ -136,12 +136,6 @@ public:
*/
void SetPriority(u32 priority);
- /**
- * Temporarily boosts the thread's priority until the next time it is scheduled
- * @param priority The new priority
- */
- void BoostPriority(u32 priority);
-
/// Adds a thread to the list of threads that are waiting for a lock held by this thread.
void AddMutexWaiter(SharedPtr<Thread> thread);
diff --git a/src/core/hle/kernel/transfer_memory.cpp b/src/core/hle/kernel/transfer_memory.cpp
index 23228e1b5..26c4e5e67 100644
--- a/src/core/hle/kernel/transfer_memory.cpp
+++ b/src/core/hle/kernel/transfer_memory.cpp
@@ -14,8 +14,8 @@ namespace Kernel {
TransferMemory::TransferMemory(KernelCore& kernel) : Object{kernel} {}
TransferMemory::~TransferMemory() = default;
-SharedPtr<TransferMemory> TransferMemory::Create(KernelCore& kernel, VAddr base_address,
- size_t size, MemoryPermission permissions) {
+SharedPtr<TransferMemory> TransferMemory::Create(KernelCore& kernel, VAddr base_address, u64 size,
+ MemoryPermission permissions) {
SharedPtr<TransferMemory> transfer_memory{new TransferMemory(kernel)};
transfer_memory->base_address = base_address;
@@ -26,7 +26,15 @@ SharedPtr<TransferMemory> TransferMemory::Create(KernelCore& kernel, VAddr base_
return transfer_memory;
}
-ResultCode TransferMemory::MapMemory(VAddr address, size_t size, MemoryPermission permissions) {
+const u8* TransferMemory::GetPointer() const {
+ return backing_block.get()->data();
+}
+
+u64 TransferMemory::GetSize() const {
+ return memory_size;
+}
+
+ResultCode TransferMemory::MapMemory(VAddr address, u64 size, MemoryPermission permissions) {
if (memory_size != size) {
return ERR_INVALID_SIZE;
}
@@ -39,13 +47,13 @@ ResultCode TransferMemory::MapMemory(VAddr address, size_t size, MemoryPermissio
return ERR_INVALID_STATE;
}
+ backing_block = std::make_shared<std::vector<u8>>(size);
+
const auto map_state = owner_permissions == MemoryPermission::None
? MemoryState::TransferMemoryIsolated
: MemoryState::TransferMemory;
auto& vm_manager = owner_process->VMManager();
- const auto map_result = vm_manager.MapMemoryBlock(
- address, std::make_shared<std::vector<u8>>(size), 0, size, map_state);
-
+ const auto map_result = vm_manager.MapMemoryBlock(address, backing_block, 0, size, map_state);
if (map_result.Failed()) {
return map_result.Code();
}
@@ -54,7 +62,7 @@ ResultCode TransferMemory::MapMemory(VAddr address, size_t size, MemoryPermissio
return RESULT_SUCCESS;
}
-ResultCode TransferMemory::UnmapMemory(VAddr address, size_t size) {
+ResultCode TransferMemory::UnmapMemory(VAddr address, u64 size) {
if (memory_size != size) {
return ERR_INVALID_SIZE;
}
diff --git a/src/core/hle/kernel/transfer_memory.h b/src/core/hle/kernel/transfer_memory.h
index ec294951e..a140b1e2b 100644
--- a/src/core/hle/kernel/transfer_memory.h
+++ b/src/core/hle/kernel/transfer_memory.h
@@ -4,6 +4,9 @@
#pragma once
+#include <memory>
+#include <vector>
+
#include "core/hle/kernel/object.h"
union ResultCode;
@@ -25,7 +28,7 @@ class TransferMemory final : public Object {
public:
static constexpr HandleType HANDLE_TYPE = HandleType::TransferMemory;
- static SharedPtr<TransferMemory> Create(KernelCore& kernel, VAddr base_address, size_t size,
+ static SharedPtr<TransferMemory> Create(KernelCore& kernel, VAddr base_address, u64 size,
MemoryPermission permissions);
TransferMemory(const TransferMemory&) = delete;
@@ -46,6 +49,12 @@ public:
return HANDLE_TYPE;
}
+ /// Gets a pointer to the backing block of this instance.
+ const u8* GetPointer() const;
+
+ /// Gets the size of the memory backing this instance in bytes.
+ u64 GetSize() const;
+
/// Attempts to map transfer memory with the given range and memory permissions.
///
/// @param address The base address to being mapping memory at.
@@ -56,7 +65,7 @@ public:
/// the same values that were given when creating the transfer memory
/// instance.
///
- ResultCode MapMemory(VAddr address, size_t size, MemoryPermission permissions);
+ ResultCode MapMemory(VAddr address, u64 size, MemoryPermission permissions);
/// Unmaps the transfer memory with the given range
///
@@ -66,17 +75,20 @@ public:
/// @pre The given address and size must be the same as the ones used
/// to create the transfer memory instance.
///
- ResultCode UnmapMemory(VAddr address, size_t size);
+ ResultCode UnmapMemory(VAddr address, u64 size);
private:
explicit TransferMemory(KernelCore& kernel);
~TransferMemory() override;
+ /// Memory block backing this instance.
+ std::shared_ptr<std::vector<u8>> backing_block;
+
/// The base address for the memory managed by this instance.
VAddr base_address = 0;
/// Size of the memory, in bytes, that this instance manages.
- size_t memory_size = 0;
+ u64 memory_size = 0;
/// The memory permissions that are applied to this instance.
MemoryPermission owner_permissions{};
diff --git a/src/core/hle/kernel/vm_manager.cpp b/src/core/hle/kernel/vm_manager.cpp
index ec0a480ce..f0c0c12fc 100644
--- a/src/core/hle/kernel/vm_manager.cpp
+++ b/src/core/hle/kernel/vm_manager.cpp
@@ -302,6 +302,86 @@ ResultVal<VAddr> VMManager::SetHeapSize(u64 size) {
return MakeResult<VAddr>(heap_region_base);
}
+ResultCode VMManager::MapCodeMemory(VAddr dst_address, VAddr src_address, u64 size) {
+ constexpr auto ignore_attribute = MemoryAttribute::LockedForIPC | MemoryAttribute::DeviceMapped;
+ const auto src_check_result = CheckRangeState(
+ src_address, size, MemoryState::All, MemoryState::Heap, VMAPermission::All,
+ VMAPermission::ReadWrite, MemoryAttribute::Mask, MemoryAttribute::None, ignore_attribute);
+
+ if (src_check_result.Failed()) {
+ return src_check_result.Code();
+ }
+
+ const auto mirror_result =
+ MirrorMemory(dst_address, src_address, size, MemoryState::ModuleCode);
+ if (mirror_result.IsError()) {
+ return mirror_result;
+ }
+
+ // Ensure we lock the source memory region.
+ const auto src_vma_result = CarveVMARange(src_address, size);
+ if (src_vma_result.Failed()) {
+ return src_vma_result.Code();
+ }
+ auto src_vma_iter = *src_vma_result;
+ src_vma_iter->second.attribute = MemoryAttribute::Locked;
+ Reprotect(src_vma_iter, VMAPermission::Read);
+
+ // The destination memory region is fine as is, however we need to make it read-only.
+ return ReprotectRange(dst_address, size, VMAPermission::Read);
+}
+
+ResultCode VMManager::UnmapCodeMemory(VAddr dst_address, VAddr src_address, u64 size) {
+ constexpr auto ignore_attribute = MemoryAttribute::LockedForIPC | MemoryAttribute::DeviceMapped;
+ const auto src_check_result = CheckRangeState(
+ src_address, size, MemoryState::All, MemoryState::Heap, VMAPermission::None,
+ VMAPermission::None, MemoryAttribute::Mask, MemoryAttribute::Locked, ignore_attribute);
+
+ if (src_check_result.Failed()) {
+ return src_check_result.Code();
+ }
+
+ // Yes, the kernel only checks the first page of the region.
+ const auto dst_check_result =
+ CheckRangeState(dst_address, Memory::PAGE_SIZE, MemoryState::FlagModule,
+ MemoryState::FlagModule, VMAPermission::None, VMAPermission::None,
+ MemoryAttribute::Mask, MemoryAttribute::None, ignore_attribute);
+
+ if (dst_check_result.Failed()) {
+ return dst_check_result.Code();
+ }
+
+ const auto dst_memory_state = std::get<MemoryState>(*dst_check_result);
+ const auto dst_contiguous_check_result = CheckRangeState(
+ dst_address, size, MemoryState::All, dst_memory_state, VMAPermission::None,
+ VMAPermission::None, MemoryAttribute::Mask, MemoryAttribute::None, ignore_attribute);
+
+ if (dst_contiguous_check_result.Failed()) {
+ return dst_contiguous_check_result.Code();
+ }
+
+ const auto unmap_result = UnmapRange(dst_address, size);
+ if (unmap_result.IsError()) {
+ return unmap_result;
+ }
+
+ // With the mirrored portion unmapped, restore the original region's traits.
+ const auto src_vma_result = CarveVMARange(src_address, size);
+ if (src_vma_result.Failed()) {
+ return src_vma_result.Code();
+ }
+ auto src_vma_iter = *src_vma_result;
+ src_vma_iter->second.state = MemoryState::Heap;
+ src_vma_iter->second.attribute = MemoryAttribute::None;
+ Reprotect(src_vma_iter, VMAPermission::ReadWrite);
+
+ if (dst_memory_state == MemoryState::ModuleCode) {
+ Core::System::GetInstance().InvalidateCpuInstructionCaches();
+ }
+
+ return unmap_result;
+}
+
MemoryInfo VMManager::QueryMemory(VAddr address) const {
const auto vma = FindVMA(address);
MemoryInfo memory_info{};
diff --git a/src/core/hle/kernel/vm_manager.h b/src/core/hle/kernel/vm_manager.h
index 6f484b7bf..288eb9450 100644
--- a/src/core/hle/kernel/vm_manager.h
+++ b/src/core/hle/kernel/vm_manager.h
@@ -43,6 +43,9 @@ enum class VMAPermission : u8 {
ReadExecute = Read | Execute,
WriteExecute = Write | Execute,
ReadWriteExecute = Read | Write | Execute,
+
+ // Used as a wildcard when checking permissions across memory ranges
+ All = 0xFF,
};
constexpr VMAPermission operator|(VMAPermission lhs, VMAPermission rhs) {
@@ -152,6 +155,9 @@ enum class MemoryState : u32 {
FlagUncached = 1U << 24,
FlagCodeMemory = 1U << 25,
+ // Wildcard used in range checking to indicate all states.
+ All = 0xFFFFFFFF,
+
// Convenience flag sets to reduce repetition
IPCFlags = FlagIPC0 | FlagIPC3 | FlagIPC1,
@@ -415,6 +421,49 @@ public:
///
ResultVal<VAddr> SetHeapSize(u64 size);
+ /// Maps a region of memory as code memory.
+ ///
+ /// @param dst_address The base address of the region to create the aliasing memory region.
+ /// @param src_address The base address of the region to be aliased.
+ /// @param size The total amount of memory to map in bytes.
+ ///
+ /// @pre Both memory regions lie within the actual addressable address space.
+ ///
+ /// @post After this function finishes execution, assuming success, then the address range
+ /// [dst_address, dst_address+size) will alias the memory region,
+ /// [src_address, src_address+size).
+ /// <p>
+ /// What this also entails is as follows:
+ /// 1. The aliased region gains the Locked memory attribute.
+ /// 2. The aliased region becomes read-only.
+ /// 3. The aliasing region becomes read-only.
+ /// 4. The aliasing region is created with a memory state of MemoryState::CodeModule.
+ ///
+ ResultCode MapCodeMemory(VAddr dst_address, VAddr src_address, u64 size);
+
+ /// Unmaps a region of memory designated as code module memory.
+ ///
+ /// @param dst_address The base address of the memory region aliasing the source memory region.
+ /// @param src_address The base address of the memory region being aliased.
+ /// @param size The size of the memory region to unmap in bytes.
+ ///
+ /// @pre Both memory ranges lie within the actual addressable address space.
+ ///
+ /// @pre The memory region being unmapped has been previously been mapped
+ /// by a call to MapCodeMemory.
+ ///
+ /// @post After execution of the function, if successful. the aliasing memory region
+ /// will be unmapped and the aliased region will have various traits about it
+ /// restored to what they were prior to the original mapping call preceding
+ /// this function call.
+ /// <p>
+ /// What this also entails is as follows:
+ /// 1. The state of the memory region will now indicate a general heap region.
+ /// 2. All memory attributes for the memory region are cleared.
+ /// 3. Memory permissions for the region are restored to user read/write.
+ ///
+ ResultCode UnmapCodeMemory(VAddr dst_address, VAddr src_address, u64 size);
+
/// Queries the memory manager for information about the given address.
///
/// @param address The address to query the memory manager about for information.
diff --git a/src/core/hle/kernel/writable_event.h b/src/core/hle/kernel/writable_event.h
index c9068dd3d..d00c92a6b 100644
--- a/src/core/hle/kernel/writable_event.h
+++ b/src/core/hle/kernel/writable_event.h
@@ -37,7 +37,7 @@ public:
return name;
}
- static const HandleType HANDLE_TYPE = HandleType::WritableEvent;
+ static constexpr HandleType HANDLE_TYPE = HandleType::WritableEvent;
HandleType GetHandleType() const override {
return HANDLE_TYPE;
}