mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2025-05-24 12:25:00 +00:00
core: Implement new memory manager (#133)
* core: Implement new memory manager * ci: Attempt to fix linux build * code: Fix a few build errors
This commit is contained in:
parent
67f6d8b2e4
commit
55855b4195
22 changed files with 792 additions and 239 deletions
|
@ -11,12 +11,12 @@
|
|||
#include "core/libraries/kernel/event_queues.h"
|
||||
#include "core/libraries/kernel/file_system.h"
|
||||
#include "core/libraries/kernel/libkernel.h"
|
||||
#include "core/libraries/kernel/memory/kernel_memory.h"
|
||||
#include "core/libraries/kernel/memory_management.h"
|
||||
#include "core/libraries/kernel/thread_management.h"
|
||||
#include "core/libraries/kernel/time_management.h"
|
||||
#include "core/libraries/libs.h"
|
||||
#include "core/linker.h"
|
||||
#include "core/memory.h"
|
||||
#ifdef _WIN64
|
||||
#include <io.h>
|
||||
#include <windows.h>
|
||||
|
@ -43,7 +43,9 @@ static PS4_SYSV_ABI void stack_chk_fail() {
|
|||
}
|
||||
|
||||
int PS4_SYSV_ABI sceKernelMunmap(void* addr, size_t len) {
|
||||
LOG_ERROR(Kernel_Vmm, "(DUMMY) called");
|
||||
LOG_INFO(Kernel_Vmm, "addr = {}, len = {:#x}", fmt::ptr(addr), len);
|
||||
auto* memory = Core::Memory::Instance();
|
||||
memory->UnmapMemory(std::bit_cast<VAddr>(addr), len);
|
||||
return SCE_OK;
|
||||
}
|
||||
|
||||
|
@ -188,6 +190,8 @@ void LibKernel_Register(Core::Loader::SymbolsResolver* sym) {
|
|||
LIB_FUNCTION("L-Q3LEjIbgA", "libkernel", 1, "libkernel", 1, 1, sceKernelMapDirectMemory);
|
||||
LIB_FUNCTION("MBuItvba6z8", "libkernel", 1, "libkernel", 1, 1, sceKernelReleaseDirectMemory);
|
||||
LIB_FUNCTION("cQke9UuBQOk", "libkernel", 1, "libkernel", 1, 1, sceKernelMunmap);
|
||||
LIB_FUNCTION("mL8NDH86iQI", "libkernel", 1, "libkernel", 1, 1, sceKernelMapNamedFlexibleMemory);
|
||||
LIB_FUNCTION("IWIBBdTHit4", "libkernel", 1, "libkernel", 1, 1, sceKernelMapFlexibleMemory);
|
||||
// equeue
|
||||
LIB_FUNCTION("D0OdFMjp46I", "libkernel", 1, "libkernel", 1, 1, sceKernelCreateEqueue);
|
||||
LIB_FUNCTION("jpFjmgAC5AE", "libkernel", 1, "libkernel", 1, 1, sceKernelDeleteEqueue);
|
||||
|
@ -205,7 +209,6 @@ void LibKernel_Register(Core::Loader::SymbolsResolver* sym) {
|
|||
Libraries::Kernel::fileSystemSymbolsRegister(sym);
|
||||
Libraries::Kernel::timeSymbolsRegister(sym);
|
||||
Libraries::Kernel::pthreadSymbolsRegister(sym);
|
||||
Libraries::Kernel::RegisterKernelMemory(sym);
|
||||
|
||||
// temp
|
||||
LIB_FUNCTION("NWtTN10cJzE", "libSceLibcInternalExt", 1, "libSceLibcInternal", 1, 1,
|
||||
|
|
|
@ -1,22 +0,0 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "flexible_memory.h"
|
||||
|
||||
namespace Libraries::Kernel {
|
||||
bool FlexibleMemory::Map(u64 virtual_addr, std::size_t len, int prot,
|
||||
VirtualMemory::MemoryMode cpu_mode) {
|
||||
std::scoped_lock lock{mutex};
|
||||
|
||||
AllocatedBlock block{};
|
||||
block.map_virtual_addr = virtual_addr;
|
||||
block.map_size = len;
|
||||
block.prot = prot;
|
||||
block.cpu_mode = cpu_mode;
|
||||
|
||||
allocated_blocks.push_back(block);
|
||||
allocated_total += len;
|
||||
|
||||
return true;
|
||||
}
|
||||
} // namespace Libraries::Kernel
|
|
@ -1,33 +0,0 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <mutex>
|
||||
#include <vector>
|
||||
#include "common/types.h"
|
||||
#include "core/virtual_memory.h"
|
||||
|
||||
namespace Libraries::Kernel {
|
||||
|
||||
class FlexibleMemory {
|
||||
public:
|
||||
struct AllocatedBlock {
|
||||
u64 map_virtual_addr;
|
||||
u64 map_size;
|
||||
int prot;
|
||||
VirtualMemory::MemoryMode cpu_mode;
|
||||
};
|
||||
|
||||
FlexibleMemory(){};
|
||||
virtual ~FlexibleMemory(){};
|
||||
|
||||
public:
|
||||
bool Map(u64 virtual_addr, std::size_t len, int prot, VirtualMemory::MemoryMode cpu_mode);
|
||||
|
||||
private:
|
||||
std::vector<AllocatedBlock> allocated_blocks;
|
||||
u64 allocated_total = 0;
|
||||
std::mutex mutex;
|
||||
};
|
||||
} // namespace Libraries::Kernel
|
|
@ -1,78 +0,0 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include <common/assert.h>
|
||||
#include <common/singleton.h>
|
||||
#include <core/libraries/error_codes.h>
|
||||
#include <core/libraries/libs.h>
|
||||
#include <core/virtual_memory.h>
|
||||
#include "flexible_memory.h"
|
||||
#include "kernel_memory.h"
|
||||
|
||||
namespace Libraries::Kernel {
|
||||
|
||||
bool Is16KBMultiple(u64 n) {
|
||||
return ((n % (16ull * 1024) == 0));
|
||||
}
|
||||
s32 PS4_SYSV_ABI sceKernelMapNamedFlexibleMemory(void** addr_in_out, std::size_t len, int prot,
|
||||
int flags, const char* name) {
|
||||
|
||||
LOG_INFO(Kernel_Vmm, "len = {:#x}, prot = {:#x}, flags = {:#x}, name = {}", len, prot, flags,
|
||||
name);
|
||||
|
||||
if (len == 0 || !Is16KBMultiple(len)) {
|
||||
LOG_ERROR(Kernel_Vmm, "len is 0 or not 16kb multiple");
|
||||
return ORBIS_KERNEL_ERROR_EINVAL;
|
||||
}
|
||||
|
||||
static constexpr size_t MaxNameSize = 32;
|
||||
if (std::strlen(name) > MaxNameSize) {
|
||||
LOG_ERROR(Kernel_Vmm, "name exceeds 32 bytes!");
|
||||
return ORBIS_KERNEL_ERROR_ENAMETOOLONG;
|
||||
}
|
||||
|
||||
if (name == nullptr) {
|
||||
LOG_ERROR(Kernel_Vmm, "name is invalid!");
|
||||
return ORBIS_KERNEL_ERROR_EFAULT;
|
||||
}
|
||||
|
||||
VirtualMemory::MemoryMode cpu_mode = VirtualMemory::MemoryMode::NoAccess;
|
||||
|
||||
switch (prot) {
|
||||
case 0x3:
|
||||
cpu_mode = VirtualMemory::MemoryMode::ReadWrite;
|
||||
break;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
auto in_addr = reinterpret_cast<u64>(*addr_in_out);
|
||||
auto out_addr = VirtualMemory::memory_alloc(in_addr, len, cpu_mode);
|
||||
*addr_in_out = reinterpret_cast<void*>(out_addr);
|
||||
|
||||
auto* flexible_memory = Common::Singleton<FlexibleMemory>::Instance();
|
||||
|
||||
if (!flexible_memory->Map(out_addr, len, prot, cpu_mode)) {
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
if (out_addr == 0) {
|
||||
LOG_ERROR(Kernel_Vmm, "Can't allocate address");
|
||||
return ORBIS_KERNEL_ERROR_ENOMEM;
|
||||
}
|
||||
LOG_INFO(Kernel_Vmm, "in_addr = {:#x} out_addr = {:#x}", in_addr, out_addr);
|
||||
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceKernelMapFlexibleMemory(void** addr_in_out, std::size_t len, int prot,
|
||||
int flags) {
|
||||
return sceKernelMapNamedFlexibleMemory(addr_in_out, len, prot, flags, "");
|
||||
}
|
||||
|
||||
void RegisterKernelMemory(Core::Loader::SymbolsResolver* sym) {
|
||||
LIB_FUNCTION("mL8NDH86iQI", "libkernel", 1, "libkernel", 1, 1, sceKernelMapNamedFlexibleMemory);
|
||||
LIB_FUNCTION("IWIBBdTHit4", "libkernel", 1, "libkernel", 1, 1, sceKernelMapFlexibleMemory);
|
||||
}
|
||||
|
||||
} // namespace Libraries::Kernel
|
|
@ -1,18 +0,0 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "common/types.h"
|
||||
|
||||
namespace Core::Loader {
|
||||
class SymbolsResolver;
|
||||
}
|
||||
|
||||
namespace Libraries::Kernel {
|
||||
s32 PS4_SYSV_ABI sceKernelMapNamedFlexibleMemory(void** addrInOut, std::size_t len, int prot,
|
||||
int flags, const char* name);
|
||||
s32 PS4_SYSV_ABI sceKernelMapFlexibleMemory(void** addr_in_out, std::size_t len, int prot,
|
||||
int flags);
|
||||
void RegisterKernelMemory(Core::Loader::SymbolsResolver* sym);
|
||||
} // namespace Libraries::Kernel
|
|
@ -3,13 +3,11 @@
|
|||
|
||||
#include <bit>
|
||||
#include "common/alignment.h"
|
||||
#include "common/assert.h"
|
||||
#include "common/logging/log.h"
|
||||
#include "common/singleton.h"
|
||||
#include "core/libraries/error_codes.h"
|
||||
#include "core/libraries/kernel/memory_management.h"
|
||||
#include "core/libraries/kernel/physical_memory.h"
|
||||
#include "core/virtual_memory.h"
|
||||
#include "core/memory.h"
|
||||
|
||||
namespace Libraries::Kernel {
|
||||
|
||||
|
@ -43,15 +41,10 @@ int PS4_SYSV_ABI sceKernelAllocateDirectMemory(s64 searchStart, s64 searchEnd, u
|
|||
return SCE_KERNEL_ERROR_EINVAL;
|
||||
}
|
||||
|
||||
u64 physical_addr = 0;
|
||||
auto* physical_memory = Common::Singleton<PhysicalMemory>::Instance();
|
||||
if (!physical_memory->Alloc(searchStart, searchEnd, len, alignment, &physical_addr,
|
||||
memoryType)) {
|
||||
LOG_CRITICAL(Kernel_Vmm, "Unable to allocate physical memory");
|
||||
return SCE_KERNEL_ERROR_EAGAIN;
|
||||
}
|
||||
*physAddrOut = static_cast<s64>(physical_addr);
|
||||
LOG_INFO(Kernel_Vmm, "physAddrOut = {:#x}", physical_addr);
|
||||
auto* memory = Core::Memory::Instance();
|
||||
PAddr phys_addr = memory->Allocate(searchStart, searchEnd, len, alignment, memoryType);
|
||||
*physAddrOut = static_cast<s64>(phys_addr);
|
||||
LOG_INFO(Kernel_Vmm, "physAddrOut = {:#x}", phys_addr);
|
||||
return SCE_OK;
|
||||
}
|
||||
|
||||
|
@ -77,40 +70,48 @@ int PS4_SYSV_ABI sceKernelMapDirectMemory(void** addr, u64 len, int prot, int fl
|
|||
}
|
||||
}
|
||||
|
||||
VirtualMemory::MemoryMode cpu_mode = VirtualMemory::MemoryMode::NoAccess;
|
||||
const VAddr in_addr = reinterpret_cast<VAddr>(*addr);
|
||||
const auto mem_prot = static_cast<Core::MemoryProt>(prot);
|
||||
const auto map_flags = static_cast<Core::MemoryMapFlags>(flags);
|
||||
auto* memory = Core::Memory::Instance();
|
||||
return memory->MapMemory(addr, in_addr, len, mem_prot, map_flags, Core::VMAType::Direct, "",
|
||||
directMemoryStart, alignment);
|
||||
}
|
||||
|
||||
switch (prot) {
|
||||
case 0x03:
|
||||
cpu_mode = VirtualMemory::MemoryMode::ReadWrite;
|
||||
break;
|
||||
case 0x32:
|
||||
case 0x33: // SCE_KERNEL_PROT_CPU_READ|SCE_KERNEL_PROT_CPU_WRITE|SCE_KERNEL_PROT_GPU_READ|SCE_KERNEL_PROT_GPU_ALL
|
||||
cpu_mode = VirtualMemory::MemoryMode::ReadWrite;
|
||||
break;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
s32 PS4_SYSV_ABI sceKernelMapNamedFlexibleMemory(void** addr_in_out, std::size_t len, int prot,
|
||||
int flags, const char* name) {
|
||||
|
||||
if (len == 0 || !Common::is16KBAligned(len)) {
|
||||
LOG_ERROR(Kernel_Vmm, "len is 0 or not 16kb multiple");
|
||||
return ORBIS_KERNEL_ERROR_EINVAL;
|
||||
}
|
||||
|
||||
auto in_addr = reinterpret_cast<u64>(*addr);
|
||||
u64 out_addr = 0;
|
||||
|
||||
if (flags == 0) {
|
||||
out_addr = VirtualMemory::memory_alloc_aligned(in_addr, len, cpu_mode, alignment);
|
||||
}
|
||||
LOG_INFO(Kernel_Vmm, "in_addr = {:#x}, out_addr = {:#x}", in_addr, out_addr);
|
||||
|
||||
*addr = reinterpret_cast<void*>(out_addr); // return out_addr to first functions parameter
|
||||
|
||||
if (out_addr == 0) {
|
||||
return SCE_KERNEL_ERROR_ENOMEM;
|
||||
static constexpr size_t MaxNameSize = 32;
|
||||
if (std::strlen(name) > MaxNameSize) {
|
||||
LOG_ERROR(Kernel_Vmm, "name exceeds 32 bytes!");
|
||||
return ORBIS_KERNEL_ERROR_ENAMETOOLONG;
|
||||
}
|
||||
|
||||
auto* physical_memory = Common::Singleton<PhysicalMemory>::Instance();
|
||||
if (!physical_memory->Map(out_addr, directMemoryStart, len, prot, cpu_mode)) {
|
||||
UNREACHABLE();
|
||||
if (name == nullptr) {
|
||||
LOG_ERROR(Kernel_Vmm, "name is invalid!");
|
||||
return ORBIS_KERNEL_ERROR_EFAULT;
|
||||
}
|
||||
|
||||
return SCE_OK;
|
||||
const VAddr in_addr = reinterpret_cast<VAddr>(*addr_in_out);
|
||||
const auto mem_prot = static_cast<Core::MemoryProt>(prot);
|
||||
const auto map_flags = static_cast<Core::MemoryMapFlags>(flags);
|
||||
auto* memory = Core::Memory::Instance();
|
||||
const int ret = memory->MapMemory(addr_in_out, in_addr, len, mem_prot, map_flags,
|
||||
Core::VMAType::Flexible, name);
|
||||
|
||||
LOG_INFO(Kernel_Vmm, "addr = {}, len = {:#x}, prot = {:#x}, flags = {:#x}",
|
||||
fmt::ptr(*addr_in_out), len, prot, flags);
|
||||
return ret;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceKernelMapFlexibleMemory(void** addr_in_out, std::size_t len, int prot,
|
||||
int flags) {
|
||||
return sceKernelMapNamedFlexibleMemory(addr_in_out, len, prot, flags, "");
|
||||
}
|
||||
|
||||
} // namespace Libraries::Kernel
|
||||
|
|
|
@ -35,5 +35,9 @@ int PS4_SYSV_ABI sceKernelAllocateDirectMemory(s64 searchStart, s64 searchEnd, u
|
|||
u64 alignment, int memoryType, s64* physAddrOut);
|
||||
int PS4_SYSV_ABI sceKernelMapDirectMemory(void** addr, u64 len, int prot, int flags,
|
||||
s64 directMemoryStart, u64 alignment);
|
||||
s32 PS4_SYSV_ABI sceKernelMapNamedFlexibleMemory(void** addrInOut, std::size_t len, int prot,
|
||||
int flags, const char* name);
|
||||
s32 PS4_SYSV_ABI sceKernelMapFlexibleMemory(void** addr_in_out, std::size_t len, int prot,
|
||||
int flags);
|
||||
|
||||
} // namespace Libraries::Kernel
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue