citra-emu
/
citra-canary
Archived
1
0
Fork 0

kernel: make handle table per-process

This commit is contained in:
Weiyi Wang 2018-10-19 21:04:18 -04:00
parent fda2a5cf54
commit eb285c33fd
11 changed files with 169 additions and 119 deletions

View File

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

View File

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

View File

@ -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;
Memory::ReadBlock(*process, thread->GetCommandBufferAddress(), cmd_buff.data(),
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.
Memory::WriteBlock(*process, thread->GetCommandBufferAddress(), cmd_buff.data(),
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,
Process& src_process,
HandleTable& src_table) {
Process& src_process) {
IPC::Header header{src_cmdbuf[0]};
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];
SharedPtr<Object> object = nullptr;
if (handle != 0) {
object = src_table.GetGeneric(handle);
object = src_process.handle_table.GetGeneric(handle);
ASSERT(object != nullptr); // TODO(yuriks): Return error
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;
}
ResultCode HLERequestContext::WriteToOutgoingCommandBuffer(u32_le* dst_cmdbuf, Process& dst_process,
HandleTable& dst_table) const {
ResultCode HLERequestContext::WriteToOutgoingCommandBuffer(u32_le* dst_cmdbuf,
Process& dst_process) const {
IPC::Header header{cmd_buf[0]};
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;
if (object != nullptr) {
// 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;
}

View File

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

View File

@ -60,9 +60,9 @@ ResultCode TranslateCommandBuffer(SharedPtr<Thread> src_thread, SharedPtr<Thread
} else if (handle == CurrentProcess) {
object = src_process;
} else if (handle != 0) {
object = g_handle_table.GetGeneric(handle);
object = src_process->handle_table.GetGeneric(handle);
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;
}
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);
}
break;

View File

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

View File

@ -300,7 +300,8 @@ ResultCode Process::LinearFree(VAddr target, u32 size) {
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() {}
SharedPtr<Process> KernelSystem::GetProcessById(u32 process_id) const {

View File

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

View File

@ -182,7 +182,9 @@ static ResultCode MapMemoryBlock(Handle handle, u32 addr, u32 permissions, u32 o
"otherpermission={}",
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)
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
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)
return ERR_INVALID_HANDLE;
return shared_memory->Unmap(Core::System::GetInstance().Kernel().GetCurrentProcess().get(),
addr);
return shared_memory->Unmap(current_process.get(), addr);
}
/// 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());
// 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;
}
/// Makes a blocking IPC call to an OS service.
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) {
return ERR_INVALID_HANDLE;
}
@ -265,12 +271,14 @@ static ResultCode SendSyncRequest(Handle handle) {
/// Close a handle
static ResultCode CloseHandle(Handle 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
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();
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) {
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)
return ERR_INVALID_HANDLE;
objects[i] = object;
@ -505,9 +515,11 @@ static ResultCode ReplyAndReceive(s32* index, VAddr handles_address, s32 handle_
using ObjectPtr = SharedPtr<WaitObject>;
std::vector<ObjectPtr> objects(handle_count);
SharedPtr<Process> current_process = Core::System::GetInstance().Kernel().GetCurrentProcess();
for (int i = 0; i < handle_count; ++i) {
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)
return ERR_INVALID_HANDLE;
objects[i] = object;
@ -518,7 +530,7 @@ static ResultCode ReplyAndReceive(s32* index, VAddr handles_address, s32 handle_
u32* cmd_buff = GetCommandBuffer();
IPC::Header header{cmd_buff[0]};
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)
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)
static ResultCode CreateAddressArbiter(Handle* out_handle) {
SharedPtr<AddressArbiter> arbiter = Core::System::GetInstance().Kernel().CreateAddressArbiter();
CASCADE_RESULT(*out_handle, g_handle_table.Create(std::move(arbiter)));
KernelSystem& kernel = Core::System::GetInstance().Kernel();
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);
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}",
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)
return ERR_INVALID_HANDLE;
@ -678,11 +694,12 @@ static void OutputDebugString(VAddr address, int len) {
static ResultCode GetResourceLimit(Handle* resource_limit, Handle 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)
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;
}
@ -694,7 +711,8 @@ static ResultCode GetResourceLimitCurrentValues(VAddr values, Handle resource_li
resource_limit_handle, names, name_count);
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)
return ERR_INVALID_HANDLE;
@ -714,7 +732,8 @@ static ResultCode GetResourceLimitLimitValues(VAddr values, Handle resource_limi
resource_limit_handle, names, name_count);
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)
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 |
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();
@ -795,7 +814,8 @@ static void ExitThread() {
/// Gets the priority for the specified thread
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)
return ERR_INVALID_HANDLE;
@ -809,7 +829,8 @@ static ResultCode SetThreadPriority(Handle handle, u32 priority) {
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)
return ERR_INVALID_HANDLE;
@ -834,9 +855,10 @@ static ResultCode SetThreadPriority(Handle handle, u32 priority) {
/// Create a mutex
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));
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}",
initial_locked ? "true" : "false", *out_handle);
@ -848,7 +870,8 @@ static ResultCode CreateMutex(Handle* out_handle, u32 initial_locked) {
static ResultCode ReleaseMutex(Handle 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)
return ERR_INVALID_HANDLE;
@ -859,7 +882,9 @@ static ResultCode ReleaseMutex(Handle handle) {
static ResultCode GetProcessId(u32* process_id, Handle 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)
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) {
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)
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) {
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)
return ERR_INVALID_HANDLE;
@ -897,10 +925,12 @@ static ResultCode GetThreadId(u32* thread_id, Handle handle) {
/// Creates a semaphore
static ResultCode CreateSemaphore(Handle* out_handle, s32 initial_count, s32 max_count) {
KernelSystem& kernel = Core::System::GetInstance().Kernel();
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));
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}",
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) {
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)
return ERR_INVALID_HANDLE;
@ -923,7 +955,9 @@ static ResultCode ReleaseSemaphore(s32* count, Handle handle, s32 release_count)
/// Query process memory
static ResultCode QueryProcessMemory(MemoryInfo* memory_info, PageInfo* page_info,
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)
return ERR_INVALID_HANDLE;
@ -949,9 +983,10 @@ static ResultCode QueryMemory(MemoryInfo* memory_info, PageInfo* page_info, u32
/// Create an event
static ResultCode CreateEvent(Handle* out_handle, u32 reset_type) {
SharedPtr<Event> evt = Core::System::GetInstance().Kernel().CreateEvent(
static_cast<ResetType>(reset_type), fmt::format("event-{:08x}", Core::CPU().GetReg(14)));
CASCADE_RESULT(*out_handle, g_handle_table.Create(std::move(evt)));
KernelSystem& kernel = Core::System::GetInstance().Kernel();
SharedPtr<Event> evt = kernel.CreateEvent(static_cast<ResetType>(reset_type),
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,
*out_handle);
@ -960,7 +995,9 @@ static ResultCode CreateEvent(Handle* out_handle, u32 reset_type) {
/// Duplicates a kernel 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);
return RESULT_SUCCESS;
}
@ -969,7 +1006,8 @@ static ResultCode DuplicateHandle(Handle* out, Handle handle) {
static ResultCode SignalEvent(Handle 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)
return ERR_INVALID_HANDLE;
@ -982,7 +1020,8 @@ static ResultCode SignalEvent(Handle handle) {
static ResultCode ClearEvent(Handle 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)
return ERR_INVALID_HANDLE;
@ -992,9 +1031,10 @@ static ResultCode ClearEvent(Handle handle) {
/// Creates a timer
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)));
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,
*out_handle);
@ -1005,7 +1045,8 @@ static ResultCode CreateTimer(Handle* out_handle, u32 reset_type) {
static ResultCode ClearTimer(Handle 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)
return ERR_INVALID_HANDLE;
@ -1021,7 +1062,8 @@ static ResultCode SetTimer(Handle handle, s64 initial, s64 interval) {
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)
return ERR_INVALID_HANDLE;
@ -1034,7 +1076,8 @@ static ResultCode SetTimer(Handle handle, s64 initial, s64 interval) {
static ResultCode CancelTimer(Handle 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)
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(
current_process, size, static_cast<MemoryPermission>(my_permission),
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);
return RESULT_SUCCESS;
@ -1127,48 +1170,58 @@ static ResultCode CreatePort(Handle* server_port, Handle* client_port, VAddr nam
// TODO(Subv): Implement named ports.
ASSERT_MSG(name_address == 0, "Named ports are currently unimplemented");
auto ports = Core::System::GetInstance().Kernel().CreatePortPair(max_sessions);
CASCADE_RESULT(*client_port,
g_handle_table.Create(std::move(std::get<SharedPtr<ClientPort>>(ports))));
KernelSystem& kernel = Core::System::GetInstance().Kernel();
SharedPtr<Process> current_process = kernel.GetCurrentProcess();
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
// created.
CASCADE_RESULT(*server_port,
g_handle_table.Create(std::move(std::get<SharedPtr<ServerPort>>(ports))));
CASCADE_RESULT(*server_port, current_process->handle_table.Create(
std::move(std::get<SharedPtr<ServerPort>>(ports))));
LOG_TRACE(Kernel_SVC, "called max_sessions={}", max_sessions);
return RESULT_SUCCESS;
}
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)
return ERR_INVALID_HANDLE;
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;
}
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);
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);
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");
return RESULT_SUCCESS;
}
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)
return ERR_INVALID_HANDLE;
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;
}
@ -1218,7 +1271,9 @@ static ResultCode GetSystemInfo(s64* out, u32 type, s32 param) {
static ResultCode GetProcessInfo(s64* out, Handle process_handle, u32 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)
return ERR_INVALID_HANDLE;

View File

@ -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
// everything else is migrated
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));
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
// callback.
if (thread->status == Kernel::ThreadStatus::Running) {
context.WriteToOutgoingCommandBuffer(cmd_buf, *current_process, Kernel::g_handle_table);
context.WriteToOutgoingCommandBuffer(cmd_buf, *current_process);
}
}

View File

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