mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-04-20 03:25:16 +00:00
vm/sys_overlay Improvements
- Implement sys_overlay_load_module_by_fd. - Implement special segment allocation when ppc_seg flag is specified.
This commit is contained in:
parent
65134f73d6
commit
997e3046e3
14 changed files with 178 additions and 59 deletions
|
@ -1420,7 +1420,7 @@ bool handle_access_violation(u32 addr, bool is_writing, x64_context* context)
|
|||
if (cpu->check_state())
|
||||
{
|
||||
// Hack: allocate memory in case the emulator is stopping
|
||||
auto area = vm::get(vm::any, addr & -0x10000, 0x10000);
|
||||
auto area = vm::reserve_map(vm::any, addr & -0x10000, 0x10000);
|
||||
|
||||
if (area->flags & 0x100)
|
||||
{
|
||||
|
|
|
@ -16,8 +16,6 @@
|
|||
|
||||
LOG_CHANNEL(cellSaveData);
|
||||
|
||||
extern u32 g_ps3_sdk_version;
|
||||
|
||||
template<>
|
||||
void fmt_class_string<CellSaveDataError>::format(std::string& out, u64 arg)
|
||||
{
|
||||
|
@ -140,7 +138,7 @@ static bool savedata_check_args(u32 operation, u32 version, vm::cptr<char> dirNa
|
|||
}
|
||||
|
||||
if (!memchr(setList->dirNamePrefix.get_ptr(), '\0', CELL_SAVEDATA_PREFIX_SIZE)
|
||||
|| (g_ps3_sdk_version > 0x3FFFFF && !setList->dirNamePrefix[0]))
|
||||
|| (g_ps3_process_info.sdk_ver > 0x3FFFFF && !setList->dirNamePrefix[0]))
|
||||
{
|
||||
// ****** sysutil savedata parameter error : 17 ******
|
||||
return false;
|
||||
|
@ -803,7 +801,7 @@ static NEVER_INLINE error_code savedata_op(ppu_thread& ppu, u32 operation, u32 v
|
|||
return CELL_SAVEDATA_ERROR_PARAM;
|
||||
}
|
||||
|
||||
if (g_ps3_sdk_version > 0x36FFFF)
|
||||
if (g_ps3_process_info.sdk_ver > 0x36FFFF)
|
||||
{
|
||||
for (u8 resv : statSet->setParam->reserved2)
|
||||
{
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include "Emu/Cell/PPUOpcodes.h"
|
||||
#include "Emu/Cell/PPUAnalyser.h"
|
||||
|
||||
#include "Emu/Cell/lv2/sys_process.h"
|
||||
#include "Emu/Cell/lv2/sys_prx.h"
|
||||
#include "Emu/Cell/lv2/sys_memory.h"
|
||||
#include "Emu/Cell/lv2/sys_overlay.h"
|
||||
|
@ -34,8 +35,6 @@ extern void ppu_initialize();
|
|||
|
||||
extern void sys_initialize_tls(ppu_thread&, u64, u32, u32, u32);
|
||||
|
||||
extern u32 g_ps3_sdk_version;
|
||||
|
||||
// HLE function name cache
|
||||
std::vector<std::string> g_ppu_function_names;
|
||||
|
||||
|
@ -1064,6 +1063,7 @@ void ppu_load_exec(const ppu_exec_object& elf)
|
|||
s32 primary_prio = 1001;
|
||||
u32 primary_stacksize = 0x100000;
|
||||
u32 malloc_pagesize = 0x100000;
|
||||
u32 ppc_seg = 0;
|
||||
|
||||
// Executable hash
|
||||
sha1_context sha;
|
||||
|
@ -1219,6 +1219,7 @@ void ppu_load_exec(const ppu_exec_object& elf)
|
|||
|
||||
primary_stacksize = info.primary_stacksize;
|
||||
malloc_pagesize = info.malloc_pagesize;
|
||||
ppc_seg = info.ppc_seg;
|
||||
|
||||
LOG_NOTICE(LOADER, "*** sdk version: 0x%x", info.sdk_version);
|
||||
LOG_NOTICE(LOADER, "*** primary prio: %d", info.primary_prio);
|
||||
|
@ -1472,7 +1473,24 @@ void ppu_load_exec(const ppu_exec_object& elf)
|
|||
_main->validate(0);
|
||||
|
||||
// Set SDK version
|
||||
g_ps3_sdk_version = sdk_version;
|
||||
g_ps3_process_info.sdk_ver = sdk_version;
|
||||
|
||||
// Set ppc fixed allocations segment permission
|
||||
g_ps3_process_info.ppc_seg = ppc_seg;
|
||||
|
||||
if (ppc_seg != 0x0)
|
||||
{
|
||||
if (ppc_seg != 0x1)
|
||||
{
|
||||
LOG_TODO(LOADER, "Unknown ppc_seg flag value = 0x%x", ppc_seg);
|
||||
}
|
||||
|
||||
// Additional segment for fixed allocations
|
||||
if (!vm::map(0x30000000, 0x10000000, 0x200))
|
||||
{
|
||||
fmt::throw_exception("Failed to map ppc_seg's segment!" HERE);
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize process arguments
|
||||
auto args = vm::ptr<u64>::make(vm::alloc(u32{sizeof(u64)} * (::size32(Emu.argv) + ::size32(Emu.envp) + 2), vm::main));
|
||||
|
|
|
@ -429,7 +429,7 @@ const std::array<ppu_function_t, 1024> s_ppu_syscall_table
|
|||
BIND_FUNC(sys_overlay_unload_module), //451 (0x1C3)
|
||||
null_func,//BIND_FUNC(sys_overlay_get_module_list) //452 (0x1C4)
|
||||
null_func,//BIND_FUNC(sys_overlay_get_module_info) //453 (0x1C5)
|
||||
null_func,//BIND_FUNC(sys_overlay_load_module_by_fd) //454 (0x1C6)
|
||||
BIND_FUNC(sys_overlay_load_module_by_fd), //454 (0x1C6)
|
||||
null_func,//BIND_FUNC(sys_overlay_get_module_info2) //455 (0x1C7)
|
||||
null_func,//BIND_FUNC(sys_overlay_get_sdk_version) //456 (0x1C8)
|
||||
null_func,//BIND_FUNC(sys_overlay_get_module_dbg_info) //457 (0x1C9)
|
||||
|
|
|
@ -52,7 +52,7 @@ error_code sys_memory_allocate(u32 size, u64 flags, vm::ptr<u32> alloc_addr)
|
|||
return CELL_ENOMEM;
|
||||
}
|
||||
|
||||
if (const auto area = vm::get(align == 0x10000 ? vm::user64k : vm::user1m, 0, ::align(size, 0x10000000)))
|
||||
if (const auto area = vm::reserve_map(align == 0x10000 ? vm::user64k : vm::user1m, 0, ::align(size, 0x10000000), 0x401))
|
||||
{
|
||||
if (u32 addr = area->alloc(size, align))
|
||||
{
|
||||
|
@ -118,7 +118,7 @@ error_code sys_memory_allocate_from_container(u32 size, u32 cid, u64 flags, vm::
|
|||
// Create phantom memory object
|
||||
const auto mem = idm::make_ptr<lv2_memory_alloca>(size, align, flags, ct.ptr);
|
||||
|
||||
if (const auto area = vm::get(align == 0x10000 ? vm::user64k : vm::user1m, 0, ::align(size, 0x10000000)))
|
||||
if (const auto area = vm::reserve_map(align == 0x10000 ? vm::user64k : vm::user1m, 0, ::align(size, 0x10000000), 0x401))
|
||||
{
|
||||
if (u32 addr = area->alloc(size, mem->align, &mem->shm))
|
||||
{
|
||||
|
|
|
@ -7,7 +7,9 @@
|
|||
#include "Crypto/unedat.h"
|
||||
#include "Loader/ELF.h"
|
||||
|
||||
#include "sys_process.h"
|
||||
#include "sys_overlay.h"
|
||||
#include "sys_fs.h"
|
||||
|
||||
extern std::shared_ptr<lv2_overlay> ppu_load_overlay(const ppu_exec_object&, const std::string& path);
|
||||
|
||||
|
@ -15,14 +17,16 @@ extern void ppu_initialize(const ppu_module&);
|
|||
|
||||
LOG_CHANNEL(sys_overlay);
|
||||
|
||||
error_code sys_overlay_load_module(vm::ptr<u32> ovlmid, vm::cptr<char> path2, u64 flags, vm::ptr<u32> entry)
|
||||
static error_code overlay_load_module(vm::ptr<u32> ovlmid, const std::string& vpath, u64 flags, vm::ptr<u32> entry, fs::file src = {})
|
||||
{
|
||||
sys_overlay.warning("sys_overlay_load_module(ovlmid=*0x%x, path=%s, flags=0x%x, entry=*0x%x)", ovlmid, path2, flags, entry);
|
||||
const std::string path = vfs::get(vpath);
|
||||
|
||||
const std::string path = path2.get_ptr();
|
||||
const auto name = path.substr(path.find_last_of('/') + 1);
|
||||
if (!src)
|
||||
{
|
||||
src.open(path);
|
||||
}
|
||||
|
||||
const ppu_exec_object obj = decrypt_self(fs::file(vfs::get(path)), fxm::get_always<LoadedNpdrmKeys_t>()->devKlic.data());
|
||||
const ppu_exec_object obj = decrypt_self(std::move(src), fxm::get_always<LoadedNpdrmKeys_t>()->devKlic.data());
|
||||
|
||||
if (obj != elf_error::ok)
|
||||
{
|
||||
|
@ -33,7 +37,7 @@ error_code sys_overlay_load_module(vm::ptr<u32> ovlmid, vm::cptr<char> path2, u6
|
|||
|
||||
ppu_initialize(*ovlm);
|
||||
|
||||
sys_overlay.success("Loaded overlay: %s", path);
|
||||
sys_overlay.success("Loaded overlay: %s", vpath);
|
||||
|
||||
*ovlmid = idm::last_id();
|
||||
*entry = ovlm->entry;
|
||||
|
@ -41,6 +45,49 @@ error_code sys_overlay_load_module(vm::ptr<u32> ovlmid, vm::cptr<char> path2, u6
|
|||
return CELL_OK;
|
||||
}
|
||||
|
||||
error_code sys_overlay_load_module(vm::ptr<u32> ovlmid, vm::cptr<char> path, u64 flags, vm::ptr<u32> entry)
|
||||
{
|
||||
sys_overlay.warning("sys_overlay_load_module(ovlmid=*0x%x, path=%s, flags=0x%x, entry=*0x%x)", ovlmid, path, flags, entry);
|
||||
|
||||
if (!g_ps3_process_info.ppc_seg)
|
||||
{
|
||||
// Process not permitted
|
||||
return CELL_ENOSYS;
|
||||
}
|
||||
|
||||
if (!path)
|
||||
{
|
||||
return CELL_EFAULT;
|
||||
}
|
||||
|
||||
return overlay_load_module(ovlmid, path.get_ptr(), flags, entry);
|
||||
}
|
||||
|
||||
error_code sys_overlay_load_module_by_fd(vm::ptr<u32> ovlmid, u32 fd, u64 offset, u64 flags, vm::ptr<u32> entry)
|
||||
{
|
||||
sys_overlay.warning("sys_overlay_load_module_by_fd(ovlmid=*0x%x, fd=%d, offset=0x%llx, flags=0x%x, entry=*0x%x)", ovlmid, fd, offset, flags, entry);
|
||||
|
||||
if (!g_ps3_process_info.ppc_seg)
|
||||
{
|
||||
// Process not permitted
|
||||
return CELL_ENOSYS;
|
||||
}
|
||||
|
||||
if ((s64)offset < 0)
|
||||
{
|
||||
return CELL_EINVAL;
|
||||
}
|
||||
|
||||
const auto file = idm::get<lv2_fs_object, lv2_file>(fd);
|
||||
|
||||
if (!file)
|
||||
{
|
||||
return CELL_EBADF;
|
||||
}
|
||||
|
||||
return overlay_load_module(ovlmid, fmt::format("%s_x%x", file->name.data(), offset), flags, entry, lv2_file::make_view(file, offset));
|
||||
}
|
||||
|
||||
error_code sys_overlay_unload_module(u32 ovlmid)
|
||||
{
|
||||
sys_overlay.warning("sys_overlay_unload_module(ovlmid=0x%x)", ovlmid);
|
||||
|
|
|
@ -12,10 +12,10 @@ struct lv2_overlay final : lv2_obj, ppu_module
|
|||
};
|
||||
|
||||
error_code sys_overlay_load_module(vm::ptr<u32> ovlmid, vm::cptr<char> path, u64 flags, vm::ptr<u32> entry);
|
||||
error_code sys_overlay_load_module_by_fd(vm::ptr<u32> ovlmid, u32 fd, u64 offset, u64 flags, vm::ptr<u32> entry);
|
||||
error_code sys_overlay_unload_module(u32 ovlmid);
|
||||
//error_code sys_overlay_get_module_list(sys_pid_t pid, size_t ovlmids_num, sys_overlay_t * ovlmids, size_t * num_of_modules);
|
||||
//error_code sys_overlay_get_module_info(sys_pid_t pid, sys_overlay_t ovlmid, sys_overlay_module_info_t * info);
|
||||
//error_code sys_overlay_load_module_by_fd(sys_overlay_t * ovlmid, int fd, u64 offset, uint64_t flags, sys_addr_t * entry);
|
||||
//error_code sys_overlay_get_module_info2(sys_pid_t pid, sys_overlay_t ovlmid, sys_overlay_module_info2_t * info);//
|
||||
//error_code sys_overlay_get_sdk_version(); //2 params
|
||||
//error_code sys_overlay_get_module_dbg_info(); //3 params?
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
|
||||
LOG_CHANNEL(sys_process);
|
||||
|
||||
u32 g_ps3_sdk_version;
|
||||
ps3_process_info_t g_ps3_process_info;
|
||||
|
||||
s32 process_getpid()
|
||||
{
|
||||
|
@ -182,7 +182,7 @@ s32 _sys_process_get_paramsfo(vm::ptr<char> buffer)
|
|||
s32 process_get_sdk_version(u32 pid, s32& ver)
|
||||
{
|
||||
// get correct SDK version for selected pid
|
||||
ver = g_ps3_sdk_version;
|
||||
ver = g_ps3_process_info.sdk_ver;
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
|
|
@ -36,6 +36,14 @@ struct sys_exit2_param
|
|||
vm::bpptr<char, u64, u64> args;
|
||||
};
|
||||
|
||||
struct ps3_process_info_t
|
||||
{
|
||||
u32 sdk_ver;
|
||||
u32 ppc_seg;
|
||||
};
|
||||
|
||||
extern ps3_process_info_t g_ps3_process_info;
|
||||
|
||||
// Auxiliary functions
|
||||
s32 process_getpid();
|
||||
s32 process_get_sdk_version(u32 pid, s32& ver);
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include "Emu/Cell/ErrorCodes.h"
|
||||
#include "Crypto/unedat.h"
|
||||
#include "sys_fs.h"
|
||||
#include "sys_process.h"
|
||||
|
||||
|
||||
|
||||
|
@ -83,6 +84,21 @@ static const std::unordered_map<std::string, int> s_prx_ignore
|
|||
|
||||
static error_code prx_load_module(const std::string& vpath, u64 flags, vm::ptr<sys_prx_load_module_option_t> pOpt, fs::file src = {})
|
||||
{
|
||||
if (flags != 0)
|
||||
{
|
||||
if (flags & SYS_PRX_LOAD_MODULE_FLAGS_INVALIDMASK)
|
||||
{
|
||||
return CELL_EINVAL;
|
||||
}
|
||||
|
||||
if (flags & SYS_PRX_LOAD_MODULE_FLAGS_FIXEDADDR && !g_ps3_process_info.ppc_seg)
|
||||
{
|
||||
return CELL_ENOSYS;
|
||||
}
|
||||
|
||||
fmt::throw_exception("sys_prx: Unimplemented fixed address allocations" HERE);
|
||||
}
|
||||
|
||||
std::string name = vpath.substr(vpath.find_last_of('/') + 1);
|
||||
std::string path = vfs::get(vpath);
|
||||
|
||||
|
|
|
@ -137,6 +137,12 @@ struct lv2_prx final : lv2_obj, ppu_module
|
|||
be_t<u16> module_info_attributes;
|
||||
};
|
||||
|
||||
enum : u64
|
||||
{
|
||||
SYS_PRX_LOAD_MODULE_FLAGS_FIXEDADDR = 0x1ull,
|
||||
SYS_PRX_LOAD_MODULE_FLAGS_INVALIDMASK = ~SYS_PRX_LOAD_MODULE_FLAGS_FIXEDADDR,
|
||||
};
|
||||
|
||||
// SysCalls
|
||||
|
||||
error_code sys_prx_get_ppu_guid();
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#include "stdafx.h"
|
||||
#include "stdafx.h"
|
||||
#include "sys_rsx.h"
|
||||
|
||||
#include "Emu/System.h"
|
||||
|
|
|
@ -943,6 +943,31 @@ namespace vm
|
|||
return block;
|
||||
}
|
||||
|
||||
static std::shared_ptr<block_t> _get_map(memory_location_t location, u32 addr)
|
||||
{
|
||||
if (location != any)
|
||||
{
|
||||
// return selected location
|
||||
if (location < g_locations.size())
|
||||
{
|
||||
return g_locations[location];
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// search location by address
|
||||
for (auto& block : g_locations)
|
||||
{
|
||||
if (block && addr >= block->addr && addr <= block->addr + block->size - 1)
|
||||
{
|
||||
return block;
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::shared_ptr<block_t> map(u32 addr, u32 size, u64 flags)
|
||||
{
|
||||
vm::writer_lock lock(0);
|
||||
|
@ -1008,50 +1033,48 @@ namespace vm
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
std::shared_ptr<block_t> get(memory_location_t location, u32 addr, u32 area_size)
|
||||
std::shared_ptr<block_t> get(memory_location_t location, u32 addr)
|
||||
{
|
||||
vm::reader_lock lock;
|
||||
|
||||
if (location != any)
|
||||
return _get_map(location, addr);
|
||||
}
|
||||
|
||||
std::shared_ptr<block_t> reserve_map(memory_location_t location, u32 addr, u32 area_size, u64 flags)
|
||||
{
|
||||
vm::reader_lock lock;
|
||||
|
||||
auto area = _get_map(location, addr);
|
||||
|
||||
if (area)
|
||||
{
|
||||
return area;
|
||||
}
|
||||
|
||||
lock.upgrade();
|
||||
|
||||
// Fixed allocation
|
||||
if (addr)
|
||||
{
|
||||
// Recheck
|
||||
area = _get_map(location, addr);
|
||||
|
||||
return !area ? _map(addr, area_size, flags) : area;
|
||||
}
|
||||
|
||||
// Allocation on arbitrary address
|
||||
if (location != any && location < g_locations.size())
|
||||
{
|
||||
// return selected location
|
||||
if (location < g_locations.size())
|
||||
auto& loc = g_locations[location];
|
||||
|
||||
if (!loc)
|
||||
{
|
||||
auto& loc = g_locations[location];
|
||||
|
||||
if (!loc && area_size)
|
||||
{
|
||||
if (location == vm::user64k || location == vm::user1m)
|
||||
{
|
||||
lock.upgrade();
|
||||
|
||||
if (!loc)
|
||||
{
|
||||
// Deferred allocation
|
||||
loc = _find_map(area_size, 0x10000000, location == vm::user64k ? 0x201 : 0x401);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return loc;
|
||||
// Deferred allocation
|
||||
loc = _find_map(area_size, 0x10000000, flags);
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// search location by address
|
||||
for (auto& block : g_locations)
|
||||
{
|
||||
if (block && addr >= block->addr && addr <= block->addr + block->size - 1)
|
||||
{
|
||||
return block;
|
||||
}
|
||||
}
|
||||
|
||||
if (area_size)
|
||||
{
|
||||
lock.upgrade();
|
||||
return _map(addr, area_size, 0x200);
|
||||
return loc;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#pragma once
|
||||
#pragma once
|
||||
|
||||
#include <map>
|
||||
#include <memory>
|
||||
|
@ -116,7 +116,10 @@ namespace vm
|
|||
std::shared_ptr<block_t> unmap(u32 addr, bool must_be_empty = false);
|
||||
|
||||
// Get memory block associated with optionally specified memory location or optionally specified address
|
||||
std::shared_ptr<block_t> get(memory_location_t location, u32 addr = 0, u32 area_size = 0);
|
||||
std::shared_ptr<block_t> get(memory_location_t location, u32 addr = 0);
|
||||
|
||||
// Allocate segment at specified location, does nothing if exists already
|
||||
std::shared_ptr<block_t> reserve_map(memory_location_t location, u32 addr, u32 area_size, u64 flags = 0x200);
|
||||
|
||||
// Get PS3/PSV virtual memory address from the provided pointer (nullptr always converted to 0)
|
||||
inline vm::addr_t get_addr(const void* real_ptr)
|
||||
|
|
Loading…
Add table
Reference in a new issue