Merge pull request #9832 from liamwhite/hle-mp

service: HLE multiprocess
This commit is contained in:
liamwhite
2023-03-01 10:38:20 -05:00
committed by GitHub
141 changed files with 1564 additions and 1148 deletions

View File

@ -126,6 +126,11 @@ Result GetInfo(Core::System& system, u64* result, InfoType info_id_type, Handle
*result = process->GetTotalPhysicalMemoryUsedWithoutSystemResource();
return ResultSuccess;
case InfoType::IsApplication:
LOG_WARNING(Kernel_SVC, "(STUBBED) Assuming process is application");
*result = true;
return ResultSuccess;
case InfoType::FreeThreadCount:
*result = process->GetFreeThreadCount();
return ResultSuccess;

View File

@ -12,56 +12,40 @@
namespace Kernel::Svc {
/// Connect to an OS service given the port name, returns the handle to the port to out
Result ConnectToNamedPort(Core::System& system, Handle* out, VAddr port_name_address) {
auto& memory = system.Memory();
if (!memory.IsValidVirtualAddress(port_name_address)) {
LOG_ERROR(Kernel_SVC,
"Port Name Address is not a valid virtual address, port_name_address=0x{:016X}",
port_name_address);
return ResultNotFound;
}
Result ConnectToNamedPort(Core::System& system, Handle* out, VAddr user_name) {
// Copy the provided name from user memory to kernel memory.
auto string_name = system.Memory().ReadCString(user_name, KObjectName::NameLengthMax);
static constexpr std::size_t PortNameMaxLength = 11;
// Read 1 char beyond the max allowed port name to detect names that are too long.
const std::string port_name = memory.ReadCString(port_name_address, PortNameMaxLength + 1);
if (port_name.size() > PortNameMaxLength) {
LOG_ERROR(Kernel_SVC, "Port name is too long, expected {} but got {}", PortNameMaxLength,
port_name.size());
return ResultOutOfRange;
}
std::array<char, KObjectName::NameLengthMax> name{};
std::strncpy(name.data(), string_name.c_str(), KObjectName::NameLengthMax - 1);
LOG_TRACE(Kernel_SVC, "called port_name={}", port_name);
// Validate that the name is valid.
R_UNLESS(name[sizeof(name) - 1] == '\x00', ResultOutOfRange);
// Get the current handle table.
auto& kernel = system.Kernel();
auto& handle_table = GetCurrentProcess(kernel).GetHandleTable();
auto& handle_table = GetCurrentProcess(system.Kernel()).GetHandleTable();
// Find the client port.
auto port = kernel.CreateNamedServicePort(port_name);
if (!port) {
LOG_ERROR(Kernel_SVC, "tried to connect to unknown port: {}", port_name);
return ResultNotFound;
}
auto port = KObjectName::Find<KClientPort>(system.Kernel(), name.data());
R_UNLESS(port.IsNotNull(), ResultNotFound);
// Reserve a handle for the port.
// NOTE: Nintendo really does write directly to the output handle here.
R_TRY(handle_table.Reserve(out));
auto handle_guard = SCOPE_GUARD({ handle_table.Unreserve(*out); });
ON_RESULT_FAILURE {
handle_table.Unreserve(*out);
};
// Create a session.
KClientSession* session{};
KClientSession* session;
R_TRY(port->CreateSession(std::addressof(session)));
kernel.RegisterNamedServiceHandler(port_name, &port->GetParent()->GetServerPort());
// Register the session in the table, close the extra reference.
handle_table.Register(*out, session);
session->Close();
// We succeeded.
handle_guard.Cancel();
return ResultSuccess;
R_SUCCEED();
}
Result CreatePort(Core::System& system, Handle* out_server, Handle* out_client,
@ -77,9 +61,12 @@ Result ConnectToPort(Core::System& system, Handle* out_handle, Handle port) {
Result ManageNamedPort(Core::System& system, Handle* out_server_handle, uint64_t user_name,
int32_t max_sessions) {
// Copy the provided name from user memory to kernel memory.
auto string_name = system.Memory().ReadCString(user_name, KObjectName::NameLengthMax);
// Copy the provided name from user memory to kernel memory.
std::array<char, KObjectName::NameLengthMax> name{};
system.Memory().ReadBlock(user_name, name.data(), sizeof(name));
std::strncpy(name.data(), string_name.c_str(), KObjectName::NameLengthMax - 1);
// Validate that sessions and name are valid.
R_UNLESS(max_sessions >= 0, ResultOutOfRange);