Move SvcMap/UnmapMemory inside the memory manager

This commit is contained in:
TheASVigilante 2023-05-05 19:07:01 +02:00
parent 850f616dc7
commit 242e39dc4d
3 changed files with 48 additions and 18 deletions

View File

@ -500,6 +500,46 @@ namespace skyline::kernel {
Logger::Error("Failed to free memory: {}", strerror(errno)); Logger::Error("Failed to free memory: {}", strerror(errno));
} }
void MemoryManager::SvcMapMemory(span<u8> source, span<u8> destination) {
std::unique_lock lock{mutex};
MapInternal(std::pair<u8 *, ChunkDescriptor>(
destination.data(),{
.size = destination.size(),
.permission = {true, true, false},
.state = memory::states::Stack,
.isSrcMergeDisallowed = true
}));
std::memcpy(destination.data(), source.data(), source.size());
ForeachChunkinRange(source, [&](std::pair<u8 *, ChunkDescriptor> &desc) __attribute__((always_inline)) {
desc.second.permission = {false, false, false};
desc.second.attributes.isBorrowed = true;
MapInternal(desc);
});
}
void MemoryManager::SvcUnmapMemory(span<u8> source, span<u8> destination) {
std::unique_lock lock{mutex};
auto dstChunk = chunks.lower_bound(destination.data());
if (destination.data() < dstChunk->first)
--dstChunk;
while (dstChunk->second.state.value == memory::states::Unmapped)
++dstChunk;
if ((destination.data() + destination.size()) > dstChunk->first) [[likely]] {
ForeachChunkinRange(span<u8>{source.data() + (dstChunk->first - destination.data()), dstChunk->second.size}, [&](std::pair<u8 *, ChunkDescriptor> &desc) __attribute__((always_inline)) {
desc.second.permission = dstChunk->second.permission;
desc.second.attributes.isBorrowed = false;
MapInternal(desc);
});
std::memcpy(source.data() + (dstChunk->first - destination.data()), dstChunk->first, dstChunk->second.size);
}
}
void MemoryManager::AddRef(std::shared_ptr<type::KMemory> ptr) { void MemoryManager::AddRef(std::shared_ptr<type::KMemory> ptr) {
memRefs.push_back(std::move(ptr)); memRefs.push_back(std::move(ptr));
} }

View File

@ -322,6 +322,10 @@ namespace skyline {
*/ */
void FreeMemory(span<u8> memory); void FreeMemory(span<u8> memory);
void SvcMapMemory(span<u8> source, span<u8> destination);
void SvcUnmapMemory(span<u8> source, span<u8> destination);
/** /**
* @brief Adds a reference to shared memory, extending its lifetime until `RemoveRef` is called * @brief Adds a reference to shared memory, extending its lifetime until `RemoveRef` is called
*/ */
@ -346,7 +350,7 @@ namespace skyline {
/** /**
* @return If the supplied region is contained withing the accessible guest address space * @return If the supplied region is contained withing the accessible guest address space
*/ */
bool AddressSpaceContains(span<u8> region) const { constexpr bool AddressSpaceContains(span<u8> region) const {
if (addressSpaceType == memory::AddressSpaceType::AddressSpace36Bit) if (addressSpaceType == memory::AddressSpaceType::AddressSpace36Bit)
return codeBase36Bit.contains(region) || base.contains(region); return codeBase36Bit.contains(region) || base.contains(region);
else else

View File

@ -172,11 +172,7 @@ namespace skyline::kernel::svc {
return; return;
} }
state.process->memory.MapStackMemory(span<u8>{destination, size}); state.process->memory.SvcMapMemory(span<u8>{source, size}, span<u8>{destination, size});
std::memcpy(destination, source, size);
state.process->memory.SetRegionPermission(span<u8>{source, size}, {false, false, false});
state.process->memory.SetRegionBorrowed(span<u8>{source, size}, true);
Logger::Debug("Mapped range 0x{:X} - 0x{:X} to 0x{:X} - 0x{:X} (Size: 0x{:X} bytes)", source, source + size, destination, destination + size, size); Logger::Debug("Mapped range 0x{:X} - 0x{:X} to 0x{:X} - 0x{:X} (Size: 0x{:X} bytes)", source, source + size, destination, destination + size, size);
state.ctx->gpr.w0 = Result{}; state.ctx->gpr.w0 = Result{};
@ -205,18 +201,8 @@ namespace skyline::kernel::svc {
return; return;
} }
auto dstChunk{state.process->memory.GetChunk(destination).value()}; state.process->memory.SvcUnmapMemory(span<u8>{source, size}, span<u8>{destination, size});
while (dstChunk.second.state.value == memory::states::Unmapped)
dstChunk = state.process->memory.GetChunk(dstChunk.first + dstChunk.second.size).value();
if ((destination + size) > dstChunk.first) [[likely]] {
state.process->memory.SetRegionPermission(span<u8>{source + (dstChunk.first - destination), dstChunk.second.size}, dstChunk.second.permission);
state.process->memory.SetRegionBorrowed(span<u8>{source + (dstChunk.first - destination), dstChunk.second.size}, false);
std::memcpy(source + (dstChunk.first - destination), dstChunk.first, dstChunk.second.size);
state.process->memory.UnmapMemory(span<u8>{destination, size}); state.process->memory.UnmapMemory(span<u8>{destination, size});
}
Logger::Debug("Unmapped range 0x{:X} - 0x{:X} to 0x{:X} - 0x{:X} (Size: 0x{:X} bytes)", destination, destination + size, source, source + size, size); Logger::Debug("Unmapped range 0x{:X} - 0x{:X} to 0x{:X} - 0x{:X} (Size: 0x{:X} bytes)", destination, destination + size, source, source + size, size);
state.ctx->gpr.w0 = Result{}; state.ctx->gpr.w0 = Result{};