implemented sceKernelMapDirectMemory

This commit is contained in:
georgemoralis 2023-08-08 22:24:17 +03:00
parent c412a5cb0b
commit 25e1095c7e
7 changed files with 101 additions and 5 deletions

View File

@ -41,7 +41,7 @@ add_executable(shadps4
src/Core/PS4/HLE/Kernel/Objects/physical_memory.cpp src/Core/PS4/HLE/Kernel/Objects/physical_memory.cpp
src/Util/string_util.cpp src/Util/string_util.cpp
src/Util/string_util.cpp src/Util/string_util.cpp
"src/Util/Singleton.h" "src/Util/Disassembler.cpp" "src/Util/Disassembler.h" "src/Core/PS4/Util/aerolib.h" "src/Core/PS4/Loader/SymbolsResolver.h" "src/Core/PS4/Loader/SymbolsResolver.cpp" "src/Core/PS4/HLE/Libs.cpp" "src/Core/PS4/HLE/Libs.h" "src/Core/PS4/HLE/LibC.cpp" "src/Core/PS4/HLE/LibC.h" "src/Lib/Timer.cpp" "src/Lib/Timer.h" "src/Core/PS4/HLE/LibKernel.cpp" "src/Core/PS4/HLE/LibKernel.h" "src/Core/PS4/HLE/LibSceVideoOut.cpp" "src/Core/PS4/HLE/LibSceVideoOut.h" "src/Core/PS4/HLE/LibSceGnmDriver.cpp" "src/Core/PS4/HLE/LibSceGnmDriver.h" "src/Core/PS4/HLE/Kernel/ThreadManagement.cpp" "src/Core/PS4/HLE/Kernel/ThreadManagement.h" "src/Core/PS4/HLE/ErrorCodes.h" "src/debug.h" "src/Core/PS4/HLE/Kernel/memory_management.cpp" "src/Core/PS4/HLE/Kernel/memory_management.h") "src/Util/Singleton.h" "src/Util/Disassembler.cpp" "src/Util/Disassembler.h" "src/Core/PS4/Util/aerolib.h" "src/Core/PS4/Loader/SymbolsResolver.h" "src/Core/PS4/Loader/SymbolsResolver.cpp" "src/Core/PS4/HLE/Libs.cpp" "src/Core/PS4/HLE/Libs.h" "src/Core/PS4/HLE/LibC.cpp" "src/Core/PS4/HLE/LibC.h" "src/Lib/Timer.cpp" "src/Lib/Timer.h" "src/Core/PS4/HLE/LibKernel.cpp" "src/Core/PS4/HLE/LibKernel.h" "src/Core/PS4/HLE/LibSceVideoOut.cpp" "src/Core/PS4/HLE/LibSceVideoOut.h" "src/Core/PS4/HLE/LibSceGnmDriver.cpp" "src/Core/PS4/HLE/LibSceGnmDriver.h" "src/Core/PS4/HLE/Kernel/ThreadManagement.cpp" "src/Core/PS4/HLE/Kernel/ThreadManagement.h" "src/Core/PS4/HLE/ErrorCodes.h" "src/debug.h" "src/Core/PS4/HLE/Kernel/memory_management.cpp" "src/Core/PS4/HLE/Kernel/memory_management.h" "src/Core/PS4/GPU/gpu_memory.cpp" "src/Core/PS4/GPU/gpu_memory.h")
find_package(OpenGL REQUIRED) find_package(OpenGL REQUIRED)
target_link_libraries(shadps4 PUBLIC fmt mincore spdlog IMGUI SDL3-shared ${OPENGL_LIBRARY}) target_link_libraries(shadps4 PUBLIC fmt mincore spdlog IMGUI SDL3-shared ${OPENGL_LIBRARY})

View File

@ -0,0 +1,5 @@
#include "gpu_memory.h"
namespace GPU {
void GpuMemorySetAllocArea(u64 virtual_addr, u64 size) {}
} // namespace GPU

View File

@ -0,0 +1,9 @@
#pragma once
#include <types.h>
namespace GPU {
enum class GPUMemoryMode : u32 { NoAccess = 0, Read = 1, Write = 2, ReadWrite = 3 };
void GpuMemorySetAllocArea(u64 virtual_addr, u64 size);
}

View File

