mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-07-07 07:21:25 +12:00
PRX/savestates/VSH: Associate PRX with library, fix VSH browser (#13221)
* PRX/savestate:s Associate PRX with library * VFS/Savestates: Fix host_root resolving * Savestates: Fix segfault in ppu_initialize * SPU: Avoid some log spam * VSH/sys_vm: Fix limit on root processes
This commit is contained in:
parent
1852b370d7
commit
e6a7597444
10 changed files with 92 additions and 37 deletions
|
@ -678,10 +678,10 @@ static auto ppu_load_exports(ppu_linkage_info* link, u32 exports_start, u32 expo
|
||||||
std::lock_guard lock(link->mutex);
|
std::lock_guard lock(link->mutex);
|
||||||
|
|
||||||
usz unload_index = 0;
|
usz unload_index = 0;
|
||||||
|
|
||||||
for (u32 addr = exports_start; addr < exports_end; unload_index++)
|
|
||||||
{
|
|
||||||
ppu_prx_module_info lib{};
|
ppu_prx_module_info lib{};
|
||||||
|
|
||||||
|
for (u32 addr = exports_start; addr < exports_end; unload_index++, addr += lib.size ? lib.size : sizeof(ppu_prx_module_info))
|
||||||
|
{
|
||||||
std::memcpy(&lib, vm::base(addr), sizeof(lib));
|
std::memcpy(&lib, vm::base(addr), sizeof(lib));
|
||||||
|
|
||||||
const bool is_library = !!(lib.attributes & PRX_EXPORT_LIBRARY_FLAG);
|
const bool is_library = !!(lib.attributes & PRX_EXPORT_LIBRARY_FLAG);
|
||||||
|
@ -712,20 +712,17 @@ static auto ppu_load_exports(ppu_linkage_info* link, u32 exports_start, u32 expo
|
||||||
result.emplace(nid, addr);
|
result.emplace(nid, addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
addr += lib.size ? lib.size : sizeof(ppu_prx_module_info);
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!is_library)
|
if (!is_library)
|
||||||
{
|
{
|
||||||
// Skipped if none of the flags is set
|
// Skipped if none of the flags is set
|
||||||
addr += lib.size ? lib.size : sizeof(ppu_prx_module_info);
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (for_observing_callbacks)
|
if (for_observing_callbacks)
|
||||||
{
|
{
|
||||||
addr += lib.size ? lib.size : sizeof(ppu_prx_module_info);
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -738,7 +735,6 @@ static auto ppu_load_exports(ppu_linkage_info* link, u32 exports_start, u32 expo
|
||||||
ppu_register_library_lock(module_name, false);
|
ppu_register_library_lock(module_name, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
addr += lib.size ? lib.size : sizeof(ppu_prx_module_info);
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -759,7 +755,6 @@ static auto ppu_load_exports(ppu_linkage_info* link, u32 exports_start, u32 expo
|
||||||
if (!should_load)
|
if (!should_load)
|
||||||
{
|
{
|
||||||
ppu_loader.notice("** Skipped module '%s' (already loaded)", module_name);
|
ppu_loader.notice("** Skipped module '%s' (already loaded)", module_name);
|
||||||
addr += lib.size ? lib.size : sizeof(ppu_prx_module_info);
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -861,8 +856,6 @@ static auto ppu_load_exports(ppu_linkage_info* link, u32 exports_start, u32 expo
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
addr += lib.size ? lib.size : sizeof(ppu_prx_module_info);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
@ -1520,6 +1513,16 @@ std::shared_ptr<lv2_prx> ppu_load_prx(const ppu_prx_object& elf, const std::stri
|
||||||
prx->exports_start = lib_info->exports_start;
|
prx->exports_start = lib_info->exports_start;
|
||||||
prx->exports_end = lib_info->exports_end;
|
prx->exports_end = lib_info->exports_end;
|
||||||
|
|
||||||
|
for (usz start = prx->exports_start, size = 0;; size++, start += vm::read8(start) ? vm::read8(start) : sizeof(ppu_prx_module_info))
|
||||||
|
{
|
||||||
|
if (start >= prx->exports_end)
|
||||||
|
{
|
||||||
|
// Preallocate storage
|
||||||
|
prx->m_external_loaded_flags.resize(size);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ppu_loader.warning("Library %s (rtoc=0x%x):", lib_name, lib_info->toc);
|
ppu_loader.warning("Library %s (rtoc=0x%x):", lib_name, lib_info->toc);
|
||||||
|
|
||||||
prx->specials = ppu_load_exports(&link, prx->exports_start, prx->exports_end, true);
|
prx->specials = ppu_load_exports(&link, prx->exports_start, prx->exports_end, true);
|
||||||
|
|
|
@ -3208,6 +3208,11 @@ extern void ppu_initialize()
|
||||||
|
|
||||||
idm::select<lv2_obj, lv2_prx>([&](u32, lv2_prx& _module)
|
idm::select<lv2_obj, lv2_prx>([&](u32, lv2_prx& _module)
|
||||||
{
|
{
|
||||||
|
if (_module.funcs.empty())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (_module.path.starts_with(firmware_sprx_path))
|
if (_module.path.starts_with(firmware_sprx_path))
|
||||||
{
|
{
|
||||||
// Postpone testing
|
// Postpone testing
|
||||||
|
|
|
@ -1267,7 +1267,7 @@ std::string spu_thread::dump_misc() const
|
||||||
|
|
||||||
void spu_thread::cpu_on_stop()
|
void spu_thread::cpu_on_stop()
|
||||||
{
|
{
|
||||||
if (current_func)
|
if (current_func && is_stopped(state - cpu_flag::stop))
|
||||||
{
|
{
|
||||||
if (start_time)
|
if (start_time)
|
||||||
{
|
{
|
||||||
|
@ -1496,7 +1496,7 @@ void spu_thread::cpu_task()
|
||||||
unsavable = false;
|
unsavable = false;
|
||||||
|
|
||||||
// Print some stats
|
// Print some stats
|
||||||
spu_log.notice("Stats: Block Weight: %u (Retreats: %u);", block_counter, block_failure);
|
(!group || group->stop_count < 5 ? spu_log.notice : spu_log.trace)("Stats: Block Weight: %u (Retreats: %u);", block_counter, block_failure);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
@ -308,11 +308,12 @@ std::shared_ptr<void> lv2_prx::load(utils::serial& ar)
|
||||||
|
|
||||||
if (seg_count)
|
if (seg_count)
|
||||||
{
|
{
|
||||||
std::basic_string<bool> loaded_flags;
|
std::basic_string<bool> loaded_flags, external_flags;
|
||||||
|
|
||||||
if (version >= 3)
|
if (version >= 4)
|
||||||
{
|
{
|
||||||
ar(loaded_flags);
|
ar(loaded_flags);
|
||||||
|
ar(external_flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
fs::file file{path.substr(0, path.size() - (offset ? fmt::format("_x%x", offset).size() : 0))};
|
fs::file file{path.substr(0, path.size() - (offset ? fmt::format("_x%x", offset).size() : 0))};
|
||||||
|
@ -323,13 +324,14 @@ std::shared_ptr<void> lv2_prx::load(utils::serial& ar)
|
||||||
file = make_file_view(std::move(file), offset);
|
file = make_file_view(std::move(file), offset);
|
||||||
prx = ppu_load_prx(ppu_prx_object{ decrypt_self(std::move(file), reinterpret_cast<u8*>(&klic)) }, path, 0, &ar);
|
prx = ppu_load_prx(ppu_prx_object{ decrypt_self(std::move(file), reinterpret_cast<u8*>(&klic)) }, path, 0, &ar);
|
||||||
prx->m_loaded_flags = std::move(loaded_flags);
|
prx->m_loaded_flags = std::move(loaded_flags);
|
||||||
|
prx->m_external_loaded_flags = std::move(external_flags);
|
||||||
|
|
||||||
if (version == 2 && state == PRX_STATE_STARTED)
|
if (version == 2 && (state == PRX_STATE_STARTED || state == PRX_STATE_STARTING))
|
||||||
{
|
{
|
||||||
prx->load_exports();
|
prx->load_exports();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (version == 3 && state == PRX_STATE_STARTED)
|
if (version >= 4 && state <= PRX_STATE_STARTED)
|
||||||
{
|
{
|
||||||
prx->restore_exports();
|
prx->restore_exports();
|
||||||
}
|
}
|
||||||
|
@ -377,6 +379,7 @@ void lv2_prx::save(utils::serial& ar)
|
||||||
if (!segs.empty())
|
if (!segs.empty())
|
||||||
{
|
{
|
||||||
ar(m_loaded_flags);
|
ar(m_loaded_flags);
|
||||||
|
ar(m_external_loaded_flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const ppu_segment& seg : segs)
|
for (const ppu_segment& seg : segs)
|
||||||
|
@ -765,9 +768,9 @@ void lv2_prx::restore_exports()
|
||||||
|
|
||||||
std::basic_string<bool> loaded_flags_empty;
|
std::basic_string<bool> loaded_flags_empty;
|
||||||
|
|
||||||
for (usz start = exports_start, i = 0; start < exports_end; i++, start += sizeof_export_data)
|
for (usz start = exports_start, i = 0; start < exports_end; i++, start += vm::read8(start) ? vm::read8(start) : sizeof_export_data)
|
||||||
{
|
{
|
||||||
if (::at32(m_loaded_flags, i))
|
if (::at32(m_external_loaded_flags, i) || (!m_loaded_flags.empty() && ::at32(m_loaded_flags, i)))
|
||||||
{
|
{
|
||||||
loaded_flags_empty.clear();
|
loaded_flags_empty.clear();
|
||||||
ppu_manual_load_imports_exports(0, 0, start, sizeof_export_data, loaded_flags_empty);
|
ppu_manual_load_imports_exports(0, 0, start, sizeof_export_data, loaded_flags_empty);
|
||||||
|
@ -783,7 +786,14 @@ void lv2_prx::unload_exports()
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ppu_manual_load_imports_exports(0, 0, exports_start, exports_end - exports_start, m_loaded_flags);
|
std::basic_string<bool> merged = m_loaded_flags;
|
||||||
|
|
||||||
|
for (usz i = 0; i < merged.size(); i++)
|
||||||
|
{
|
||||||
|
merged[i] |= ::at32(m_external_loaded_flags, i);
|
||||||
|
}
|
||||||
|
|
||||||
|
ppu_manual_load_imports_exports(0, 0, exports_start, exports_end - exports_start, merged);
|
||||||
}
|
}
|
||||||
|
|
||||||
error_code _sys_prx_register_module(ppu_thread& ppu, vm::cptr<char> name, vm::ptr<void> opt)
|
error_code _sys_prx_register_module(ppu_thread& ppu, vm::cptr<char> name, vm::ptr<void> opt)
|
||||||
|
@ -864,7 +874,39 @@ error_code _sys_prx_register_library(ppu_thread& ppu, vm::ptr<void> library)
|
||||||
return CELL_EFAULT;
|
return CELL_EFAULT;
|
||||||
}
|
}
|
||||||
|
|
||||||
ppu_manual_load_imports_exports(0, 0, library.addr(), 0x1c, *std::make_unique<std::basic_string<bool>>());
|
constexpr u32 sizeof_lib = 0x1c;
|
||||||
|
|
||||||
|
std::array<char, sizeof_lib> mem_copy{};
|
||||||
|
std::memcpy(mem_copy.data(), library.get_ptr(), sizeof_lib);
|
||||||
|
|
||||||
|
std::basic_string<bool> flags;
|
||||||
|
ppu_manual_load_imports_exports(0, 0, library.addr(), sizeof_lib, flags);
|
||||||
|
|
||||||
|
if (flags.front())
|
||||||
|
{
|
||||||
|
const bool success = idm::select<lv2_obj, lv2_prx>([&](u32 id, lv2_prx& prx)
|
||||||
|
{
|
||||||
|
if (prx.state == PRX_STATE_INITIALIZED)
|
||||||
|
{
|
||||||
|
for (u32 lib_addr = prx.exports_start, index = 0; lib_addr < prx.exports_end; index++, lib_addr += vm::read8(lib_addr) ? vm::read8(lib_addr) : sizeof_lib)
|
||||||
|
{
|
||||||
|
if (std::memcpy(vm::base(lib_addr), mem_copy.data(), sizeof_lib) == 0)
|
||||||
|
{
|
||||||
|
atomic_storage<bool>::release(prx.m_external_loaded_flags[index], true);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}).ret;
|
||||||
|
|
||||||
|
if (!success)
|
||||||
|
{
|
||||||
|
sys_prx.error("_sys_prx_register_library(): Failed to associate library to PRX!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return CELL_OK;
|
return CELL_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -196,6 +196,7 @@ struct lv2_prx final : lv2_obj, ppu_module
|
||||||
u32 exports_end = 0;
|
u32 exports_end = 0;
|
||||||
|
|
||||||
std::basic_string<bool> m_loaded_flags;
|
std::basic_string<bool> m_loaded_flags;
|
||||||
|
std::basic_string<bool> m_external_loaded_flags;
|
||||||
|
|
||||||
void load_exports(); // (Re)load exports
|
void load_exports(); // (Re)load exports
|
||||||
void restore_exports(); // For savestates
|
void restore_exports(); // For savestates
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
#include "stdafx.h"
|
#include "stdafx.h"
|
||||||
#include "sys_vm.h"
|
#include "sys_vm.h"
|
||||||
|
#include "sys_process.h"
|
||||||
|
|
||||||
#include "Emu/IdManager.h"
|
#include "Emu/IdManager.h"
|
||||||
#include "Emu/Cell/ErrorCodes.h"
|
#include "Emu/Cell/ErrorCodes.h"
|
||||||
|
@ -70,7 +71,8 @@ error_code sys_vm_memory_map(ppu_thread& ppu, u32 vsize, u32 psize, u32 cid, u64
|
||||||
if (!g_fxo->get<sys_vm_global_t>().total_vsize.fetch_op([vsize](u32& size)
|
if (!g_fxo->get<sys_vm_global_t>().total_vsize.fetch_op([vsize](u32& size)
|
||||||
{
|
{
|
||||||
// A single process can hold up to 256MB of virtual memory, even on DECR
|
// A single process can hold up to 256MB of virtual memory, even on DECR
|
||||||
if (0x10000000 - size < vsize)
|
// VSH can hold more
|
||||||
|
if ((g_ps3_process_info.has_root_perm() ? 0x1E000000 : 0x10000000) - size < vsize)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1077,10 +1077,10 @@ game_boot_result Emulator::Load(const std::string& title_id, bool add_only, bool
|
||||||
m_path = disc;
|
m_path = disc;
|
||||||
m_path += std::string_view(argv[0]).substr(9);
|
m_path += std::string_view(argv[0]).substr(9);
|
||||||
}
|
}
|
||||||
else if (argv[0].starts_with("/host_root"sv))
|
else if (argv[0].starts_with("/host_root/"sv))
|
||||||
{
|
{
|
||||||
sys_log.error("Host root has been used in path redirection!");
|
sys_log.error("Host root has been used in path redirection!");
|
||||||
m_path = argv[0].substr(9);
|
m_path = argv[0].substr(11);
|
||||||
}
|
}
|
||||||
else if (argv[0].starts_with("/dev_hdd1"sv))
|
else if (argv[0].starts_with("/dev_hdd1"sv))
|
||||||
{
|
{
|
||||||
|
|
|
@ -75,6 +75,10 @@ bool vfs::mount(std::string_view vpath, std::string_view path, bool is_dir)
|
||||||
list.back()->path += '/';
|
list.back()->path += '/';
|
||||||
if (!is_dir && list.back()->path.ends_with('/'))
|
if (!is_dir && list.back()->path.ends_with('/'))
|
||||||
vfs_log.error("File mounted with trailing /.");
|
vfs_log.error("File mounted with trailing /.");
|
||||||
|
|
||||||
|
if (path == "/") // Special
|
||||||
|
list.back()->path = "/";
|
||||||
|
|
||||||
vfs_log.notice("Mounted path \"%s\" to \"%s\"", vpath_backup, list.back()->path);
|
vfs_log.notice("Mounted path \"%s\" to \"%s\"", vpath_backup, list.back()->path);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -376,21 +380,19 @@ std::string vfs::retrieve(std::string_view path, const vfs_directory* node, std:
|
||||||
|
|
||||||
std::vector<std::string_view> mount_path_empty;
|
std::vector<std::string_view> mount_path_empty;
|
||||||
|
|
||||||
if (std::string res = vfs::retrieve(path, &table.root, &mount_path_empty); !res.empty())
|
const std::string rpath = Emu.GetCallbacks().resolve_path(path);
|
||||||
|
|
||||||
|
if (!rpath.empty())
|
||||||
|
{
|
||||||
|
if (std::string res = vfs::retrieve(rpath, &table.root, &mount_path_empty); !res.empty())
|
||||||
{
|
{
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
mount_path_empty.clear();
|
mount_path_empty.clear();
|
||||||
|
|
||||||
const std::string rpath = Emu.GetCallbacks().resolve_path(path);
|
return vfs::retrieve(path, &table.root, &mount_path_empty);
|
||||||
|
|
||||||
if (rpath.empty())
|
|
||||||
{
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
return vfs::retrieve(rpath, &table.root, &mount_path_empty);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
mount_path->emplace_back();
|
mount_path->emplace_back();
|
||||||
|
|
|
@ -42,7 +42,7 @@ SERIALIZATION_VER(lv2_sync, 3, 1)
|
||||||
SERIALIZATION_VER(lv2_vm, 4, 1)
|
SERIALIZATION_VER(lv2_vm, 4, 1)
|
||||||
SERIALIZATION_VER(lv2_net, 5, 1, 2/*RECV/SEND timeout*/)
|
SERIALIZATION_VER(lv2_net, 5, 1, 2/*RECV/SEND timeout*/)
|
||||||
SERIALIZATION_VER(lv2_fs, 6, 1)
|
SERIALIZATION_VER(lv2_fs, 6, 1)
|
||||||
SERIALIZATION_VER(lv2_prx_overlay, 7, 1, 2/*PRX dynamic exports*/, 3/*Conditionally Loaded Local Exports*/)
|
SERIALIZATION_VER(lv2_prx_overlay, 7, 1, 2/*PRX dynamic exports*/, 4/*Conditionally Loaded Local Exports*/)
|
||||||
SERIALIZATION_VER(lv2_memory, 8, 1)
|
SERIALIZATION_VER(lv2_memory, 8, 1)
|
||||||
SERIALIZATION_VER(lv2_config, 9, 1)
|
SERIALIZATION_VER(lv2_config, 9, 1)
|
||||||
|
|
||||||
|
|
|
@ -72,7 +72,7 @@ Localized::sound::sound()
|
||||||
|
|
||||||
Localized::title_t::title_t()
|
Localized::title_t::title_t()
|
||||||
: titles({
|
: titles({
|
||||||
{ "vsh/module/vsh.self", tr("XMB (VSH)") },
|
{ "vsh/module/vsh.self", tr("The PS3 Interface (XMB, or VSH)") },
|
||||||
})
|
})
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue