Add sceKernelGetDirectMemoryType and update sceKernelReserveVirtualRange to search for free region when virtual_addr==0

This commit is contained in:
Borchev 2024-07-21 11:29:24 -07:00
parent 36d528743a
commit f556f85279
5 changed files with 52 additions and 2 deletions

View File

@ -375,6 +375,7 @@ void LibKernel_Register(Core::Loader::SymbolsResolver* sym) {
sceKernelCheckedReleaseDirectMemory);
LIB_FUNCTION("rVjRvHJ0X6c", "libkernel", 1, "libkernel", 1, 1, sceKernelVirtualQuery);
LIB_FUNCTION("7oxv3PPCumo", "libkernel", 1, "libkernel", 1, 1, sceKernelReserveVirtualRange);
LIB_FUNCTION("BC+OG5m9+bw", "libkernel", 1, "libkernel", 1, 1, sceKernelGetDirectMemoryType);
LIB_FUNCTION("pO96TwzOm5E", "libkernel", 1, "libkernel", 1, 1, sceKernelGetDirectMemorySize);
LIB_FUNCTION("NcaWUxfMNIQ", "libkernel", 1, "libkernel", 1, 1, sceKernelMapNamedDirectMemory);
LIB_FUNCTION("L-Q3LEjIbgA", "libkernel", 1, "libkernel", 1, 1, sceKernelMapDirectMemory);

View File

@ -211,4 +211,12 @@ void PS4_SYSV_ABI _sceKernelRtldSetApplicationHeapAPI(void* func) {
linker->SetHeapApiFunc(func);
}
int PS4_SYSV_ABI sceKernelGetDirectMemoryType(u64 addr, int* directMemoryTypeOut,
void** directMemoryStartOut,
void** directMemoryEndOut) {
LOG_WARNING(Kernel_Vmm, "called, direct memory addr = {:#x}", addr);
auto* memory = Core::Memory::Instance();
return memory->GetDirectMemoryType(addr, directMemoryTypeOut, directMemoryStartOut, directMemoryEndOut);
}
} // namespace Libraries::Kernel

View File

@ -81,5 +81,8 @@ int PS4_SYSV_ABI sceKernelDirectMemoryQuery(u64 offset, int flags, OrbisQueryInf
size_t infoSize);
s32 PS4_SYSV_ABI sceKernelAvailableFlexibleMemorySize(size_t* sizeOut);
void PS4_SYSV_ABI _sceKernelRtldSetApplicationHeapAPI(void* func);
int PS4_SYSV_ABI sceKernelGetDirectMemoryType(u64 addr, int* directMemoryTypeOut,
void** directMemoryStartOut,
void** directMemoryEndOut);
} // namespace Libraries::Kernel

View File

@ -87,10 +87,27 @@ int MemoryManager::Reserve(void** out_addr, VAddr virtual_addr, size_t size, Mem
u64 alignment) {
std::scoped_lock lk{mutex};
ASSERT_MSG(virtual_addr != 0, "TODO: Reserve address is zero - search for free space");
virtual_addr = (virtual_addr == 0) ? impl.VirtualBase() : virtual_addr;
alignment = alignment > 0 ? alignment : 16_KB;
VAddr mapped_addr = alignment > 0 ? Common::AlignUp(virtual_addr, alignment) : virtual_addr;
// Find the first free area starting with provided virtual address.
if (False(flags & MemoryMapFlags::Fixed)) {
auto it = FindVMA(mapped_addr);
// If the VMA is free and contains the requested mapping we are done.
if (it->second.type == VMAType::Free && it->second.Contains(virtual_addr, size)) {
mapped_addr = virtual_addr;
} else {
// Search for the first free VMA that fits our mapping.
while (it->second.type != VMAType::Free || it->second.size < size) {
it++;
}
ASSERT(it != vma_map.end());
const auto& vma = it->second;
mapped_addr = alignment > 0 ? Common::AlignUp(vma.base, alignment) : vma.base;
}
}
// Add virtual memory area
auto& new_vma = AddMapping(mapped_addr, size);
new_vma.disallow_merge = True(flags & MemoryMapFlags::NoCoalesce);
@ -489,4 +506,22 @@ void MemoryManager::UnmapVulkanMemory(VAddr addr, size_t size) {
mapped_memories.erase(it);
}
int MemoryManager::GetDirectMemoryType(PAddr addr, int* directMemoryTypeOut, void** directMemoryStartOut,
void** directMemoryEndOut) {
std::scoped_lock lk{mutex};
auto dmem_area = FindDmemArea(addr);
if (dmem_area == dmem_map.end() || dmem_area->second.is_free) {
LOG_ERROR(Core, "Unable to find allocated direct memory region to check type!");
return ORBIS_KERNEL_ERROR_ENOENT;
}
const auto& area = dmem_area->second;
*directMemoryStartOut = reinterpret_cast<void*>(area.base);
*directMemoryEndOut = reinterpret_cast<void*>(area.GetEnd());
*directMemoryTypeOut = area.memory_type;
return ORBIS_OK;
}
} // namespace Core

View File

@ -160,6 +160,9 @@ public:
std::pair<vk::Buffer, size_t> GetVulkanBuffer(VAddr addr);
int GetDirectMemoryType(PAddr addr, int* directMemoryTypeOut, void** directMemoryStartOut,
void** directMemoryEndOut);
private:
VMAHandle FindVMA(VAddr target) {
return std::prev(vma_map.upper_bound(target));