kernel: make handle table per-process

master
Weiyi Wang 2018-10-19 21:04:18 +07:00
parent fda2a5cf54
commit eb285c33fd
11 changed files with 169 additions and 119 deletions

@ -5,7 +5,6 @@
#include <utility> #include <utility>
#include "common/assert.h" #include "common/assert.h"
#include "common/logging/log.h" #include "common/logging/log.h"
#include "core/core.h" // TODO: for current_process. Remove this later
#include "core/hle/kernel/errors.h" #include "core/hle/kernel/errors.h"
#include "core/hle/kernel/handle_table.h" #include "core/hle/kernel/handle_table.h"
#include "core/hle/kernel/process.h" #include "core/hle/kernel/process.h"
@ -13,9 +12,7 @@
namespace Kernel { namespace Kernel {
HandleTable g_handle_table; HandleTable::HandleTable(KernelSystem& kernel) : kernel(kernel) {
HandleTable::HandleTable() {
next_generation = 1; next_generation = 1;
Clear(); Clear();
} }
@ -77,9 +74,7 @@ SharedPtr<Object> HandleTable::GetGeneric(Handle handle) const {
if (handle == CurrentThread) { if (handle == CurrentThread) {
return GetCurrentThread(); return GetCurrentThread();
} else if (handle == CurrentProcess) { } else if (handle == CurrentProcess) {
// TODO: should this return HandleTable's parent process, or kernel's current process? return kernel.GetCurrentProcess();
// Should change this either way
return Core::System::GetInstance().Kernel().GetCurrentProcess();
} }
if (!IsValid(handle)) { if (!IsValid(handle)) {

@ -42,7 +42,7 @@ enum KernelHandle : Handle {
*/ */
class HandleTable final : NonCopyable { class HandleTable final : NonCopyable {
public: public:
HandleTable(); explicit HandleTable(KernelSystem& kernel);
/** /**
* Allocates a handle for the given object. * Allocates a handle for the given object.
@ -119,8 +119,8 @@ private:
/// Head of the free slots linked list. /// Head of the free slots linked list.
u16 next_free_slot; u16 next_free_slot;
KernelSystem& kernel;
}; };
extern HandleTable g_handle_table;
} // namespace Kernel } // namespace Kernel

@ -50,7 +50,7 @@ SharedPtr<Event> HLERequestContext::SleepClientThread(SharedPtr<Thread> thread,
std::array<u32_le, IPC::COMMAND_BUFFER_LENGTH + 2 * IPC::MAX_STATIC_BUFFERS> cmd_buff; std::array<u32_le, IPC::COMMAND_BUFFER_LENGTH + 2 * IPC::MAX_STATIC_BUFFERS> cmd_buff;
Memory::ReadBlock(*process, thread->GetCommandBufferAddress(), cmd_buff.data(), Memory::ReadBlock(*process, thread->GetCommandBufferAddress(), cmd_buff.data(),
cmd_buff.size() * sizeof(u32)); cmd_buff.size() * sizeof(u32));
context.WriteToOutgoingCommandBuffer(cmd_buff.data(), *process, Kernel::g_handle_table); context.WriteToOutgoingCommandBuffer(cmd_buff.data(), *process);
// Copy the translated command buffer back into the thread's command buffer area. // Copy the translated command buffer back into the thread's command buffer area.
Memory::WriteBlock(*process, thread->GetCommandBufferAddress(), cmd_buff.data(), Memory::WriteBlock(*process, thread->GetCommandBufferAddress(), cmd_buff.data(),
cmd_buff.size() * sizeof(u32)); cmd_buff.size() * sizeof(u32));
@ -98,8 +98,7 @@ void HLERequestContext::AddStaticBuffer(u8 buffer_id, std::vector<u8> data) {
} }
ResultCode HLERequestContext::PopulateFromIncomingCommandBuffer(const u32_le* src_cmdbuf, ResultCode HLERequestContext::PopulateFromIncomingCommandBuffer(const u32_le* src_cmdbuf,
Process& src_process, Process& src_process) {
HandleTable& src_table) {
IPC::Header header{src_cmdbuf[0]}; IPC::Header header{src_cmdbuf[0]};
std::size_t untranslated_size = 1u + header.normal_params_size; std::size_t untranslated_size = 1u + header.normal_params_size;
@ -122,10 +121,10 @@ ResultCode HLERequestContext::PopulateFromIncomingCommandBuffer(const u32_le* sr
Handle handle = src_cmdbuf[i]; Handle handle = src_cmdbuf[i];
SharedPtr<Object> object = nullptr; SharedPtr<Object> object = nullptr;
if (handle != 0) { if (handle != 0) {
object = src_table.GetGeneric(handle); object = src_process.handle_table.GetGeneric(handle);
ASSERT(object != nullptr); // TODO(yuriks): Return error ASSERT(object != nullptr); // TODO(yuriks): Return error
if (descriptor == IPC::DescriptorType::MoveHandle) { if (descriptor == IPC::DescriptorType::MoveHandle) {
src_table.Close(handle); src_process.handle_table.Close(handle);
} }
} }
@ -163,8 +162,8 @@ ResultCode HLERequestContext::PopulateFromIncomingCommandBuffer(const u32_le* sr
return RESULT_SUCCESS; return RESULT_SUCCESS;
} }
ResultCode HLERequestContext::WriteToOutgoingCommandBuffer(u32_le* dst_cmdbuf, Process& dst_process, ResultCode HLERequestContext::WriteToOutgoingCommandBuffer(u32_le* dst_cmdbuf,
HandleTable& dst_table) const { Process& dst_process) const {
IPC::Header header{cmd_buf[0]}; IPC::Header header{cmd_buf[0]};
std::size_t untranslated_size = 1u + header.normal_params_size; std::size_t untranslated_size = 1u + header.normal_params_size;
@ -189,7 +188,7 @@ ResultCode HLERequestContext::WriteToOutgoingCommandBuffer(u32_le* dst_cmdbuf, P
Handle handle = 0; Handle handle = 0;
if (object != nullptr) { if (object != nullptr) {
// TODO(yuriks): Figure out the proper error handling for if this fails // TODO(yuriks): Figure out the proper error handling for if this fails
handle = dst_table.Create(object).Unwrap(); handle = dst_process.handle_table.Create(object).Unwrap();
} }
dst_cmdbuf[i++] = handle; dst_cmdbuf[i++] = handle;
} }

@ -226,11 +226,9 @@ public:
MappedBuffer& GetMappedBuffer(u32 id_from_cmdbuf); MappedBuffer& GetMappedBuffer(u32 id_from_cmdbuf);
/// Populates this context with data from the requesting process/thread. /// Populates this context with data from the requesting process/thread.
ResultCode PopulateFromIncomingCommandBuffer(const u32_le* src_cmdbuf, Process& src_process, ResultCode PopulateFromIncomingCommandBuffer(const u32_le* src_cmdbuf, Process& src_process);
HandleTable& src_table);
/// Writes data from this context back to the requesting process/thread. /// Writes data from this context back to the requesting process/thread.
ResultCode WriteToOutgoingCommandBuffer(u32_le* dst_cmdbuf, Process& dst_process, ResultCode WriteToOutgoingCommandBuffer(u32_le* dst_cmdbuf, Process& dst_process) const;
HandleTable& dst_table) const;
private: private:
std::array<u32, IPC::COMMAND_BUFFER_LENGTH> cmd_buf; std::array<u32, IPC::COMMAND_BUFFER_LENGTH> cmd_buf;

@ -60,9 +60,9 @@ ResultCode TranslateCommandBuffer(SharedPtr<Thread> src_thread, SharedPtr<Thread
} else if (handle == CurrentProcess) { } else if (handle == CurrentProcess) {
object = src_process; object = src_process;
} else if (handle != 0) { } else if (handle != 0) {
object = g_handle_table.GetGeneric(handle); object = src_process->handle_table.GetGeneric(handle);
if (descriptor == IPC::DescriptorType::MoveHandle) { if (descriptor == IPC::DescriptorType::MoveHandle) {
g_handle_table.Close(handle); src_process->handle_table.Close(handle);
} }
} }
@ -73,7 +73,7 @@ ResultCode TranslateCommandBuffer(SharedPtr<Thread> src_thread, SharedPtr<Thread
continue; continue;
} }
auto result = g_handle_table.Create(std::move(object)); auto result = dst_process->handle_table.Create(std::move(object));
cmd_buf[i++] = result.ValueOr(0); cmd_buf[i++] = result.ValueOr(0);
} }
break; break;

@ -27,8 +27,6 @@ KernelSystem::KernelSystem(u32 system_mode) {
/// Shutdown the kernel /// Shutdown the kernel
KernelSystem::~KernelSystem() { KernelSystem::~KernelSystem() {
g_handle_table.Clear(); // Free all kernel objects
Kernel::ThreadingShutdown(); Kernel::ThreadingShutdown();
Kernel::TimersShutdown(); Kernel::TimersShutdown();

@ -300,7 +300,8 @@ ResultCode Process::LinearFree(VAddr target, u32 size) {
return RESULT_SUCCESS; return RESULT_SUCCESS;
} }
Kernel::Process::Process(KernelSystem& kernel) : Object(kernel), kernel(kernel) {} Kernel::Process::Process(KernelSystem& kernel)
: Object(kernel), handle_table(kernel), kernel(kernel) {}
Kernel::Process::~Process() {} Kernel::Process::~Process() {}
SharedPtr<Process> KernelSystem::GetProcessById(u32 process_id) const { SharedPtr<Process> KernelSystem::GetProcessById(u32 process_id) const {

@ -13,6 +13,7 @@
#include <boost/container/static_vector.hpp> #include <boost/container/static_vector.hpp>
#include "common/bit_field.h" #include "common/bit_field.h"
#include "common/common_types.h" #include "common/common_types.h"
#include "core/hle/kernel/handle_table.h"
#include "core/hle/kernel/object.h" #include "core/hle/kernel/object.h"
#include "core/hle/kernel/vm_manager.h" #include "core/hle/kernel/vm_manager.h"
@ -123,6 +124,8 @@ public:
return HANDLE_TYPE; return HANDLE_TYPE;
} }
HandleTable handle_table;
SharedPtr<CodeSet> codeset; SharedPtr<CodeSet> codeset;
/// Resource limit descriptor for this process /// Resource limit descriptor for this process
SharedPtr<ResourceLimit> resource_limit; SharedPtr<ResourceLimit> resource_limit;

@ -182,7 +182,9 @@ static ResultCode MapMemoryBlock(Handle handle, u32 addr, u32 permissions, u32 o
"otherpermission={}", "otherpermission={}",
handle, addr, permissions, other_permissions); handle, addr, permissions, other_permissions);
SharedPtr<SharedMemory> shared_memory = g_handle_table.Get<SharedMemory>(handle); SharedPtr<SharedMemory> shared_memory =
Core::System::GetInstance().Kernel().GetCurrentProcess()->handle_table.Get<SharedMemory>(
handle);
if (shared_memory == nullptr) if (shared_memory == nullptr)
return ERR_INVALID_HANDLE; return ERR_INVALID_HANDLE;
@ -211,12 +213,12 @@ static ResultCode UnmapMemoryBlock(Handle handle, u32 addr) {
// TODO(Subv): Return E0A01BF5 if the address is not in the application's heap // TODO(Subv): Return E0A01BF5 if the address is not in the application's heap
SharedPtr<SharedMemory> shared_memory = g_handle_table.Get<SharedMemory>(handle); SharedPtr<Process> current_process = Core::System::GetInstance().Kernel().GetCurrentProcess();
SharedPtr<SharedMemory> shared_memory = current_process->handle_table.Get<SharedMemory>(handle);
if (shared_memory == nullptr) if (shared_memory == nullptr)
return ERR_INVALID_HANDLE; return ERR_INVALID_HANDLE;
return shared_memory->Unmap(Core::System::GetInstance().Kernel().GetCurrentProcess().get(), return shared_memory->Unmap(current_process.get(), addr);
addr);
} }
/// Connect to an OS service given the port name, returns the handle to the port to out /// Connect to an OS service given the port name, returns the handle to the port to out
@ -244,13 +246,17 @@ static ResultCode ConnectToPort(Handle* out_handle, VAddr port_name_address) {
CASCADE_RESULT(client_session, client_port->Connect()); CASCADE_RESULT(client_session, client_port->Connect());
// Return the client session // Return the client session
CASCADE_RESULT(*out_handle, g_handle_table.Create(client_session)); CASCADE_RESULT(*out_handle,
Core::System::GetInstance().Kernel().GetCurrentProcess()->handle_table.Create(
client_session));
return RESULT_SUCCESS; return RESULT_SUCCESS;
} }
/// Makes a blocking IPC call to an OS service. /// Makes a blocking IPC call to an OS service.
static ResultCode SendSyncRequest(Handle handle) { static ResultCode SendSyncRequest(Handle handle) {
SharedPtr<ClientSession> session = g_handle_table.Get<ClientSession>(handle); SharedPtr<ClientSession> session =
Core::System::GetInstance().Kernel().GetCurrentProcess()->handle_table.Get<ClientSession>(
handle);
if (session == nullptr) { if (session == nullptr) {
return ERR_INVALID_HANDLE; return ERR_INVALID_HANDLE;
} }
@ -265,12 +271,14 @@ static ResultCode SendSyncRequest(Handle handle) {
/// Close a handle /// Close a handle
static ResultCode CloseHandle(Handle handle) { static ResultCode CloseHandle(Handle handle) {
LOG_TRACE(Kernel_SVC, "Closing handle 0x{:08X}", handle); LOG_TRACE(Kernel_SVC, "Closing handle 0x{:08X}", handle);
return g_handle_table.Close(handle); return Core::System::GetInstance().Kernel().GetCurrentProcess()->handle_table.Close(handle);
} }
/// Wait for a handle to synchronize, timeout after the specified nanoseconds /// Wait for a handle to synchronize, timeout after the specified nanoseconds
static ResultCode WaitSynchronization1(Handle handle, s64 nano_seconds) { static ResultCode WaitSynchronization1(Handle handle, s64 nano_seconds) {
auto object = g_handle_table.Get<WaitObject>(handle); auto object =
Core::System::GetInstance().Kernel().GetCurrentProcess()->handle_table.Get<WaitObject>(
handle);
Thread* thread = GetCurrentThread(); Thread* thread = GetCurrentThread();
if (object == nullptr) if (object == nullptr)
@ -341,7 +349,9 @@ static ResultCode WaitSynchronizationN(s32* out, VAddr handles_address, s32 hand
for (int i = 0; i < handle_count; ++i) { for (int i = 0; i < handle_count; ++i) {
Handle handle = Memory::Read32(handles_address + i * sizeof(Handle)); Handle handle = Memory::Read32(handles_address + i * sizeof(Handle));
auto object = g_handle_table.Get<WaitObject>(handle); auto object =
Core::System::GetInstance().Kernel().GetCurrentProcess()->handle_table.Get<WaitObject>(
handle);
if (object == nullptr) if (object == nullptr)
return ERR_INVALID_HANDLE; return ERR_INVALID_HANDLE;
objects[i] = object; objects[i] = object;
@ -505,9 +515,11 @@ static ResultCode ReplyAndReceive(s32* index, VAddr handles_address, s32 handle_
using ObjectPtr = SharedPtr<WaitObject>; using ObjectPtr = SharedPtr<WaitObject>;
std::vector<ObjectPtr> objects(handle_count); std::vector<ObjectPtr> objects(handle_count);
SharedPtr<Process> current_process = Core::System::GetInstance().Kernel().GetCurrentProcess();
for (int i = 0; i < handle_count; ++i) { for (int i = 0; i < handle_count; ++i) {
Handle handle = Memory::Read32(handles_address + i * sizeof(Handle)); Handle handle = Memory::Read32(handles_address + i * sizeof(Handle));
auto object = g_handle_table.Get<WaitObject>(handle); auto object = current_process->handle_table.Get<WaitObject>(handle);
if (object == nullptr) if (object == nullptr)
return ERR_INVALID_HANDLE; return ERR_INVALID_HANDLE;
objects[i] = object; objects[i] = object;
@ -518,7 +530,7 @@ static ResultCode ReplyAndReceive(s32* index, VAddr handles_address, s32 handle_
u32* cmd_buff = GetCommandBuffer(); u32* cmd_buff = GetCommandBuffer();
IPC::Header header{cmd_buff[0]}; IPC::Header header{cmd_buff[0]};
if (reply_target != 0 && header.command_id != 0xFFFF) { if (reply_target != 0 && header.command_id != 0xFFFF) {
auto session = g_handle_table.Get<ServerSession>(reply_target); auto session = current_process->handle_table.Get<ServerSession>(reply_target);
if (session == nullptr) if (session == nullptr)
return ERR_INVALID_HANDLE; return ERR_INVALID_HANDLE;
@ -618,8 +630,10 @@ static ResultCode ReplyAndReceive(s32* index, VAddr handles_address, s32 handle_
/// Create an address arbiter (to allocate access to shared resources) /// Create an address arbiter (to allocate access to shared resources)
static ResultCode CreateAddressArbiter(Handle* out_handle) { static ResultCode CreateAddressArbiter(Handle* out_handle) {
SharedPtr<AddressArbiter> arbiter = Core::System::GetInstance().Kernel().CreateAddressArbiter(); KernelSystem& kernel = Core::System::GetInstance().Kernel();
CASCADE_RESULT(*out_handle, g_handle_table.Create(std::move(arbiter))); SharedPtr<AddressArbiter> arbiter = kernel.CreateAddressArbiter();
CASCADE_RESULT(*out_handle,
kernel.GetCurrentProcess()->handle_table.Create(std::move(arbiter)));
LOG_TRACE(Kernel_SVC, "returned handle=0x{:08X}", *out_handle); LOG_TRACE(Kernel_SVC, "returned handle=0x{:08X}", *out_handle);
return RESULT_SUCCESS; return RESULT_SUCCESS;
} }
@ -630,7 +644,9 @@ static ResultCode ArbitrateAddress(Handle handle, u32 address, u32 type, u32 val
LOG_TRACE(Kernel_SVC, "called handle=0x{:08X}, address=0x{:08X}, type=0x{:08X}, value=0x{:08X}", LOG_TRACE(Kernel_SVC, "called handle=0x{:08X}, address=0x{:08X}, type=0x{:08X}, value=0x{:08X}",
handle, address, type, value); handle, address, type, value);
SharedPtr<AddressArbiter> arbiter = g_handle_table.Get<AddressArbiter>(handle); SharedPtr<AddressArbiter> arbiter =
Core::System::GetInstance().Kernel().GetCurrentProcess()->handle_table.Get<AddressArbiter>(
handle);
if (arbiter == nullptr) if (arbiter == nullptr)
return ERR_INVALID_HANDLE; return ERR_INVALID_HANDLE;
@ -678,11 +694,12 @@ static void OutputDebugString(VAddr address, int len) {
static ResultCode GetResourceLimit(Handle* resource_limit, Handle process_handle) { static ResultCode GetResourceLimit(Handle* resource_limit, Handle process_handle) {
LOG_TRACE(Kernel_SVC, "called process=0x{:08X}", process_handle); LOG_TRACE(Kernel_SVC, "called process=0x{:08X}", process_handle);
SharedPtr<Process> process = g_handle_table.Get<Process>(process_handle); SharedPtr<Process> current_process = Core::System::GetInstance().Kernel().GetCurrentProcess();
SharedPtr<Process> process = current_process->handle_table.Get<Process>(process_handle);
if (process == nullptr) if (process == nullptr)
return ERR_INVALID_HANDLE; return ERR_INVALID_HANDLE;
CASCADE_RESULT(*resource_limit, g_handle_table.Create(process->resource_limit)); CASCADE_RESULT(*resource_limit, current_process->handle_table.Create(process->resource_limit));
return RESULT_SUCCESS; return RESULT_SUCCESS;
} }
@ -694,7 +711,8 @@ static ResultCode GetResourceLimitCurrentValues(VAddr values, Handle resource_li
resource_limit_handle, names, name_count); resource_limit_handle, names, name_count);
SharedPtr<ResourceLimit> resource_limit = SharedPtr<ResourceLimit> resource_limit =
g_handle_table.Get<ResourceLimit>(resource_limit_handle); Core::System::GetInstance().Kernel().GetCurrentProcess()->handle_table.Get<ResourceLimit>(
resource_limit_handle);
if (resource_limit == nullptr) if (resource_limit == nullptr)
return ERR_INVALID_HANDLE; return ERR_INVALID_HANDLE;
@ -714,7 +732,8 @@ static ResultCode GetResourceLimitLimitValues(VAddr values, Handle resource_limi
resource_limit_handle, names, name_count); resource_limit_handle, names, name_count);
SharedPtr<ResourceLimit> resource_limit = SharedPtr<ResourceLimit> resource_limit =
g_handle_table.Get<ResourceLimit>(resource_limit_handle); Core::System::GetInstance().Kernel().GetCurrentProcess()->handle_table.Get<ResourceLimit>(
resource_limit_handle);
if (resource_limit == nullptr) if (resource_limit == nullptr)
return ERR_INVALID_HANDLE; return ERR_INVALID_HANDLE;
@ -773,7 +792,7 @@ static ResultCode CreateThread(Handle* out_handle, u32 priority, u32 entry_point
thread->context->SetFpscr(FPSCR_DEFAULT_NAN | FPSCR_FLUSH_TO_ZERO | thread->context->SetFpscr(FPSCR_DEFAULT_NAN | FPSCR_FLUSH_TO_ZERO |
FPSCR_ROUND_TOZERO); // 0x03C00000 FPSCR_ROUND_TOZERO); // 0x03C00000
CASCADE_RESULT(*out_handle, g_handle_table.Create(std::move(thread))); CASCADE_RESULT(*out_handle, current_process->handle_table.Create(std::move(thread)));
Core::System::GetInstance().PrepareReschedule(); Core::System::GetInstance().PrepareReschedule();
@ -795,7 +814,8 @@ static void ExitThread() {
/// Gets the priority for the specified thread /// Gets the priority for the specified thread
static ResultCode GetThreadPriority(u32* priority, Handle handle) { static ResultCode GetThreadPriority(u32* priority, Handle handle) {
const SharedPtr<Thread> thread = g_handle_table.Get<Thread>(handle); const SharedPtr<Thread> thread =
Core::System::GetInstance().Kernel().GetCurrentProcess()->handle_table.Get<Thread>(handle);
if (thread == nullptr) if (thread == nullptr)
return ERR_INVALID_HANDLE; return ERR_INVALID_HANDLE;
@ -809,7 +829,8 @@ static ResultCode SetThreadPriority(Handle handle, u32 priority) {
return ERR_OUT_OF_RANGE; return ERR_OUT_OF_RANGE;
} }
SharedPtr<Thread> thread = g_handle_table.Get<Thread>(handle); SharedPtr<Thread> thread =
Core::System::GetInstance().Kernel().GetCurrentProcess()->handle_table.Get<Thread>(handle);
if (thread == nullptr) if (thread == nullptr)
return ERR_INVALID_HANDLE; return ERR_INVALID_HANDLE;
@ -834,9 +855,10 @@ static ResultCode SetThreadPriority(Handle handle, u32 priority) {
/// Create a mutex /// Create a mutex
static ResultCode CreateMutex(Handle* out_handle, u32 initial_locked) { static ResultCode CreateMutex(Handle* out_handle, u32 initial_locked) {
SharedPtr<Mutex> mutex = Core::System::GetInstance().Kernel().CreateMutex(initial_locked != 0); KernelSystem& kernel = Core::System::GetInstance().Kernel();
SharedPtr<Mutex> mutex = kernel.CreateMutex(initial_locked != 0);
mutex->name = fmt::format("mutex-{:08x}", Core::CPU().GetReg(14)); mutex->name = fmt::format("mutex-{:08x}", Core::CPU().GetReg(14));
CASCADE_RESULT(*out_handle, g_handle_table.Create(std::move(mutex))); CASCADE_RESULT(*out_handle, kernel.GetCurrentProcess()->handle_table.Create(std::move(mutex)));
LOG_TRACE(Kernel_SVC, "called initial_locked={} : created handle=0x{:08X}", LOG_TRACE(Kernel_SVC, "called initial_locked={} : created handle=0x{:08X}",
initial_locked ? "true" : "false", *out_handle); initial_locked ? "true" : "false", *out_handle);
@ -848,7 +870,8 @@ static ResultCode CreateMutex(Handle* out_handle, u32 initial_locked) {
static ResultCode ReleaseMutex(Handle handle) { static ResultCode ReleaseMutex(Handle handle) {
LOG_TRACE(Kernel_SVC, "called handle=0x{:08X}", handle); LOG_TRACE(Kernel_SVC, "called handle=0x{:08X}", handle);
SharedPtr<Mutex> mutex = g_handle_table.Get<Mutex>(handle); SharedPtr<Mutex> mutex =
Core::System::GetInstance().Kernel().GetCurrentProcess()->handle_table.Get<Mutex>(handle);
if (mutex == nullptr) if (mutex == nullptr)
return ERR_INVALID_HANDLE; return ERR_INVALID_HANDLE;
@ -859,7 +882,9 @@ static ResultCode ReleaseMutex(Handle handle) {
static ResultCode GetProcessId(u32* process_id, Handle process_handle) { static ResultCode GetProcessId(u32* process_id, Handle process_handle) {
LOG_TRACE(Kernel_SVC, "called process=0x{:08X}", process_handle); LOG_TRACE(Kernel_SVC, "called process=0x{:08X}", process_handle);
const SharedPtr<Process> process = g_handle_table.Get<Process>(process_handle); const SharedPtr<Process> process =
Core::System::GetInstance().Kernel().GetCurrentProcess()->handle_table.Get<Process>(
process_handle);
if (process == nullptr) if (process == nullptr)
return ERR_INVALID_HANDLE; return ERR_INVALID_HANDLE;
@ -871,7 +896,9 @@ static ResultCode GetProcessId(u32* process_id, Handle process_handle) {
static ResultCode GetProcessIdOfThread(u32* process_id, Handle thread_handle) { static ResultCode GetProcessIdOfThread(u32* process_id, Handle thread_handle) {
LOG_TRACE(Kernel_SVC, "called thread=0x{:08X}", thread_handle); LOG_TRACE(Kernel_SVC, "called thread=0x{:08X}", thread_handle);
const SharedPtr<Thread> thread = g_handle_table.Get<Thread>(thread_handle); const SharedPtr<Thread> thread =
Core::System::GetInstance().Kernel().GetCurrentProcess()->handle_table.Get<Thread>(
thread_handle);
if (thread == nullptr) if (thread == nullptr)
return ERR_INVALID_HANDLE; return ERR_INVALID_HANDLE;
@ -887,7 +914,8 @@ static ResultCode GetProcessIdOfThread(u32* process_id, Handle thread_handle) {
static ResultCode GetThreadId(u32* thread_id, Handle handle) { static ResultCode GetThreadId(u32* thread_id, Handle handle) {
LOG_TRACE(Kernel_SVC, "called thread=0x{:08X}", handle); LOG_TRACE(Kernel_SVC, "called thread=0x{:08X}", handle);
const SharedPtr<Thread> thread = g_handle_table.Get<Thread>(handle); const SharedPtr<Thread> thread =
Core::System::GetInstance().Kernel().GetCurrentProcess()->handle_table.Get<Thread>(handle);
if (thread == nullptr) if (thread == nullptr)
return ERR_INVALID_HANDLE; return ERR_INVALID_HANDLE;
@ -897,10 +925,12 @@ static ResultCode GetThreadId(u32* thread_id, Handle handle) {
/// Creates a semaphore /// Creates a semaphore
static ResultCode CreateSemaphore(Handle* out_handle, s32 initial_count, s32 max_count) { static ResultCode CreateSemaphore(Handle* out_handle, s32 initial_count, s32 max_count) {
KernelSystem& kernel = Core::System::GetInstance().Kernel();
CASCADE_RESULT(SharedPtr<Semaphore> semaphore, CASCADE_RESULT(SharedPtr<Semaphore> semaphore,
Core::System::GetInstance().Kernel().CreateSemaphore(initial_count, max_count)); kernel.CreateSemaphore(initial_count, max_count));
semaphore->name = fmt::format("semaphore-{:08x}", Core::CPU().GetReg(14)); semaphore->name = fmt::format("semaphore-{:08x}", Core::CPU().GetReg(14));
CASCADE_RESULT(*out_handle, g_handle_table.Create(std::move(semaphore))); CASCADE_RESULT(*out_handle,
kernel.GetCurrentProcess()->handle_table.Create(std::move(semaphore)));
LOG_TRACE(Kernel_SVC, "called initial_count={}, max_count={}, created handle=0x{:08X}", LOG_TRACE(Kernel_SVC, "called initial_count={}, max_count={}, created handle=0x{:08X}",
initial_count, max_count, *out_handle); initial_count, max_count, *out_handle);
@ -911,7 +941,9 @@ static ResultCode CreateSemaphore(Handle* out_handle, s32 initial_count, s32 max
static ResultCode ReleaseSemaphore(s32* count, Handle handle, s32 release_count) { static ResultCode ReleaseSemaphore(s32* count, Handle handle, s32 release_count) {
LOG_TRACE(Kernel_SVC, "called release_count={}, handle=0x{:08X}", release_count, handle); LOG_TRACE(Kernel_SVC, "called release_count={}, handle=0x{:08X}", release_count, handle);
SharedPtr<Semaphore> semaphore = g_handle_table.Get<Semaphore>(handle); SharedPtr<Semaphore> semaphore =
Core::System::GetInstance().Kernel().GetCurrentProcess()->handle_table.Get<Semaphore>(
handle);
if (semaphore == nullptr) if (semaphore == nullptr)
return ERR_INVALID_HANDLE; return ERR_INVALID_HANDLE;
@ -923,7 +955,9 @@ static ResultCode ReleaseSemaphore(s32* count, Handle handle, s32 release_count)
/// Query process memory /// Query process memory
static ResultCode QueryProcessMemory(MemoryInfo* memory_info, PageInfo* page_info, static ResultCode QueryProcessMemory(MemoryInfo* memory_info, PageInfo* page_info,
Handle process_handle, u32 addr) { Handle process_handle, u32 addr) {
SharedPtr<Process> process = g_handle_table.Get<Process>(process_handle); SharedPtr<Process> process =
Core::System::GetInstance().Kernel().GetCurrentProcess()->handle_table.Get<Process>(
process_handle);
if (process == nullptr) if (process == nullptr)
return ERR_INVALID_HANDLE; return ERR_INVALID_HANDLE;
@ -949,9 +983,10 @@ static ResultCode QueryMemory(MemoryInfo* memory_info, PageInfo* page_info, u32
/// Create an event /// Create an event
static ResultCode CreateEvent(Handle* out_handle, u32 reset_type) { static ResultCode CreateEvent(Handle* out_handle, u32 reset_type) {
SharedPtr<Event> evt = Core::System::GetInstance().Kernel().CreateEvent( KernelSystem& kernel = Core::System::GetInstance().Kernel();
static_cast<ResetType>(reset_type), fmt::format("event-{:08x}", Core::CPU().GetReg(14))); SharedPtr<Event> evt = kernel.CreateEvent(static_cast<ResetType>(reset_type),
CASCADE_RESULT(*out_handle, g_handle_table.Create(std::move(evt))); fmt::format("event-{:08x}", Core::CPU().GetReg(14)));
CASCADE_RESULT(*out_handle, kernel.GetCurrentProcess()->handle_table.Create(std::move(evt)));
LOG_TRACE(Kernel_SVC, "called reset_type=0x{:08X} : created handle=0x{:08X}", reset_type, LOG_TRACE(Kernel_SVC, "called reset_type=0x{:08X} : created handle=0x{:08X}", reset_type,
*out_handle); *out_handle);
@ -960,7 +995,9 @@ static ResultCode CreateEvent(Handle* out_handle, u32 reset_type) {
/// Duplicates a kernel handle /// Duplicates a kernel handle
static ResultCode DuplicateHandle(Handle* out, Handle handle) { static ResultCode DuplicateHandle(Handle* out, Handle handle) {
CASCADE_RESULT(*out, g_handle_table.Duplicate(handle)); CASCADE_RESULT(
*out,
Core::System::GetInstance().Kernel().GetCurrentProcess()->handle_table.Duplicate(handle));
LOG_TRACE(Kernel_SVC, "duplicated 0x{:08X} to 0x{:08X}", handle, *out); LOG_TRACE(Kernel_SVC, "duplicated 0x{:08X} to 0x{:08X}", handle, *out);
return RESULT_SUCCESS; return RESULT_SUCCESS;
} }
@ -969,7 +1006,8 @@ static ResultCode DuplicateHandle(Handle* out, Handle handle) {
static ResultCode SignalEvent(Handle handle) { static ResultCode SignalEvent(Handle handle) {
LOG_TRACE(Kernel_SVC, "called event=0x{:08X}", handle); LOG_TRACE(Kernel_SVC, "called event=0x{:08X}", handle);
SharedPtr<Event> evt = g_handle_table.Get<Event>(handle); SharedPtr<Event> evt =
Core::System::GetInstance().Kernel().GetCurrentProcess()->handle_table.Get<Event>(handle);
if (evt == nullptr) if (evt == nullptr)
return ERR_INVALID_HANDLE; return ERR_INVALID_HANDLE;
@ -982,7 +1020,8 @@ static ResultCode SignalEvent(Handle handle) {
static ResultCode ClearEvent(Handle handle) { static ResultCode ClearEvent(Handle handle) {
LOG_TRACE(Kernel_SVC, "called event=0x{:08X}", handle); LOG_TRACE(Kernel_SVC, "called event=0x{:08X}", handle);
SharedPtr<Event> evt = g_handle_table.Get<Event>(handle); SharedPtr<Event> evt =
Core::System::GetInstance().Kernel().GetCurrentProcess()->handle_table.Get<Event>(handle);
if (evt == nullptr) if (evt == nullptr)
return ERR_INVALID_HANDLE; return ERR_INVALID_HANDLE;
@ -992,9 +1031,10 @@ static ResultCode ClearEvent(Handle handle) {
/// Creates a timer /// Creates a timer
static ResultCode CreateTimer(Handle* out_handle, u32 reset_type) { static ResultCode CreateTimer(Handle* out_handle, u32 reset_type) {
SharedPtr<Timer> timer = Core::System::GetInstance().Kernel().CreateTimer( KernelSystem& kernel = Core::System::GetInstance().Kernel();
SharedPtr<Timer> timer = kernel.CreateTimer(
static_cast<ResetType>(reset_type), fmt ::format("timer-{:08x}", Core::CPU().GetReg(14))); static_cast<ResetType>(reset_type), fmt ::format("timer-{:08x}", Core::CPU().GetReg(14)));
CASCADE_RESULT(*out_handle, g_handle_table.Create(std::move(timer))); CASCADE_RESULT(*out_handle, kernel.GetCurrentProcess()->handle_table.Create(std::move(timer)));
LOG_TRACE(Kernel_SVC, "called reset_type=0x{:08X} : created handle=0x{:08X}", reset_type, LOG_TRACE(Kernel_SVC, "called reset_type=0x{:08X} : created handle=0x{:08X}", reset_type,
*out_handle); *out_handle);
@ -1005,7 +1045,8 @@ static ResultCode CreateTimer(Handle* out_handle, u32 reset_type) {
static ResultCode ClearTimer(Handle handle) { static ResultCode ClearTimer(Handle handle) {
LOG_TRACE(Kernel_SVC, "called timer=0x{:08X}", handle); LOG_TRACE(Kernel_SVC, "called timer=0x{:08X}", handle);
SharedPtr<Timer> timer = g_handle_table.Get<Timer>(handle); SharedPtr<Timer> timer =
Core::System::GetInstance().Kernel().GetCurrentProcess()->handle_table.Get<Timer>(handle);
if (timer == nullptr) if (timer == nullptr)
return ERR_INVALID_HANDLE; return ERR_INVALID_HANDLE;
@ -1021,7 +1062,8 @@ static ResultCode SetTimer(Handle handle, s64 initial, s64 interval) {
return ERR_OUT_OF_RANGE_KERNEL; return ERR_OUT_OF_RANGE_KERNEL;
} }
SharedPtr<Timer> timer = g_handle_table.Get<Timer>(handle); SharedPtr<Timer> timer =
Core::System::GetInstance().Kernel().GetCurrentProcess()->handle_table.Get<Timer>(handle);
if (timer == nullptr) if (timer == nullptr)
return ERR_INVALID_HANDLE; return ERR_INVALID_HANDLE;
@ -1034,7 +1076,8 @@ static ResultCode SetTimer(Handle handle, s64 initial, s64 interval) {
static ResultCode CancelTimer(Handle handle) { static ResultCode CancelTimer(Handle handle) {
LOG_TRACE(Kernel_SVC, "called timer=0x{:08X}", handle); LOG_TRACE(Kernel_SVC, "called timer=0x{:08X}", handle);
SharedPtr<Timer> timer = g_handle_table.Get<Timer>(handle); SharedPtr<Timer> timer =
Core::System::GetInstance().Kernel().GetCurrentProcess()->handle_table.Get<Timer>(handle);
if (timer == nullptr) if (timer == nullptr)
return ERR_INVALID_HANDLE; return ERR_INVALID_HANDLE;
@ -1116,7 +1159,7 @@ static ResultCode CreateMemoryBlock(Handle* out_handle, u32 addr, u32 size, u32
shared_memory = Core::System::GetInstance().Kernel().CreateSharedMemory( shared_memory = Core::System::GetInstance().Kernel().CreateSharedMemory(
current_process, size, static_cast<MemoryPermission>(my_permission), current_process, size, static_cast<MemoryPermission>(my_permission),
static_cast<MemoryPermission>(other_permission), addr, region); static_cast<MemoryPermission>(other_permission), addr, region);
CASCADE_RESULT(*out_handle, g_handle_table.Create(std::move(shared_memory))); CASCADE_RESULT(*out_handle, current_process->handle_table.Create(std::move(shared_memory)));
LOG_WARNING(Kernel_SVC, "called addr=0x{:08X}", addr); LOG_WARNING(Kernel_SVC, "called addr=0x{:08X}", addr);
return RESULT_SUCCESS; return RESULT_SUCCESS;
@ -1127,48 +1170,58 @@ static ResultCode CreatePort(Handle* server_port, Handle* client_port, VAddr nam
// TODO(Subv): Implement named ports. // TODO(Subv): Implement named ports.
ASSERT_MSG(name_address == 0, "Named ports are currently unimplemented"); ASSERT_MSG(name_address == 0, "Named ports are currently unimplemented");
auto ports = Core::System::GetInstance().Kernel().CreatePortPair(max_sessions); KernelSystem& kernel = Core::System::GetInstance().Kernel();
CASCADE_RESULT(*client_port, SharedPtr<Process> current_process = kernel.GetCurrentProcess();
g_handle_table.Create(std::move(std::get<SharedPtr<ClientPort>>(ports))));
auto ports = kernel.CreatePortPair(max_sessions);
CASCADE_RESULT(*client_port, current_process->handle_table.Create(
std::move(std::get<SharedPtr<ClientPort>>(ports))));
// Note: The 3DS kernel also leaks the client port handle if the server port handle fails to be // Note: The 3DS kernel also leaks the client port handle if the server port handle fails to be
// created. // created.
CASCADE_RESULT(*server_port, CASCADE_RESULT(*server_port, current_process->handle_table.Create(
g_handle_table.Create(std::move(std::get<SharedPtr<ServerPort>>(ports)))); std::move(std::get<SharedPtr<ServerPort>>(ports))));
LOG_TRACE(Kernel_SVC, "called max_sessions={}", max_sessions); LOG_TRACE(Kernel_SVC, "called max_sessions={}", max_sessions);
return RESULT_SUCCESS; return RESULT_SUCCESS;
} }
static ResultCode CreateSessionToPort(Handle* out_client_session, Handle client_port_handle) { static ResultCode CreateSessionToPort(Handle* out_client_session, Handle client_port_handle) {
SharedPtr<ClientPort> client_port = g_handle_table.Get<ClientPort>(client_port_handle); SharedPtr<Process> current_process = Core::System::GetInstance().Kernel().GetCurrentProcess();
SharedPtr<ClientPort> client_port =
current_process->handle_table.Get<ClientPort>(client_port_handle);
if (client_port == nullptr) if (client_port == nullptr)
return ERR_INVALID_HANDLE; return ERR_INVALID_HANDLE;
CASCADE_RESULT(auto session, client_port->Connect()); CASCADE_RESULT(auto session, client_port->Connect());
CASCADE_RESULT(*out_client_session, g_handle_table.Create(std::move(session))); CASCADE_RESULT(*out_client_session, current_process->handle_table.Create(std::move(session)));
return RESULT_SUCCESS; return RESULT_SUCCESS;
} }
static ResultCode CreateSession(Handle* server_session, Handle* client_session) { static ResultCode CreateSession(Handle* server_session, Handle* client_session) {
auto sessions = Core::System::GetInstance().Kernel().CreateSessionPair(); KernelSystem& kernel = Core::System::GetInstance().Kernel();
auto sessions = kernel.CreateSessionPair();
SharedPtr<Process> current_process = kernel.GetCurrentProcess();
auto& server = std::get<SharedPtr<ServerSession>>(sessions); auto& server = std::get<SharedPtr<ServerSession>>(sessions);
CASCADE_RESULT(*server_session, g_handle_table.Create(std::move(server))); CASCADE_RESULT(*server_session, current_process->handle_table.Create(std::move(server)));
auto& client = std::get<SharedPtr<ClientSession>>(sessions); auto& client = std::get<SharedPtr<ClientSession>>(sessions);
CASCADE_RESULT(*client_session, g_handle_table.Create(std::move(client))); CASCADE_RESULT(*client_session, current_process->handle_table.Create(std::move(client)));
LOG_TRACE(Kernel_SVC, "called"); LOG_TRACE(Kernel_SVC, "called");
return RESULT_SUCCESS; return RESULT_SUCCESS;
} }
static ResultCode AcceptSession(Handle* out_server_session, Handle server_port_handle) { static ResultCode AcceptSession(Handle* out_server_session, Handle server_port_handle) {
SharedPtr<ServerPort> server_port = g_handle_table.Get<ServerPort>(server_port_handle); SharedPtr<Process> current_process = Core::System::GetInstance().Kernel().GetCurrentProcess();
SharedPtr<ServerPort> server_port =
current_process->handle_table.Get<ServerPort>(server_port_handle);
if (server_port == nullptr) if (server_port == nullptr)
return ERR_INVALID_HANDLE; return ERR_INVALID_HANDLE;
CASCADE_RESULT(auto session, server_port->Accept()); CASCADE_RESULT(auto session, server_port->Accept());
CASCADE_RESULT(*out_server_session, g_handle_table.Create(std::move(session))); CASCADE_RESULT(*out_server_session, current_process->handle_table.Create(std::move(session)));
return RESULT_SUCCESS; return RESULT_SUCCESS;
} }
@ -1218,7 +1271,9 @@ static ResultCode GetSystemInfo(s64* out, u32 type, s32 param) {
static ResultCode GetProcessInfo(s64* out, Handle process_handle, u32 type) { static ResultCode GetProcessInfo(s64* out, Handle process_handle, u32 type) {
LOG_TRACE(Kernel_SVC, "called process=0x{:08X} type={}", process_handle, type); LOG_TRACE(Kernel_SVC, "called process=0x{:08X} type={}", process_handle, type);
SharedPtr<Process> process = g_handle_table.Get<Process>(process_handle); SharedPtr<Process> process =
Core::System::GetInstance().Kernel().GetCurrentProcess()->handle_table.Get<Process>(
process_handle);
if (process == nullptr) if (process == nullptr)
return ERR_INVALID_HANDLE; return ERR_INVALID_HANDLE;

@ -194,7 +194,7 @@ void ServiceFrameworkBase::HandleSyncRequest(SharedPtr<ServerSession> server_ses
// TODO(yuriks): The kernel should be the one handling this as part of translation after // TODO(yuriks): The kernel should be the one handling this as part of translation after
// everything else is migrated // everything else is migrated
Kernel::HLERequestContext context(std::move(server_session)); Kernel::HLERequestContext context(std::move(server_session));
context.PopulateFromIncomingCommandBuffer(cmd_buf, *current_process, Kernel::g_handle_table); context.PopulateFromIncomingCommandBuffer(cmd_buf, *current_process);
LOG_TRACE(Service, "{}", MakeFunctionString(info->name, GetServiceName().c_str(), cmd_buf)); LOG_TRACE(Service, "{}", MakeFunctionString(info->name, GetServiceName().c_str(), cmd_buf));
handler_invoker(this, info->handler_callback, context); handler_invoker(this, info->handler_callback, context);
@ -206,7 +206,7 @@ void ServiceFrameworkBase::HandleSyncRequest(SharedPtr<ServerSession> server_ses
// the thread to sleep then the writing of the command buffer will be deferred to the wakeup // the thread to sleep then the writing of the command buffer will be deferred to the wakeup
// callback. // callback.
if (thread->status == Kernel::ThreadStatus::Running) { if (thread->status == Kernel::ThreadStatus::Running) {
context.WriteToOutgoingCommandBuffer(cmd_buf, *current_process, Kernel::g_handle_table); context.WriteToOutgoingCommandBuffer(cmd_buf, *current_process);
} }
} }

@ -26,14 +26,13 @@ TEST_CASE("HLERequestContext::PopulateFromIncomingCommandBuffer", "[core][kernel
HLERequestContext context(std::move(session)); HLERequestContext context(std::move(session));
auto process = kernel.CreateProcess(kernel.CreateCodeSet("", 0)); auto process = kernel.CreateProcess(kernel.CreateCodeSet("", 0));
HandleTable handle_table;
SECTION("works with empty cmdbuf") { SECTION("works with empty cmdbuf") {
const u32_le input[]{ const u32_le input[]{
IPC::MakeHeader(0x1234, 0, 0), IPC::MakeHeader(0x1234, 0, 0),
}; };
context.PopulateFromIncomingCommandBuffer(input, *process, handle_table); context.PopulateFromIncomingCommandBuffer(input, *process);
REQUIRE(context.CommandBuffer()[0] == 0x12340000); REQUIRE(context.CommandBuffer()[0] == 0x12340000);
} }
@ -46,7 +45,7 @@ TEST_CASE("HLERequestContext::PopulateFromIncomingCommandBuffer", "[core][kernel
0xAABBCCDD, 0xAABBCCDD,
}; };
context.PopulateFromIncomingCommandBuffer(input, *process, handle_table); context.PopulateFromIncomingCommandBuffer(input, *process);
auto* output = context.CommandBuffer(); auto* output = context.CommandBuffer();
REQUIRE(output[1] == 0x12345678); REQUIRE(output[1] == 0x12345678);
@ -56,34 +55,34 @@ TEST_CASE("HLERequestContext::PopulateFromIncomingCommandBuffer", "[core][kernel
SECTION("translates move handles") { SECTION("translates move handles") {
auto a = MakeObject(kernel); auto a = MakeObject(kernel);
Handle a_handle = handle_table.Create(a).Unwrap(); Handle a_handle = process->handle_table.Create(a).Unwrap();
const u32_le input[]{ const u32_le input[]{
IPC::MakeHeader(0, 0, 2), IPC::MakeHeader(0, 0, 2),
IPC::MoveHandleDesc(1), IPC::MoveHandleDesc(1),
a_handle, a_handle,
}; };
context.PopulateFromIncomingCommandBuffer(input, *process, handle_table); context.PopulateFromIncomingCommandBuffer(input, *process);
auto* output = context.CommandBuffer(); auto* output = context.CommandBuffer();
REQUIRE(context.GetIncomingHandle(output[2]) == a); REQUIRE(context.GetIncomingHandle(output[2]) == a);
REQUIRE(handle_table.GetGeneric(a_handle) == nullptr); REQUIRE(process->handle_table.GetGeneric(a_handle) == nullptr);
} }
SECTION("translates copy handles") { SECTION("translates copy handles") {
auto a = MakeObject(kernel); auto a = MakeObject(kernel);
Handle a_handle = handle_table.Create(a).Unwrap(); Handle a_handle = process->handle_table.Create(a).Unwrap();
const u32_le input[]{ const u32_le input[]{
IPC::MakeHeader(0, 0, 2), IPC::MakeHeader(0, 0, 2),
IPC::CopyHandleDesc(1), IPC::CopyHandleDesc(1),
a_handle, a_handle,
}; };
context.PopulateFromIncomingCommandBuffer(input, *process, handle_table); context.PopulateFromIncomingCommandBuffer(input, *process);
auto* output = context.CommandBuffer(); auto* output = context.CommandBuffer();
REQUIRE(context.GetIncomingHandle(output[2]) == a); REQUIRE(context.GetIncomingHandle(output[2]) == a);
REQUIRE(handle_table.GetGeneric(a_handle) == a); REQUIRE(process->handle_table.GetGeneric(a_handle) == a);
} }
SECTION("translates multi-handle descriptors") { SECTION("translates multi-handle descriptors") {
@ -91,12 +90,15 @@ TEST_CASE("HLERequestContext::PopulateFromIncomingCommandBuffer", "[core][kernel
auto b = MakeObject(kernel); auto b = MakeObject(kernel);
auto c = MakeObject(kernel); auto c = MakeObject(kernel);
const u32_le input[]{ const u32_le input[]{
IPC::MakeHeader(0, 0, 5), IPC::MoveHandleDesc(2), IPC::MakeHeader(0, 0, 5),
handle_table.Create(a).Unwrap(), handle_table.Create(b).Unwrap(), IPC::MoveHandleDesc(2),
IPC::MoveHandleDesc(1), handle_table.Create(c).Unwrap(), process->handle_table.Create(a).Unwrap(),
process->handle_table.Create(b).Unwrap(),
IPC::MoveHandleDesc(1),
process->handle_table.Create(c).Unwrap(),
}; };
context.PopulateFromIncomingCommandBuffer(input, *process, handle_table); context.PopulateFromIncomingCommandBuffer(input, *process);
auto* output = context.CommandBuffer(); auto* output = context.CommandBuffer();
REQUIRE(context.GetIncomingHandle(output[2]) == a); REQUIRE(context.GetIncomingHandle(output[2]) == a);
@ -111,7 +113,7 @@ TEST_CASE("HLERequestContext::PopulateFromIncomingCommandBuffer", "[core][kernel
0, 0,
}; };
auto result = context.PopulateFromIncomingCommandBuffer(input, *process, handle_table); auto result = context.PopulateFromIncomingCommandBuffer(input, *process);
REQUIRE(result == RESULT_SUCCESS); REQUIRE(result == RESULT_SUCCESS);
auto* output = context.CommandBuffer(); auto* output = context.CommandBuffer();
@ -125,7 +127,7 @@ TEST_CASE("HLERequestContext::PopulateFromIncomingCommandBuffer", "[core][kernel
0x98989898, 0x98989898,
}; };
context.PopulateFromIncomingCommandBuffer(input, *process, handle_table); context.PopulateFromIncomingCommandBuffer(input, *process);
REQUIRE(context.CommandBuffer()[2] == process->process_id); REQUIRE(context.CommandBuffer()[2] == process->process_id);
} }
@ -145,7 +147,7 @@ TEST_CASE("HLERequestContext::PopulateFromIncomingCommandBuffer", "[core][kernel
target_address, target_address,
}; };
context.PopulateFromIncomingCommandBuffer(input, *process, handle_table); context.PopulateFromIncomingCommandBuffer(input, *process);
CHECK(context.GetStaticBuffer(0) == *buffer); CHECK(context.GetStaticBuffer(0) == *buffer);
@ -166,7 +168,7 @@ TEST_CASE("HLERequestContext::PopulateFromIncomingCommandBuffer", "[core][kernel
target_address, target_address,
}; };
context.PopulateFromIncomingCommandBuffer(input, *process, handle_table); context.PopulateFromIncomingCommandBuffer(input, *process);
std::vector<u8> other_buffer(buffer->size()); std::vector<u8> other_buffer(buffer->size());
context.GetMappedBuffer(0).Read(other_buffer.data(), 0, buffer->size()); context.GetMappedBuffer(0).Read(other_buffer.data(), 0, buffer->size());
@ -199,7 +201,7 @@ TEST_CASE("HLERequestContext::PopulateFromIncomingCommandBuffer", "[core][kernel
0x12345678, 0x12345678,
0xABCDEF00, 0xABCDEF00,
IPC::MoveHandleDesc(1), IPC::MoveHandleDesc(1),
handle_table.Create(a).Unwrap(), process->handle_table.Create(a).Unwrap(),
IPC::CallingPidDesc(), IPC::CallingPidDesc(),
0, 0,
IPC::StaticBufferDesc(buffer_static->size(), 0), IPC::StaticBufferDesc(buffer_static->size(), 0),
@ -208,7 +210,7 @@ TEST_CASE("HLERequestContext::PopulateFromIncomingCommandBuffer", "[core][kernel
target_address_mapped, target_address_mapped,
}; };
context.PopulateFromIncomingCommandBuffer(input, *process, handle_table); context.PopulateFromIncomingCommandBuffer(input, *process);
auto* output = context.CommandBuffer(); auto* output = context.CommandBuffer();
CHECK(output[1] == 0x12345678); CHECK(output[1] == 0x12345678);
@ -236,14 +238,13 @@ TEST_CASE("HLERequestContext::WriteToOutgoingCommandBuffer", "[core][kernel]") {
HLERequestContext context(std::move(session)); HLERequestContext context(std::move(session));
auto process = kernel.CreateProcess(kernel.CreateCodeSet("", 0)); auto process = kernel.CreateProcess(kernel.CreateCodeSet("", 0));
HandleTable handle_table;
auto* input = context.CommandBuffer(); auto* input = context.CommandBuffer();
u32_le output[IPC::COMMAND_BUFFER_LENGTH]; u32_le output[IPC::COMMAND_BUFFER_LENGTH];
SECTION("works with empty cmdbuf") { SECTION("works with empty cmdbuf") {
input[0] = IPC::MakeHeader(0x1234, 0, 0); input[0] = IPC::MakeHeader(0x1234, 0, 0);
context.WriteToOutgoingCommandBuffer(output, *process, handle_table); context.WriteToOutgoingCommandBuffer(output, *process);
REQUIRE(output[0] == 0x12340000); REQUIRE(output[0] == 0x12340000);
} }
@ -254,7 +255,7 @@ TEST_CASE("HLERequestContext::WriteToOutgoingCommandBuffer", "[core][kernel]") {
input[2] = 0x21122112; input[2] = 0x21122112;
input[3] = 0xAABBCCDD; input[3] = 0xAABBCCDD;
context.WriteToOutgoingCommandBuffer(output, *process, handle_table); context.WriteToOutgoingCommandBuffer(output, *process);
REQUIRE(output[1] == 0x12345678); REQUIRE(output[1] == 0x12345678);
REQUIRE(output[2] == 0x21122112); REQUIRE(output[2] == 0x21122112);
@ -270,10 +271,10 @@ TEST_CASE("HLERequestContext::WriteToOutgoingCommandBuffer", "[core][kernel]") {
input[3] = IPC::CopyHandleDesc(1); input[3] = IPC::CopyHandleDesc(1);
input[4] = context.AddOutgoingHandle(b); input[4] = context.AddOutgoingHandle(b);
context.WriteToOutgoingCommandBuffer(output, *process, handle_table); context.WriteToOutgoingCommandBuffer(output, *process);
REQUIRE(handle_table.GetGeneric(output[2]) == a); REQUIRE(process->handle_table.GetGeneric(output[2]) == a);
REQUIRE(handle_table.GetGeneric(output[4]) == b); REQUIRE(process->handle_table.GetGeneric(output[4]) == b);
} }
SECTION("translates null handles") { SECTION("translates null handles") {
@ -281,7 +282,7 @@ TEST_CASE("HLERequestContext::WriteToOutgoingCommandBuffer", "[core][kernel]") {
input[1] = IPC::MoveHandleDesc(1); input[1] = IPC::MoveHandleDesc(1);
input[2] = context.AddOutgoingHandle(nullptr); input[2] = context.AddOutgoingHandle(nullptr);
auto result = context.WriteToOutgoingCommandBuffer(output, *process, handle_table); auto result = context.WriteToOutgoingCommandBuffer(output, *process);
REQUIRE(result == RESULT_SUCCESS); REQUIRE(result == RESULT_SUCCESS);
REQUIRE(output[2] == 0); REQUIRE(output[2] == 0);
@ -298,11 +299,11 @@ TEST_CASE("HLERequestContext::WriteToOutgoingCommandBuffer", "[core][kernel]") {
input[4] = IPC::CopyHandleDesc(1); input[4] = IPC::CopyHandleDesc(1);
input[5] = context.AddOutgoingHandle(c); input[5] = context.AddOutgoingHandle(c);
context.WriteToOutgoingCommandBuffer(output, *process, handle_table); context.WriteToOutgoingCommandBuffer(output, *process);
REQUIRE(handle_table.GetGeneric(output[2]) == a); REQUIRE(process->handle_table.GetGeneric(output[2]) == a);
REQUIRE(handle_table.GetGeneric(output[3]) == b); REQUIRE(process->handle_table.GetGeneric(output[3]) == b);
REQUIRE(handle_table.GetGeneric(output[5]) == c); REQUIRE(process->handle_table.GetGeneric(output[5]) == c);
} }
SECTION("translates StaticBuffer descriptors") { SECTION("translates StaticBuffer descriptors") {
@ -329,7 +330,7 @@ TEST_CASE("HLERequestContext::WriteToOutgoingCommandBuffer", "[core][kernel]") {
IPC::StaticBufferDesc(output_buffer->size(), 0); IPC::StaticBufferDesc(output_buffer->size(), 0);
output_cmdbuff[IPC::COMMAND_BUFFER_LENGTH + 1] = target_address; output_cmdbuff[IPC::COMMAND_BUFFER_LENGTH + 1] = target_address;
context.WriteToOutgoingCommandBuffer(output_cmdbuff.data(), *process, handle_table); context.WriteToOutgoingCommandBuffer(output_cmdbuff.data(), *process);
CHECK(*output_buffer == input_buffer); CHECK(*output_buffer == input_buffer);
REQUIRE(process->vm_manager.UnmapRange(target_address, output_buffer->size()) == REQUIRE(process->vm_manager.UnmapRange(target_address, output_buffer->size()) ==
@ -352,7 +353,7 @@ TEST_CASE("HLERequestContext::WriteToOutgoingCommandBuffer", "[core][kernel]") {
target_address, target_address,
}; };
context.PopulateFromIncomingCommandBuffer(input_cmdbuff, *process, handle_table); context.PopulateFromIncomingCommandBuffer(input_cmdbuff, *process);
context.GetMappedBuffer(0).Write(input_buffer.data(), 0, input_buffer.size()); context.GetMappedBuffer(0).Write(input_buffer.data(), 0, input_buffer.size());
@ -360,7 +361,7 @@ TEST_CASE("HLERequestContext::WriteToOutgoingCommandBuffer", "[core][kernel]") {
input[1] = IPC::MappedBufferDesc(output_buffer->size(), IPC::W); input[1] = IPC::MappedBufferDesc(output_buffer->size(), IPC::W);
input[2] = 0; input[2] = 0;
context.WriteToOutgoingCommandBuffer(output, *process, handle_table); context.WriteToOutgoingCommandBuffer(output, *process);
CHECK(output[1] == IPC::MappedBufferDesc(output_buffer->size(), IPC::W)); CHECK(output[1] == IPC::MappedBufferDesc(output_buffer->size(), IPC::W));
CHECK(output[2] == target_address); CHECK(output[2] == target_address);