@ -24,6 +24,11 @@ bool PhysicalMemory::Alloc(u64 searchStart, u64 searchEnd, u64 len, u64 alignmen
block.size = len; block.size = len;
block.start_addr = find_free_pos; block.start_addr = find_free_pos;
block.memoryType = memoryType; block.memoryType = memoryType;
block.gpu_mode = GPU::GPUMemoryMode::NoAccess;
block.map_size = 0;
block.map_virtual_addr = 0;
block.prot = 0;
block.cpu_mode = VirtualMemory::MemoryMode::NoAccess;
m_allocatedBlocks.push_back(block); m_allocatedBlocks.push_back(block);
@ -33,4 +38,23 @@ bool PhysicalMemory::Alloc(u64 searchStart, u64 searchEnd, u64 len, u64 alignmen
return false; return false;
} }
bool PhysicalMemory::Map(u64 virtual_addr, u64 phys_addr, u64 len, int prot, VirtualMemory::MemoryMode cpu_mode, GPU::GPUMemoryMode gpu_mode) {
for (auto& b : m_allocatedBlocks) {
if (phys_addr >= b.start_addr && phys_addr < b.start_addr + b.size) {
if (b.map_virtual_addr != 0 || b.map_size != 0) {
return false;
}
b.map_virtual_addr = virtual_addr;
b.map_size = len;
b.prot = prot;
b.cpu_mode = cpu_mode;
b.gpu_mode = gpu_mode;
return true;
}
}
return false;
}
} // namespace HLE::Kernel::Objects } // namespace HLE::Kernel::Objects

View File

