memory: Rename and implement batch unmap
This commit is contained in:
parent
cb9216d73f
commit
1440741fe9
|
@ -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.
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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");
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue