memory: Rename and implement batch unmap

This commit is contained in:
IndecisiveTurtle 2024-07-25 02:04:46 +03:00
parent cb9216d73f
commit 1440741fe9
4 changed files with 46 additions and 16 deletions

View File

@ -2,6 +2,7 @@
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
#include <bit> #include <bit>
#include "common/assert.h"
#include "common/alignment.h" #include "common/alignment.h"
#include "common/logging/log.h" #include "common/logging/log.h"
#include "common/singleton.h" #include "common/singleton.h"
@ -230,6 +231,8 @@ s32 PS4_SYSV_ABI sceKernelBatchMap(OrbisKernelBatchMapEntry* entries, int numEnt
return sceKernelBatchMap2(entries, numEntries, numEntriesOut, 0x10); // 0x10 : Fixed / 0x410 return sceKernelBatchMap2(entries, numEntries, numEntriesOut, 0x10); // 0x10 : Fixed / 0x410
} }
int PS4_SYSV_ABI sceKernelMunmap(void* addr, size_t len);
s32 PS4_SYSV_ABI sceKernelBatchMap2(OrbisKernelBatchMapEntry* entries, int numEntries, s32 PS4_SYSV_ABI sceKernelBatchMap2(OrbisKernelBatchMapEntry* entries, int numEntries,
int* numEntriesOut, int flags) { int* numEntriesOut, int flags) {
int processed = 0; int processed = 0;
@ -251,10 +254,19 @@ s32 PS4_SYSV_ABI sceKernelBatchMap2(OrbisKernelBatchMapEntry* entries, int numEn
i, entries[i].operation, entries[i].length, entries[i].offset, (u8)entries[i].type, i, entries[i].operation, entries[i].length, entries[i].offset, (u8)entries[i].type,
result); result);
if (result == 0)
processed++;
} else if (entries[i].operation == 1) {
result = sceKernelMunmap(entries[i].start, entries[i].length);
LOG_INFO(
Kernel_Vmm,
"BatchMap: entry = {}, operation = {}, len = {:#x}, result = {}",
i, entries[i].operation, entries[i].length, result);
if (result == 0) if (result == 0)
processed++; processed++;
} else { } else {
LOG_ERROR(Kernel_Vmm, "called: Unimplemented Operation = {}", entries[i].operation); UNREACHABLE_MSG("called: Unimplemented Operation = {}", entries[i].operation);
} }
} }
if (numEntriesOut != NULL) { // can be zero. do not return an error code. if (numEntriesOut != NULL) { // can be zero. do not return an error code.

View File

@ -785,7 +785,21 @@ int PS4_SYSV_ABI posix_pthread_mutex_destroy(ScePthreadMutex* mutex) {
int PS4_SYSV_ABI posix_pthread_cond_wait(ScePthreadCond* cond, ScePthreadMutex* mutex) { int PS4_SYSV_ABI posix_pthread_cond_wait(ScePthreadCond* cond, ScePthreadMutex* mutex) {
int result = scePthreadCondWait(cond, mutex); int result = scePthreadCondWait(cond, mutex);
if (result < 0) { if (result < 0) {
UNREACHABLE(); int rt = result > SCE_KERNEL_ERROR_UNKNOWN && result <= SCE_KERNEL_ERROR_ESTOP
? result + -SCE_KERNEL_ERROR_UNKNOWN
: POSIX_EOTHER;
return rt;
}
return result;
}
int PS4_SYSV_ABI posix_pthread_cond_timedwait(ScePthreadCond* cond, ScePthreadMutex* mutex, u64 usec) {
int result = scePthreadCondTimedwait(cond, mutex, usec);
if (result < 0) {
int rt = result > SCE_KERNEL_ERROR_UNKNOWN && result <= SCE_KERNEL_ERROR_ESTOP
? result + -SCE_KERNEL_ERROR_UNKNOWN
: POSIX_EOTHER;
return rt;
} }
return result; return result;
} }
@ -1462,6 +1476,7 @@ void pthreadSymbolsRegister(Core::Loader::SymbolsResolver* sym) {
LIB_FUNCTION("ltCfaGr2JGE", "libScePosix", 1, "libkernel", 1, 1, posix_pthread_mutex_destroy); LIB_FUNCTION("ltCfaGr2JGE", "libScePosix", 1, "libkernel", 1, 1, posix_pthread_mutex_destroy);
LIB_FUNCTION("Op8TBGY5KHg", "libkernel", 1, "libkernel", 1, 1, posix_pthread_cond_wait); LIB_FUNCTION("Op8TBGY5KHg", "libkernel", 1, "libkernel", 1, 1, posix_pthread_cond_wait);
LIB_FUNCTION("Op8TBGY5KHg", "libScePosix", 1, "libkernel", 1, 1, posix_pthread_cond_wait); LIB_FUNCTION("Op8TBGY5KHg", "libScePosix", 1, "libkernel", 1, 1, posix_pthread_cond_wait);
LIB_FUNCTION("27bAgiJmOh0", "libScePosix", 1, "libkernel", 1, 1, posix_pthread_cond_timedwait);
LIB_FUNCTION("mkx2fVhNMsg", "libScePosix", 1, "libkernel", 1, 1, posix_pthread_cond_broadcast); LIB_FUNCTION("mkx2fVhNMsg", "libScePosix", 1, "libkernel", 1, 1, posix_pthread_cond_broadcast);
LIB_FUNCTION("dQHWEsJtoE4", "libScePosix", 1, "libkernel", 1, 1, posix_pthread_mutexattr_init); LIB_FUNCTION("dQHWEsJtoE4", "libScePosix", 1, "libkernel", 1, 1, posix_pthread_mutexattr_init);
LIB_FUNCTION("mDmgMOGVUqg", "libScePosix", 1, "libkernel", 1, 1, LIB_FUNCTION("mDmgMOGVUqg", "libScePosix", 1, "libkernel", 1, 1,

View File

@ -55,7 +55,7 @@ PAddr MemoryManager::Allocate(PAddr search_start, PAddr search_end, size_t size,
free_addr = alignment > 0 ? Common::AlignUp(free_addr, alignment) : free_addr; free_addr = alignment > 0 ? Common::AlignUp(free_addr, alignment) : free_addr;
// Add the allocated region to the list and commit its pages. // Add the allocated region to the list and commit its pages.
auto& area = AddDmemAllocation(free_addr, size); auto& area = CarveDmemArea(free_addr, size);
area.memory_type = memory_type; area.memory_type = memory_type;
area.is_free = false; area.is_free = false;
return free_addr; return free_addr;
@ -131,7 +131,7 @@ int MemoryManager::Reserve(void** out_addr, VAddr virtual_addr, size_t size, Mem
} }
// Add virtual memory area // Add virtual memory area
const auto new_vma_handle = AddMapping(mapped_addr, size); const auto new_vma_handle = CarveVMA(mapped_addr, size);
auto& new_vma = new_vma_handle->second; auto& new_vma = new_vma_handle->second;
new_vma.disallow_merge = True(flags & MemoryMapFlags::NoCoalesce); new_vma.disallow_merge = True(flags & MemoryMapFlags::NoCoalesce);
new_vma.prot = MemoryProt::NoAccess; new_vma.prot = MemoryProt::NoAccess;
@ -186,7 +186,7 @@ int MemoryManager::MapMemory(void** out_addr, VAddr virtual_addr, size_t size, M
*out_addr = impl.Map(mapped_addr, size, alignment, phys_addr, is_exec); *out_addr = impl.Map(mapped_addr, size, alignment, phys_addr, is_exec);
TRACK_ALLOC(*out_addr, size, "VMEM"); TRACK_ALLOC(*out_addr, size, "VMEM");
auto& new_vma = AddMapping(mapped_addr, size)->second; auto& new_vma = CarveVMA(mapped_addr, size)->second;
new_vma.disallow_merge = True(flags & MemoryMapFlags::NoCoalesce); new_vma.disallow_merge = True(flags & MemoryMapFlags::NoCoalesce);
new_vma.prot = prot; new_vma.prot = prot;
new_vma.name = name; new_vma.name = name;
@ -238,7 +238,7 @@ int MemoryManager::MapFile(void** out_addr, VAddr virtual_addr, size_t size, Mem
impl.MapFile(mapped_addr, size, offset, std::bit_cast<u32>(prot), fd); impl.MapFile(mapped_addr, size, offset, std::bit_cast<u32>(prot), fd);
// Add virtual memory area // Add virtual memory area
auto& new_vma = AddMapping(mapped_addr, size_aligned)->second; auto& new_vma = CarveVMA(mapped_addr, size_aligned)->second;
new_vma.disallow_merge = True(flags & MemoryMapFlags::NoCoalesce); new_vma.disallow_merge = True(flags & MemoryMapFlags::NoCoalesce);
new_vma.prot = prot; new_vma.prot = prot;
new_vma.name = "File"; new_vma.name = "File";
@ -253,9 +253,9 @@ void MemoryManager::UnmapMemory(VAddr virtual_addr, size_t size) {
std::scoped_lock lk{mutex}; std::scoped_lock lk{mutex};
// TODO: Partial unmaps are technically supported by the guest. // TODO: Partial unmaps are technically supported by the guest.
const auto it = vma_map.find(virtual_addr); const auto it = FindVMA(virtual_addr);
ASSERT_MSG(it != vma_map.end() && it->first == virtual_addr, ASSERT_MSG(it->second.Contains(virtual_addr, size),
"Attempting to unmap partially mapped range"); "Existing mapping does not contain requested unmap range");
const auto type = it->second.type; const auto type = it->second.type;
const bool has_backing = type == VMAType::Direct || type == VMAType::File; const bool has_backing = type == VMAType::Direct || type == VMAType::File;
@ -267,11 +267,12 @@ void MemoryManager::UnmapMemory(VAddr virtual_addr, size_t size) {
} }
// Mark region as free and attempt to coalesce it with neighbours. // Mark region as free and attempt to coalesce it with neighbours.
auto& vma = it->second; const auto new_it = CarveVMA(virtual_addr, size, true);
auto& vma = new_it->second;
vma.type = VMAType::Free; vma.type = VMAType::Free;
vma.prot = MemoryProt::NoAccess; vma.prot = MemoryProt::NoAccess;
vma.phys_base = 0; vma.phys_base = 0;
MergeAdjacent(vma_map, it); MergeAdjacent(vma_map, new_it);
// Unmap the memory region. // Unmap the memory region.
impl.Unmap(virtual_addr, size, has_backing); impl.Unmap(virtual_addr, size, has_backing);
@ -374,12 +375,13 @@ std::pair<vk::Buffer, size_t> MemoryManager::GetVulkanBuffer(VAddr addr) {
return std::make_pair(*it->second.buffer, addr - it->first); return std::make_pair(*it->second.buffer, addr - it->first);
} }
MemoryManager::VMAHandle MemoryManager::AddMapping(VAddr virtual_addr, size_t size) { MemoryManager::VMAHandle MemoryManager::CarveVMA(VAddr virtual_addr, size_t size,
bool allow_mapped) {
auto vma_handle = FindVMA(virtual_addr); auto vma_handle = FindVMA(virtual_addr);
ASSERT_MSG(vma_handle != vma_map.end(), "Virtual address not in vm_map"); ASSERT_MSG(vma_handle != vma_map.end(), "Virtual address not in vm_map");
const VirtualMemoryArea& vma = vma_handle->second; const VirtualMemoryArea& vma = vma_handle->second;
ASSERT_MSG((vma.type == VMAType::Free || vma.type == VMAType::Reserved) && ASSERT_MSG((vma.type == VMAType::Free || vma.type == VMAType::Reserved || allow_mapped) &&
vma.base <= virtual_addr, vma.base <= virtual_addr,
"Adding a mapping to already mapped region"); "Adding a mapping to already mapped region");
@ -399,7 +401,7 @@ MemoryManager::VMAHandle MemoryManager::AddMapping(VAddr virtual_addr, size_t si
return vma_handle; return vma_handle;
} }
DirectMemoryArea& MemoryManager::AddDmemAllocation(PAddr addr, size_t size) { DirectMemoryArea& MemoryManager::CarveDmemArea(PAddr addr, size_t size) {
auto dmem_handle = FindDmemArea(addr); auto dmem_handle = FindDmemArea(addr);
ASSERT_MSG(dmem_handle != dmem_map.end(), "Physical address not in dmem_map"); ASSERT_MSG(dmem_handle != dmem_map.end(), "Physical address not in dmem_map");

View File

@ -202,9 +202,10 @@ private:
return iter; return iter;
} }
VMAHandle AddMapping(VAddr virtual_addr, size_t size); VMAHandle CarveVMA(VAddr virtual_addr, size_t size,
bool allow_mapped = false);
DirectMemoryArea& AddDmemAllocation(PAddr addr, size_t size); DirectMemoryArea& CarveDmemArea(PAddr addr, size_t size);
VMAHandle Split(VMAHandle vma_handle, size_t offset_in_vma); VMAHandle Split(VMAHandle vma_handle, size_t offset_in_vma);