@ -1,6 +1,7 @@
#pragma once #pragma once
#include <types.h> #include <types.h>
#include <Core/virtual_memory.h>
#include <Core/PS4/GPU/gpu_memory.h>
#include <vector> #include <vector>
namespace HLE::Kernel::Objects { namespace HLE::Kernel::Objects {
@ -11,12 +12,18 @@ class PhysicalMemory {
u64 start_addr; u64 start_addr;
u64 size; u64 size;
int memoryType; int memoryType;
u64 map_virtual_addr;
u64 map_size;
int prot;
VirtualMemory::MemoryMode cpu_mode;
GPU::GPUMemoryMode gpu_mode;
}; };
PhysicalMemory() {} PhysicalMemory() {}
virtual ~PhysicalMemory() {} virtual ~PhysicalMemory() {}
public: public:
bool Alloc(u64 searchStart, u64 searchEnd, u64 len, u64 alignment, u64* physAddrOut, int memoryType); bool Alloc(u64 searchStart, u64 searchEnd, u64 len, u64 alignment, u64* physAddrOut, int memoryType);
bool Map(u64 virtual_addr, u64 phys_addr, u64 len, int prot, VirtualMemory::MemoryMode cpu_mode, GPU::GPUMemoryMode gpu_mode);
private: private:
std::vector<AllocatedBlock> m_allocatedBlocks; std::vector<AllocatedBlock> m_allocatedBlocks;

View File

@ -1,5 +1,7 @@
#include "memory_management.h" #include "memory_management.h"
#include <Core/PS4/GPU/gpu_memory.h>
#include <Core/virtual_memory.h>
#include <debug.h> #include <debug.h>
#include <bit> #include <bit>
@ -65,14 +67,63 @@ int PS4_SYSV_ABI sceKernelAllocateDirectMemory(s64 searchStart, s64 searchEnd, u
int PS4_SYSV_ABI sceKernelMapDirectMemory(void** addr, u64 len, int prot, int flags, s64 directMemoryStart, u64 alignment) { int PS4_SYSV_ABI sceKernelMapDirectMemory(void** addr, u64 len, int prot, int flags, s64 directMemoryStart, u64 alignment) {
PRINT_FUNCTION_NAME(); PRINT_FUNCTION_NAME();
if (len == 0 || !is16KBAligned(len))
{
LOG_TRACE_IF(log_file_memory, "sceKernelMapDirectMemory returned SCE_KERNEL_ERROR_EINVAL len invalid\n");
return SCE_KERNEL_ERROR_EINVAL;
}
if (!is16KBAligned(directMemoryStart))
{
LOG_TRACE_IF(log_file_memory, "sceKernelMapDirectMemory returned SCE_KERNEL_ERROR_EINVAL directMemoryStart invalid\n");
return SCE_KERNEL_ERROR_EINVAL;
}
if (alignment != 0 || (!isPowerOfTwo(alignment) && !is16KBAligned(alignment)))
{
LOG_TRACE_IF(log_file_memory, "sceKernelMapDirectMemory returned SCE_KERNEL_ERROR_EINVAL alignment invalid\n");
return SCE_KERNEL_ERROR_EINVAL;
}
auto* physical_memory = Singleton<HLE::Kernel::Objects::PhysicalMemory>::Instance(); auto* physical_memory = Singleton<HLE::Kernel::Objects::PhysicalMemory>::Instance();
LOG_INFO_IF(log_file_memory, "len = {}\n", log_hex_full(len)); LOG_INFO_IF(log_file_memory, "len = {}\n", log_hex_full(len));
LOG_INFO_IF(log_file_memory, "prot = {}\n", log_hex_full(prot)); LOG_INFO_IF(log_file_memory, "prot = {}\n", log_hex_full(prot));
LOG_INFO_IF(log_file_memory, "flags = {}\n", log_hex_full(flags)); LOG_INFO_IF(log_file_memory, "flags = {}\n", log_hex_full(flags));
LOG_INFO_IF(log_file_memory, "directMemoryStart = {}\n", log_hex_full(directMemoryStart)); LOG_INFO_IF(log_file_memory, "directMemoryStart = {}\n", log_hex_full(directMemoryStart));
LOG_INFO_IF(log_file_memory, "alignment = {}\n", log_hex_full(alignment)); LOG_INFO_IF(log_file_memory, "alignment = {}\n", log_hex_full(alignment));
VirtualMemory::MemoryMode cpu_mode = VirtualMemory::MemoryMode::NoAccess;
GPU::GPUMemoryMode gpu_mode = GPU::GPUMemoryMode::NoAccess;
switch (prot) {
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;
gpu_mode = GPU::GPUMemoryMode::ReadWrite;
break;
default: BREAKPOINT();
}
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_IF(log_file_memory, "in_addr = {}\n", log_hex_full(in_addr));
LOG_INFO_IF(log_file_memory, "out_addr = {}\n", log_hex_full(out_addr));
*addr = reinterpret_cast<void*>(out_addr); // return out_addr to first functions parameter
if (out_addr == 0) {
return SCE_KERNEL_ERROR_ENOMEM;
}
if (!physical_memory->Map(out_addr, directMemoryStart, len, prot, cpu_mode, gpu_mode)) {
BREAKPOINT(); BREAKPOINT();
}
if (gpu_mode != GPU::GPUMemoryMode::NoAccess) {
GPU::GpuMemorySetAllocArea(out_addr, len);
}
return SCE_OK; return SCE_OK;
} }

View File

@ -6,6 +6,8 @@
constexpr u64 SCE_KERNEL_MAIN_DMEM_SIZE = 5376_MB; // ~ 6GB constexpr u64 SCE_KERNEL_MAIN_DMEM_SIZE = 5376_MB; // ~ 6GB
namespace HLE::Libs::LibKernel::MemoryManagement {
// memory types // memory types
enum MemoryTypes : u32 { enum MemoryTypes : u32 {
@ -15,7 +17,6 @@ enum MemoryTypes : u32 {
}; };
enum MemoryFlags : u32 { enum MemoryFlags : u32 {
NOT_SPECIFIED = 0, // not in SCE but it is a possible value (aligned memory)
SCE_KERNEL_MAP_FIXED = 0x0010, // Fixed SCE_KERNEL_MAP_FIXED = 0x0010, // Fixed
SCE_KERNEL_MAP_NO_OVERWRITE = 0x0080, SCE_KERNEL_MAP_NO_OVERWRITE = 0x0080,
SCE_KERNEL_MAP_NO_COALESCE = 0x400000 SCE_KERNEL_MAP_NO_COALESCE = 0x400000
@ -28,7 +29,6 @@ enum MemoryProtection : u32 {
SCE_KERNEL_PROT_GPU_WRITE = 0x20, // Permit writes from the GPU SCE_KERNEL_PROT_GPU_WRITE = 0x20, // Permit writes from the GPU
SCE_KERNEL_PROT_GPU_RW = 0x30 // Permit reads/writes from the GPU SCE_KERNEL_PROT_GPU_RW = 0x30 // Permit reads/writes from the GPU
}; };
namespace HLE::Libs::LibKernel::MemoryManagement {
u64 PS4_SYSV_ABI sceKernelGetDirectMemorySize(); u64 PS4_SYSV_ABI sceKernelGetDirectMemorySize();
int PS4_SYSV_ABI sceKernelAllocateDirectMemory(s64 searchStart, s64 searchEnd, u64 len, u64 alignment, int memoryType, s64* physAddrOut); int PS4_SYSV_ABI sceKernelAllocateDirectMemory(s64 searchStart, s64 searchEnd, u64 len, u64 alignment, int memoryType, s64* physAddrOut);