Skip to content

Commit

Permalink
vm/sys_overlay Improvements
Browse files Browse the repository at this point in the history
- Allow mappings of .rsx_image segment, RSX flags are (flags >> 24) & 0x7 according to sce-tool source code
- Implement sys_overlay_load_module_by_fd
- Reduce vm::main size to 256mb
- Increase vm::user64k size to 512mb
- Implement special segment allocation when ppc_seg flag is specified
  • Loading branch information
elad335 committed Jun 17, 2019
1 parent d52953f commit 896b7a1
Show file tree
Hide file tree
Showing 15 changed files with 177 additions and 58 deletions.
2 changes: 1 addition & 1 deletion Utilities/Thread.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1407,7 +1407,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)
{
Expand Down
6 changes: 2 additions & 4 deletions rpcs3/Emu/Cell/Modules/cellSaveData.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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)
{
Expand Down
40 changes: 35 additions & 5 deletions rpcs3/Emu/Cell/PPUModule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include "Emu/Cell/PPUModule.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"
Expand All @@ -33,8 +34,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;

Expand Down Expand Up @@ -1057,6 +1056,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;
Expand All @@ -1083,8 +1083,14 @@ void ppu_load_exec(const ppu_exec_object& elf)
if (prog.bin.size() > size || prog.bin.size() != prog.p_filesz)
fmt::throw_exception("Invalid binary size (0x%llx, memsz=0x%x)", prog.bin.size(), size);

if (!vm::falloc(addr, size))
fmt::throw_exception("vm::falloc() failed (addr=0x%x, memsz=0x%x)", addr, size);
// Check if .rsx_image segment
const bool is_rsx_image = addr == 0x10000000;

if (auto area = vm::reserve_map(!is_rsx_image ? vm::main : vm::rsx_image, 0, u32{is_rsx_image} << 28, ((flag >> 24) & 0x7) ? 0x400 : 0x200);
!area || !area->falloc(addr, size))
{
fmt::throw_exception("falloc() failed (addr=0x%x, memsz=0x%x)" HERE, addr, size);
}

// Copy segment data, hash it
std::memcpy(vm::base(addr), prog.bin.data(), prog.bin.size());
Expand All @@ -1103,6 +1109,9 @@ void ppu_load_exec(const ppu_exec_object& elf)
}
}

// Allocate user 64k allocation block
vm::reserve_map(vm::user64k, 0, 0x20000000, 0x201);

// Load section list, used by the analyser
for (const auto& s : elf.shdrs)
{
Expand Down Expand Up @@ -1212,6 +1221,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);
Expand Down Expand Up @@ -1465,7 +1475,27 @@ 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 != 0)
{
if (vm::get(vm::rsx_image))
{
// TODO: Check this
fmt::throw_exception("Unhandled ppc seg allocation" HERE);
}

if (ppc_seg != 1)
{
LOG_TODO(LOADER, "Unknown ppc_seg flag = 0x%x", ppc_seg);
}

// Additional segment for fixed allocations
vm::reserve_map(vm::main_ex, 0, 0x10000000, 0x200);
}

// Initialize process arguments
auto args = vm::ptr<u64>::make(vm::alloc(u32{sizeof(u64)} * (::size32(Emu.argv) + ::size32(Emu.envp) + 2), vm::main));
Expand Down
2 changes: 1 addition & 1 deletion rpcs3/Emu/Cell/lv2/lv2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -427,7 +427,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)
Expand Down
4 changes: 2 additions & 2 deletions rpcs3/Emu/Cell/lv2/sys_memory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,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))
{
Expand Down Expand Up @@ -109,7 +109,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))
{
Expand Down
37 changes: 34 additions & 3 deletions rpcs3/Emu/Cell/lv2/sys_overlay.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,24 @@
#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);

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, std::string 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, path2, flags, entry);
if (!g_ps3_process_info.ppc_seg)
{
// Process not permitted
return CELL_ENOSYS;
}

const std::string path = path2.get_ptr();
const auto name = path.substr(path.find_last_of('/') + 1);

const ppu_exec_object obj = decrypt_self(fs::file(vfs::get(path)), fxm::get_always<LoadedNpdrmKeys_t>()->devKlic.data());
Expand All @@ -40,6 +45,32 @@ 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 (!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, flags=0x%x, entry=*0x%x)", ovlmid, fd, flags, entry);

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);
}

error_code sys_overlay_unload_module(u32 ovlmid)
{
sys_overlay.warning("sys_overlay_unload_module(ovlmid=0x%x)", ovlmid);
Expand Down
2 changes: 1 addition & 1 deletion rpcs3/Emu/Cell/lv2/sys_overlay.h
Original file line number Diff line number Diff line change
Expand Up @@ -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?
Expand Down
4 changes: 2 additions & 2 deletions rpcs3/Emu/Cell/lv2/sys_process.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@

LOG_CHANNEL(sys_process);

u32 g_ps3_sdk_version;
ps3_process_info_t g_ps3_process_info;

s32 process_getpid()
{
Expand Down Expand Up @@ -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;
}
Expand Down
8 changes: 8 additions & 0 deletions rpcs3/Emu/Cell/lv2/sys_process.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,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);
Expand Down
18 changes: 17 additions & 1 deletion rpcs3/Emu/Cell/lv2/sys_prx.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#include "stdafx.h"
#include "stdafx.h"
#include "Emu/Memory/vm.h"
#include "Emu/System.h"
#include "Emu/IdManager.h"
Expand All @@ -8,6 +8,7 @@
#include "Emu/Cell/ErrorCodes.h"
#include "Crypto/unedat.h"
#include "sys_fs.h"
#include "sys_process.h"
#include "sys_prx.h"


Expand Down Expand Up @@ -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 ((u32)flags)
{
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);

Expand Down
6 changes: 6 additions & 0 deletions rpcs3/Emu/Cell/lv2/sys_prx.h
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,12 @@ struct lv2_prx final : lv2_obj, ppu_module
be_t<u16> module_info_attributes;
};

enum : u64
{
SYS_PRX_LOAD_MODULE_FLAGS_FIXEDADDR = 1,
SYS_PRX_LOAD_MODULE_FLAGS_INVALIDMASK = 0xFFFFFFFE
};

// SysCalls

error_code sys_prx_get_ppu_guid();
Expand Down
2 changes: 1 addition & 1 deletion rpcs3/Emu/Cell/lv2/sys_rsx.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ error_code sys_rsx_context_iomap(u32 context_id, u32 io, u32 ea, u32 size, u64 f

for (u32 addr = ea, end = ea + size; addr < end; addr += 0x100000)
{
if (!vm::check_addr(addr, 1, vm::page_allocated | (addr < 0x20000000 ? 0 : vm::page_1m_size)))
if (!vm::check_addr(addr, 1, vm::page_allocated | vm::page_1m_size))
{
return CELL_EINVAL;
}
Expand Down

0 comments on commit 896b7a1

Please sign in to comment.