mirror of
https://github.com/Atmosphere-NX/Atmosphere.git
synced 2025-05-14 07:04:24 -04:00
kern: update initial process load logic to do per-segment mapping/decompression
This commit is contained in:
parent
cfd2d5b012
commit
3b8f65d502
3 changed files with 169 additions and 72 deletions
|
@ -156,40 +156,14 @@ namespace ams::kern {
|
|||
KPageGroup *process_pg = std::addressof(pg);
|
||||
ON_SCOPE_EXIT { process_pg->Close(); };
|
||||
|
||||
/* Get the temporary region. */
|
||||
const auto &temp_region = KMemoryLayout::GetTempRegion();
|
||||
MESOSPHERE_ABORT_UNLESS(temp_region.GetEndAddress() != 0);
|
||||
|
||||
/* Map the process's memory into the temporary region. */
|
||||
KProcessAddress temp_address = Null<KProcessAddress>;
|
||||
MESOSPHERE_R_ABORT_UNLESS(Kernel::GetKernelPageTable().MapPageGroup(std::addressof(temp_address), pg, temp_region.GetAddress(), temp_region.GetSize() / PageSize, KMemoryState_Kernel, KMemoryPermission_KernelReadWrite));
|
||||
|
||||
/* Setup the new page group's memory, so that we can load the process. */
|
||||
{
|
||||
/* Copy the unaligned ending of the compressed binary. */
|
||||
if (const size_t unaligned_size = binary_size - util::AlignDown(binary_size, PageSize); unaligned_size != 0) {
|
||||
std::memcpy(GetVoidPointer(temp_address + process_size - unaligned_size), GetVoidPointer(data + binary_size - unaligned_size), unaligned_size);
|
||||
}
|
||||
|
||||
/* Copy the aligned part of the compressed binary. */
|
||||
if (const size_t aligned_size = util::AlignDown(binary_size, PageSize); aligned_size != 0 && src_pool == dst_pool) {
|
||||
std::memmove(GetVoidPointer(temp_address + process_size - binary_size), GetVoidPointer(temp_address), aligned_size);
|
||||
} else {
|
||||
if (src_pool != dst_pool) {
|
||||
std::memcpy(GetVoidPointer(temp_address + process_size - binary_size), GetVoidPointer(data), aligned_size);
|
||||
Kernel::GetMemoryManager().Close(KMemoryLayout::GetLinearPhysicalAddress(data), aligned_size / PageSize);
|
||||
}
|
||||
}
|
||||
|
||||
/* Clear the first part of the memory. */
|
||||
std::memset(GetVoidPointer(temp_address), 0, process_size - binary_size);
|
||||
}
|
||||
|
||||
/* Load the process. */
|
||||
MESOSPHERE_R_ABORT_UNLESS(reader.Load(temp_address, params, temp_address + process_size - binary_size));
|
||||
reader.Load(pg, data);
|
||||
|
||||
/* Unmap the temporary mapping. */
|
||||
MESOSPHERE_R_ABORT_UNLESS(Kernel::GetKernelPageTable().UnmapPageGroup(temp_address, pg, KMemoryState_Kernel));
|
||||
/* If necessary, close/release the aligned part of the data we just loaded. */
|
||||
if (const size_t aligned_bin_size = util::AlignDown(binary_size, PageSize); aligned_bin_size != 0 && src_pool != dst_pool) {
|
||||
Kernel::GetMemoryManager().Close(KMemoryLayout::GetLinearPhysicalAddress(data), aligned_bin_size / PageSize);
|
||||
Kernel::GetSystemResourceLimit().Release(ams::svc::LimitableResource_PhysicalMemoryMax, aligned_bin_size);
|
||||
}
|
||||
|
||||
/* Create a KProcess object. */
|
||||
new_process = KProcess::Create();
|
||||
|
@ -242,11 +216,6 @@ namespace ams::kern {
|
|||
MESOSPHERE_R_ABORT_UNLESS(new_process->Initialize(params, *process_pg, reader.GetCapabilities(), reader.GetNumCapabilities(), std::addressof(Kernel::GetSystemResourceLimit()), dst_pool, reader.IsImmortal()));
|
||||
}
|
||||
|
||||
/* Release the memory that was previously reserved. */
|
||||
if (const size_t aligned_bin_size = util::AlignDown(binary_size, PageSize); aligned_bin_size != 0 && src_pool != dst_pool) {
|
||||
Kernel::GetSystemResourceLimit().Release(ams::svc::LimitableResource_PhysicalMemoryMax, aligned_bin_size);
|
||||
}
|
||||
|
||||
/* Set the process's memory permissions. */
|
||||
MESOSPHERE_R_ABORT_UNLESS(reader.SetMemoryPermissions(new_process->GetPageTable(), params));
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue