mirror of
https://github.com/RPCS3/rpcs3.git
synced 2024-11-22 18:53:28 +01:00
VSH Improvements (#13172)
* sys_prx: Implement PRX LIB register syscall * VSH: partial log spam fix * sys_process reboot fix * Implement sys_memory_container_destroy_parent_with_childs * sys_net: Implement SO_RCVTIMEO/SO_SENDTIMEO * VSH: Implement sys_rsx_context_free * PPU LLVM: distinguish PPU cache exec also by address Fixes referencing multiple PRX. * UI: Do not report size of apps inside /dev_flash
This commit is contained in:
parent
8ec1a5627d
commit
0946e5945f
@ -2876,7 +2876,7 @@ extern void ppu_finalize(const ppu_module& info)
|
|||||||
fmt::append(cache_path, "ppu-%s-%s/", fmt::base57(info.sha1), info.path.substr(info.path.find_last_of('/') + 1));
|
fmt::append(cache_path, "ppu-%s-%s/", fmt::base57(info.sha1), info.path.substr(info.path.find_last_of('/') + 1));
|
||||||
|
|
||||||
#ifdef LLVM_AVAILABLE
|
#ifdef LLVM_AVAILABLE
|
||||||
g_fxo->get<jit_module_manager>().remove(cache_path + info.name);
|
g_fxo->get<jit_module_manager>().remove(cache_path + info.name + "_" + std::to_string(info.segs[0].addr));
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3425,7 +3425,7 @@ bool ppu_initialize(const ppu_module& info, bool check_only)
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Permanently loaded compiled PPU modules (name -> data)
|
// Permanently loaded compiled PPU modules (name -> data)
|
||||||
jit_module& jit_mod = g_fxo->get<jit_module_manager>().get(cache_path + info.name);
|
jit_module& jit_mod = g_fxo->get<jit_module_manager>().get(cache_path + info.name + "_" + std::to_string(info.segs[0].addr));
|
||||||
|
|
||||||
// Compiler instance (deferred initialization)
|
// Compiler instance (deferred initialization)
|
||||||
std::shared_ptr<jit_compiler>& jit = jit_mod.pjit;
|
std::shared_ptr<jit_compiler>& jit = jit_mod.pjit;
|
||||||
|
@ -394,7 +394,7 @@ const std::array<std::pair<ppu_intrp_func_t, std::string_view>, 1024> g_ppu_sysc
|
|||||||
BIND_SYSC(sys_memory_container_destroy), //342 (0x156)
|
BIND_SYSC(sys_memory_container_destroy), //342 (0x156)
|
||||||
BIND_SYSC(sys_memory_container_get_size), //343 (0x157)
|
BIND_SYSC(sys_memory_container_get_size), //343 (0x157)
|
||||||
NULL_FUNC(sys_memory_budget_set), //344 (0x158)
|
NULL_FUNC(sys_memory_budget_set), //344 (0x158)
|
||||||
null_func,//BIND_SYSC(sys_memory_...), //345 (0x159)
|
BIND_SYSC(sys_memory_container_destroy_parent_with_childs), //345 (0x159)
|
||||||
null_func,//BIND_SYSC(sys_memory_...), //346 (0x15A)
|
null_func,//BIND_SYSC(sys_memory_...), //346 (0x15A)
|
||||||
uns_func, //347 (0x15B) UNS
|
uns_func, //347 (0x15B) UNS
|
||||||
BIND_SYSC(sys_memory_allocate), //348 (0x15C)
|
BIND_SYSC(sys_memory_allocate), //348 (0x15C)
|
||||||
|
@ -110,8 +110,6 @@ error_code sys_hid_manager_513(u64 a1, u64 a2, vm::ptr<void> buf, u64 buf_size)
|
|||||||
|
|
||||||
error_code sys_hid_manager_514(u32 pkg_id, vm::ptr<void> buf, u64 buf_size)
|
error_code sys_hid_manager_514(u32 pkg_id, vm::ptr<void> buf, u64 buf_size)
|
||||||
{
|
{
|
||||||
sys_hid.todo("sys_hid_manager_514(pkg_id=0x%x, buf=*0x%x, buf_size=0x%llx)", pkg_id, buf, buf_size);
|
|
||||||
|
|
||||||
if (pkg_id == 0xE)
|
if (pkg_id == 0xE)
|
||||||
{
|
{
|
||||||
sys_hid.trace("sys_hid_manager_514(pkg_id=0x%x, buf=*0x%x, buf_size=0x%llx)", pkg_id, buf, buf_size);
|
sys_hid.trace("sys_hid_manager_514(pkg_id=0x%x, buf=*0x%x, buf_size=0x%llx)", pkg_id, buf, buf_size);
|
||||||
@ -161,10 +159,11 @@ error_code sys_hid_manager_read(u32 handle, u32 pkg_id, vm::ptr<void> buf, u64 b
|
|||||||
return CELL_EFAULT;
|
return CELL_EFAULT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
(pkg_id == 2 || pkg_id == 0x81 ? sys_hid.trace : sys_hid.todo)
|
||||||
|
("sys_hid_manager_read(handle=0x%x, pkg_id=0x%x, buf=*0x%x, buf_size=0x%llx)", handle, pkg_id, buf, buf_size);
|
||||||
|
|
||||||
if (pkg_id == 2)
|
if (pkg_id == 2)
|
||||||
{
|
{
|
||||||
sys_hid.trace("sys_hid_manager_read(handle=0x%x, pkg_id=0x%x, buf=*0x%x, buf_size=0x%llx)", handle, pkg_id, buf, buf_size);
|
|
||||||
|
|
||||||
// cellPadGetData
|
// cellPadGetData
|
||||||
// it returns just button array from 'CellPadData'
|
// it returns just button array from 'CellPadData'
|
||||||
//auto data = vm::static_ptr_cast<u16[64]>(buf);
|
//auto data = vm::static_ptr_cast<u16[64]>(buf);
|
||||||
@ -179,8 +178,6 @@ error_code sys_hid_manager_read(u32 handle, u32 pkg_id, vm::ptr<void> buf, u64 b
|
|||||||
}
|
}
|
||||||
else if (pkg_id == 0x81)
|
else if (pkg_id == 0x81)
|
||||||
{
|
{
|
||||||
sys_hid.trace("sys_hid_manager_read(handle=0x%x, pkg_id=0x%x, buf=*0x%x, buf_size=0x%llx)", handle, pkg_id, buf, buf_size);
|
|
||||||
|
|
||||||
// cellPadGetDataExtra?
|
// cellPadGetDataExtra?
|
||||||
vm::var<CellPadData> tmpData;
|
vm::var<CellPadData> tmpData;
|
||||||
if ((cellPadGetData(0, +tmpData) == CELL_OK) && tmpData->len > 0)
|
if ((cellPadGetData(0, +tmpData) == CELL_OK) && tmpData->len > 0)
|
||||||
@ -191,7 +188,5 @@ error_code sys_hid_manager_read(u32 handle, u32 pkg_id, vm::ptr<void> buf, u64 b
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sys_hid.todo("sys_hid_manager_read(handle=0x%x, pkg_id=0x%x, buf=*0x%x, buf_size=0x%llx)", handle, pkg_id, buf, buf_size);
|
|
||||||
|
|
||||||
return CELL_OK;
|
return CELL_OK;
|
||||||
}
|
}
|
||||||
|
@ -402,3 +402,17 @@ error_code sys_memory_container_get_size(cpu_thread& cpu, vm::ptr<sys_memory_inf
|
|||||||
|
|
||||||
return CELL_OK;
|
return CELL_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
error_code sys_memory_container_destroy_parent_with_childs(cpu_thread& cpu, u32 cid, u32 must_0, vm::ptr<u32> mc_child)
|
||||||
|
{
|
||||||
|
sys_memory.warning("sys_memory_container_destroy_parent_with_childs(cid=0x%x, must_0=%d, mc_child=*0x%x)", cid, must_0, mc_child);
|
||||||
|
|
||||||
|
if (must_0)
|
||||||
|
{
|
||||||
|
return CELL_EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Multi-process is not supported yet so child containers mean nothing at the moment
|
||||||
|
// Simply destroy parent
|
||||||
|
return sys_memory_container_destroy(cpu, cid);
|
||||||
|
}
|
||||||
|
@ -137,3 +137,4 @@ error_code sys_memory_get_user_memory_stat(cpu_thread& cpu, vm::ptr<sys_memory_u
|
|||||||
error_code sys_memory_container_create(cpu_thread& cpu, vm::ptr<u32> cid, u32 size);
|
error_code sys_memory_container_create(cpu_thread& cpu, vm::ptr<u32> cid, u32 size);
|
||||||
error_code sys_memory_container_destroy(cpu_thread& cpu, u32 cid);
|
error_code sys_memory_container_destroy(cpu_thread& cpu, u32 cid);
|
||||||
error_code sys_memory_container_get_size(cpu_thread& cpu, vm::ptr<sys_memory_info_t> mem_info, u32 cid);
|
error_code sys_memory_container_get_size(cpu_thread& cpu, vm::ptr<sys_memory_info_t> mem_info, u32 cid);
|
||||||
|
error_code sys_memory_container_destroy_parent_with_childs(cpu_thread& cpu, u32 cid, u32 must_0, vm::ptr<u32> mc_child);
|
||||||
|
@ -256,6 +256,14 @@ lv2_socket::lv2_socket(utils::serial& ar, lv2_socket_type _type)
|
|||||||
// Try to match structure between different platforms
|
// Try to match structure between different platforms
|
||||||
ar.pos += 8;
|
ar.pos += 8;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
const s32 version = GET_SERIALIZATION_VERSION(lv2_net);
|
||||||
|
|
||||||
|
if (version >= 2)
|
||||||
|
{
|
||||||
|
ar(so_rcvtimeo, so_sendtimeo);
|
||||||
|
}
|
||||||
|
|
||||||
lv2_id = idm::last_id();
|
lv2_id = idm::last_id();
|
||||||
|
|
||||||
ar(last_bound_addr);
|
ar(last_bound_addr);
|
||||||
@ -303,6 +311,7 @@ void lv2_socket::save(utils::serial& ar, bool save_only_this_class)
|
|||||||
#else
|
#else
|
||||||
ar(std::array<char, 8>{});
|
ar(std::array<char, 8>{});
|
||||||
#endif
|
#endif
|
||||||
|
ar(so_rcvtimeo, so_sendtimeo);
|
||||||
ar(last_bound_addr);
|
ar(last_bound_addr);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -830,6 +839,13 @@ error_code sys_net_bnet_recvfrom(ppu_thread& ppu, s32 s, vm::ptr<void> buf, u32
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (sock.so_rcvtimeo && get_guest_system_time() - ppu.start_time > sock.so_rcvtimeo)
|
||||||
|
{
|
||||||
|
result = -SYS_NET_EWOULDBLOCK;
|
||||||
|
lv2_obj::awake(&ppu);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
sock.set_poll_event(lv2_socket::poll_t::read);
|
sock.set_poll_event(lv2_socket::poll_t::read);
|
||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
@ -1030,6 +1046,14 @@ error_code sys_net_bnet_sendto(ppu_thread& ppu, s32 s, vm::cptr<void> buf, u32 l
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (sock.so_sendtimeo && get_guest_system_time() - ppu.start_time > sock.so_sendtimeo)
|
||||||
|
{
|
||||||
|
result = -SYS_NET_EWOULDBLOCK;
|
||||||
|
lv2_obj::awake(&ppu);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
sock.set_poll_event(lv2_socket::poll_t::write);
|
sock.set_poll_event(lv2_socket::poll_t::write);
|
||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
|
@ -106,7 +106,7 @@ void lv2_socket::handle_events(const pollfd& native_pfd, [[maybe_unused]] bool u
|
|||||||
if (native_pfd.revents & POLLERR && events.test_and_reset(lv2_socket::poll_t::error))
|
if (native_pfd.revents & POLLERR && events.test_and_reset(lv2_socket::poll_t::error))
|
||||||
events_happening += lv2_socket::poll_t::error;
|
events_happening += lv2_socket::poll_t::error;
|
||||||
|
|
||||||
if (events_happening)
|
if (events_happening || (!queue.empty() && (so_rcvtimeo || so_sendtimeo)))
|
||||||
{
|
{
|
||||||
std::lock_guard lock(mutex);
|
std::lock_guard lock(mutex);
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
@ -114,7 +114,7 @@ void lv2_socket::handle_events(const pollfd& native_pfd, [[maybe_unused]] bool u
|
|||||||
set_connecting(false);
|
set_connecting(false);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
for (auto it = queue.begin(); events_happening && it != queue.end();)
|
for (auto it = queue.begin(); it != queue.end();)
|
||||||
{
|
{
|
||||||
if (it->second(events_happening))
|
if (it->second(events_happening))
|
||||||
{
|
{
|
||||||
|
@ -150,4 +150,8 @@ protected:
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
sys_net_sockaddr last_bound_addr{};
|
sys_net_sockaddr last_bound_addr{};
|
||||||
|
|
||||||
|
public:
|
||||||
|
u64 so_rcvtimeo = 0;
|
||||||
|
u64 so_sendtimeo = 0;
|
||||||
};
|
};
|
||||||
|
@ -634,13 +634,18 @@ s32 lv2_socket_native::setsockopt(s32 level, s32 optname, const std::vector<u8>&
|
|||||||
native_opt = optname == SYS_NET_SO_SNDTIMEO ? SO_SNDTIMEO : SO_RCVTIMEO;
|
native_opt = optname == SYS_NET_SO_SNDTIMEO ? SO_SNDTIMEO : SO_RCVTIMEO;
|
||||||
native_val = &native_timeo;
|
native_val = &native_timeo;
|
||||||
native_len = sizeof(native_timeo);
|
native_len = sizeof(native_timeo);
|
||||||
|
|
||||||
|
const int tv_sec = ::narrow<int>(reinterpret_cast<const sys_net_timeval*>(optval.data())->tv_sec);
|
||||||
|
const int tv_usec = ::narrow<int>(reinterpret_cast<const sys_net_timeval*>(optval.data())->tv_usec);
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
native_timeo = ::narrow<int>(reinterpret_cast<const sys_net_timeval*>(optval.data())->tv_sec) * 1000;
|
native_timeo = tv_sec * 1000;
|
||||||
native_timeo += ::narrow<int>(reinterpret_cast<const sys_net_timeval*>(optval.data())->tv_usec) / 1000;
|
native_timeo += tv_usec / 1000;
|
||||||
#else
|
#else
|
||||||
native_timeo.tv_sec = ::narrow<int>(reinterpret_cast<const sys_net_timeval*>(optval.data())->tv_sec);
|
native_timeo.tv_sec = tv_sec;
|
||||||
native_timeo.tv_usec = ::narrow<int>(reinterpret_cast<const sys_net_timeval*>(optval.data())->tv_usec);
|
native_timeo.tv_usec = tv_usec;
|
||||||
#endif
|
#endif
|
||||||
|
// TODO: Overflow detection?
|
||||||
|
(optname == SYS_NET_SO_SNDTIMEO ? so_sendtimeo : so_rcvtimeo) = tv_usec + tv_sec * 1000000;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SYS_NET_SO_LINGER:
|
case SYS_NET_SO_LINGER:
|
||||||
|
@ -409,7 +409,10 @@ void lv2_exitspawn(ppu_thread& ppu, std::vector<std::string>& argv, std::vector<
|
|||||||
{
|
{
|
||||||
ppu.state += cpu_flag::wait;
|
ppu.state += cpu_flag::wait;
|
||||||
|
|
||||||
Emu.CallFromMainThread([argv = std::move(argv), envp = std::move(envp), data = std::move(data)]() mutable
|
// sys_sm_shutdown
|
||||||
|
const bool is_real_reboot = (ppu.gpr[11] == 379);
|
||||||
|
|
||||||
|
Emu.CallFromMainThread([is_real_reboot, argv = std::move(argv), envp = std::move(envp), data = std::move(data)]() mutable
|
||||||
{
|
{
|
||||||
sys_process.success("Process finished -> %s", argv[0]);
|
sys_process.success("Process finished -> %s", argv[0]);
|
||||||
|
|
||||||
@ -428,8 +431,14 @@ void lv2_exitspawn(ppu_thread& ppu, std::vector<std::string>& argv, std::vector<
|
|||||||
|
|
||||||
using namespace id_manager;
|
using namespace id_manager;
|
||||||
|
|
||||||
auto func = [old_size = g_fxo->get<lv2_memory_container>().size, vec = (reader_lock{g_mutex}, g_fxo->get<id_map<lv2_memory_container>>().vec)](u32 sdk_suggested_mem) mutable
|
auto func = [is_real_reboot, old_size = g_fxo->get<lv2_memory_container>().size, vec = (reader_lock{g_mutex}, g_fxo->get<id_map<lv2_memory_container>>().vec)](u32 sdk_suggested_mem) mutable
|
||||||
{
|
{
|
||||||
|
if (is_real_reboot)
|
||||||
|
{
|
||||||
|
// Do not save containers on actual reboot
|
||||||
|
vec.clear();
|
||||||
|
}
|
||||||
|
|
||||||
// Save LV2 memory containers
|
// Save LV2 memory containers
|
||||||
g_fxo->init<id_map<lv2_memory_container>>()->vec = std::move(vec);
|
g_fxo->init<id_map<lv2_memory_container>>()->vec = std::move(vec);
|
||||||
|
|
||||||
|
@ -19,6 +19,7 @@ extern std::shared_ptr<lv2_prx> ppu_load_prx(const ppu_prx_object&, const std::s
|
|||||||
extern void ppu_unload_prx(const lv2_prx& prx);
|
extern void ppu_unload_prx(const lv2_prx& prx);
|
||||||
extern bool ppu_initialize(const ppu_module&, bool = false);
|
extern bool ppu_initialize(const ppu_module&, bool = false);
|
||||||
extern void ppu_finalize(const ppu_module&);
|
extern void ppu_finalize(const ppu_module&);
|
||||||
|
extern void ppu_manual_load_imports_exports(u32 imports_start, u32 imports_size, u32 exports_start, u32 exports_size, std::basic_string<bool>& loaded_flags);
|
||||||
|
|
||||||
LOG_CHANNEL(sys_prx);
|
LOG_CHANNEL(sys_prx);
|
||||||
|
|
||||||
@ -741,8 +742,6 @@ error_code _sys_prx_unload_module(ppu_thread& ppu, u32 id, u64 flags, vm::ptr<sy
|
|||||||
return CELL_OK;
|
return CELL_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ppu_manual_load_imports_exports(u32 imports_start, u32 imports_size, u32 exports_start, u32 exports_size, std::basic_string<bool>& loaded_flags);
|
|
||||||
|
|
||||||
void lv2_prx::load_exports()
|
void lv2_prx::load_exports()
|
||||||
{
|
{
|
||||||
if (exports_end <= exports_start)
|
if (exports_end <= exports_start)
|
||||||
@ -858,7 +857,14 @@ error_code _sys_prx_register_library(ppu_thread& ppu, vm::ptr<void> library)
|
|||||||
{
|
{
|
||||||
ppu.state += cpu_flag::wait;
|
ppu.state += cpu_flag::wait;
|
||||||
|
|
||||||
sys_prx.todo("_sys_prx_register_library(library=*0x%x)", library);
|
sys_prx.notice("_sys_prx_register_library(library=*0x%x)", library);
|
||||||
|
|
||||||
|
if (!vm::check_addr(library.addr()))
|
||||||
|
{
|
||||||
|
return CELL_EFAULT;
|
||||||
|
}
|
||||||
|
|
||||||
|
ppu_manual_load_imports_exports(0, 0, library.addr(), 0x1c, *std::make_unique<std::basic_string<bool>>());
|
||||||
return CELL_OK;
|
return CELL_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -279,21 +279,52 @@ error_code sys_rsx_context_allocate(cpu_thread& cpu, vm::ptr<u32> context_id, vm
|
|||||||
* lv2 SysCall 671 (0x29F): sys_rsx_context_free
|
* lv2 SysCall 671 (0x29F): sys_rsx_context_free
|
||||||
* @param context_id (IN): RSX context generated by sys_rsx_context_allocate to free the context.
|
* @param context_id (IN): RSX context generated by sys_rsx_context_allocate to free the context.
|
||||||
*/
|
*/
|
||||||
error_code sys_rsx_context_free(cpu_thread& cpu, u32 context_id)
|
error_code sys_rsx_context_free(ppu_thread& ppu, u32 context_id)
|
||||||
{
|
{
|
||||||
cpu.state += cpu_flag::wait;
|
ppu.state += cpu_flag::wait;
|
||||||
|
|
||||||
sys_rsx.todo("sys_rsx_context_free(context_id=0x%x)", context_id);
|
sys_rsx.todo("sys_rsx_context_free(context_id=0x%x)", context_id);
|
||||||
|
|
||||||
const auto render = rsx::get_current_renderer();
|
const auto render = rsx::get_current_renderer();
|
||||||
|
|
||||||
|
rsx::eng_lock fifo_lock(render);
|
||||||
std::scoped_lock lock(render->sys_rsx_mtx);
|
std::scoped_lock lock(render->sys_rsx_mtx);
|
||||||
|
|
||||||
if (context_id != 0x55555555 || !render->dma_address)
|
const u32 dma_address = render->dma_address;
|
||||||
|
render->dma_address = 0;
|
||||||
|
|
||||||
|
if (context_id != 0x55555555 || !dma_address || render->state & cpu_flag::ret)
|
||||||
{
|
{
|
||||||
return CELL_EINVAL;
|
return CELL_EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
g_fxo->get<rsx::vblank_thread>() = thread_state::finished;
|
||||||
|
|
||||||
|
const u32 queue_id = vm::_ptr<RsxDriverInfo>(render->driver_info)->handler_queue;
|
||||||
|
|
||||||
|
render->state += cpu_flag::ret;
|
||||||
|
|
||||||
|
while (render->state & cpu_flag::ret)
|
||||||
|
{
|
||||||
|
thread_ctrl::wait_for(1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
sys_event_port_disconnect(ppu, render->rsx_event_port);
|
||||||
|
sys_event_port_destroy(ppu, render->rsx_event_port);
|
||||||
|
sys_event_queue_destroy(ppu, queue_id, SYS_EVENT_QUEUE_DESTROY_FORCE);
|
||||||
|
|
||||||
|
render->label_addr = 0;
|
||||||
|
render->driver_info = 0;
|
||||||
|
render->main_mem_size = 0;
|
||||||
|
render->rsx_event_port = 0;
|
||||||
|
render->display_buffers_count = 0;
|
||||||
|
render->current_display_buffer = 0;
|
||||||
|
render->ctrl = nullptr;
|
||||||
|
render->rsx_thread_running = false;
|
||||||
|
render->serialized = false;
|
||||||
|
|
||||||
|
ensure(vm::get(vm::rsx_context)->dealloc(dma_address));
|
||||||
|
|
||||||
return CELL_OK;
|
return CELL_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -437,13 +468,46 @@ error_code sys_rsx_context_attribute(u32 context_id, u32 package_id, u64 a3, u64
|
|||||||
{
|
{
|
||||||
case 0x001: // FIFO
|
case 0x001: // FIFO
|
||||||
{
|
{
|
||||||
rsx::eng_lock rlock(render);
|
|
||||||
const u64 get = static_cast<u32>(a3);
|
const u64 get = static_cast<u32>(a3);
|
||||||
const u64 put = static_cast<u32>(a4);
|
const u64 put = static_cast<u32>(a4);
|
||||||
vm::_ref<atomic_be_t<u64>>(render->dma_address + ::offset32(&RsxDmaControl::put)).release(put << 32 | get);
|
const u64 get_put = put << 32 | get;
|
||||||
render->fifo_ctrl->set_get(static_cast<u32>(get));
|
bool changed_value = false;
|
||||||
render->last_known_code_start = get;
|
{
|
||||||
render->sync_point_request.release(true);
|
rsx::eng_lock rlock(render);
|
||||||
|
std::lock_guard lock(render->sys_rsx_mtx);
|
||||||
|
render->fifo_ctrl->abort();
|
||||||
|
|
||||||
|
while (render->new_get_put == umax)
|
||||||
|
{
|
||||||
|
if (render->new_get_put.compare_and_swap_test(u64{umax}, get_put))
|
||||||
|
{
|
||||||
|
changed_value = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Assume CAS can fail spuriously here
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wait for the first store to complete (or be aborted)
|
||||||
|
while (render->new_get_put != umax)
|
||||||
|
{
|
||||||
|
if (Emu.IsStopped() && changed_value)
|
||||||
|
{
|
||||||
|
// Abort
|
||||||
|
if (render->new_get_put.compare_and_swap_test(get_put, u64{umax}))
|
||||||
|
{
|
||||||
|
if (auto cpu = cpu_thread::get_current())
|
||||||
|
{
|
||||||
|
cpu->state += cpu_flag::again;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
thread_ctrl::wait_for(1000);
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -134,7 +134,7 @@ error_code sys_rsx_device_close(cpu_thread& cpu);
|
|||||||
error_code sys_rsx_memory_allocate(cpu_thread& cpu, vm::ptr<u32> mem_handle, vm::ptr<u64> mem_addr, u32 size, u64 flags, u64 a5, u64 a6, u64 a7);
|
error_code sys_rsx_memory_allocate(cpu_thread& cpu, vm::ptr<u32> mem_handle, vm::ptr<u64> mem_addr, u32 size, u64 flags, u64 a5, u64 a6, u64 a7);
|
||||||
error_code sys_rsx_memory_free(cpu_thread& cpu, u32 mem_handle);
|
error_code sys_rsx_memory_free(cpu_thread& cpu, u32 mem_handle);
|
||||||
error_code sys_rsx_context_allocate(cpu_thread& cpu, vm::ptr<u32> context_id, vm::ptr<u64> lpar_dma_control, vm::ptr<u64> lpar_driver_info, vm::ptr<u64> lpar_reports, u64 mem_ctx, u64 system_mode);
|
error_code sys_rsx_context_allocate(cpu_thread& cpu, vm::ptr<u32> context_id, vm::ptr<u64> lpar_dma_control, vm::ptr<u64> lpar_driver_info, vm::ptr<u64> lpar_reports, u64 mem_ctx, u64 system_mode);
|
||||||
error_code sys_rsx_context_free(cpu_thread& cpu, u32 context_id);
|
error_code sys_rsx_context_free(ppu_thread& ppu, u32 context_id);
|
||||||
error_code sys_rsx_context_iomap(cpu_thread& cpu, u32 context_id, u32 io, u32 ea, u32 size, u64 flags);
|
error_code sys_rsx_context_iomap(cpu_thread& cpu, u32 context_id, u32 io, u32 ea, u32 size, u64 flags);
|
||||||
error_code sys_rsx_context_iounmap(cpu_thread& cpu, u32 context_id, u32 io, u32 size);
|
error_code sys_rsx_context_iounmap(cpu_thread& cpu, u32 context_id, u32 io, u32 size);
|
||||||
error_code sys_rsx_context_attribute(u32 context_id, u32 package_id, u64 a3, u64 a4, u64 a5, u64 a6);
|
error_code sys_rsx_context_attribute(u32 context_id, u32 package_id, u64 a3, u64 a4, u64 a5, u64 a6);
|
||||||
|
@ -129,7 +129,7 @@ void sys_spu_image::free() const
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void sys_spu_image::deploy(u8* loc, std::span<const sys_spu_segment> segs)
|
void sys_spu_image::deploy(u8* loc, std::span<const sys_spu_segment> segs, bool is_verbose)
|
||||||
{
|
{
|
||||||
// Segment info dump
|
// Segment info dump
|
||||||
std::string dump;
|
std::string dump;
|
||||||
@ -192,7 +192,7 @@ void sys_spu_image::deploy(u8* loc, std::span<const sys_spu_segment> segs)
|
|||||||
applied += g_fxo->get<patch_engine>().apply(Emu.GetTitleID() + '-' + hash, loc);
|
applied += g_fxo->get<patch_engine>().apply(Emu.GetTitleID() + '-' + hash, loc);
|
||||||
}
|
}
|
||||||
|
|
||||||
spu_log.notice("Loaded SPU image: %s (<- %u)%s", hash, applied.size(), dump);
|
(is_verbose ? spu_log.notice : sys_spu.trace)("Loaded SPU image: %s (<- %u)%s", hash, applied.size(), dump);
|
||||||
}
|
}
|
||||||
|
|
||||||
lv2_spu_group::lv2_spu_group(utils::serial& ar) noexcept
|
lv2_spu_group::lv2_spu_group(utils::serial& ar) noexcept
|
||||||
@ -1061,7 +1061,7 @@ error_code sys_spu_thread_group_start(ppu_thread& ppu, u32 id)
|
|||||||
auto& args = group->args[thread->lv2_id >> 24];
|
auto& args = group->args[thread->lv2_id >> 24];
|
||||||
auto& img = group->imgs[thread->lv2_id >> 24];
|
auto& img = group->imgs[thread->lv2_id >> 24];
|
||||||
|
|
||||||
sys_spu_image::deploy(thread->ls, std::span(img.second.data(), img.second.size()));
|
sys_spu_image::deploy(thread->ls, std::span(img.second.data(), img.second.size()), group->stop_count < 5);
|
||||||
|
|
||||||
thread->cpu_init();
|
thread->cpu_init();
|
||||||
thread->gpr[3] = v128::from64(0, args[0]);
|
thread->gpr[3] = v128::from64(0, args[0]);
|
||||||
|
@ -227,7 +227,7 @@ struct sys_spu_image
|
|||||||
|
|
||||||
void load(const fs::file& stream);
|
void load(const fs::file& stream);
|
||||||
void free() const;
|
void free() const;
|
||||||
static void deploy(u8* loc, std::span<const sys_spu_segment> segs);
|
static void deploy(u8* loc, std::span<const sys_spu_segment> segs, bool is_verbose = true);
|
||||||
};
|
};
|
||||||
|
|
||||||
enum : u32
|
enum : u32
|
||||||
|
@ -546,7 +546,7 @@ namespace rsx
|
|||||||
if (dma_address)
|
if (dma_address)
|
||||||
{
|
{
|
||||||
ctrl = vm::_ptr<RsxDmaControl>(dma_address);
|
ctrl = vm::_ptr<RsxDmaControl>(dma_address);
|
||||||
m_rsx_thread_exiting = false;
|
rsx_thread_running = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (g_cfg.savestate.start_paused)
|
if (g_cfg.savestate.start_paused)
|
||||||
@ -712,7 +712,14 @@ namespace rsx
|
|||||||
thread_ctrl::wait_for(1000);
|
thread_ctrl::wait_for(1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
on_task();
|
on_task();
|
||||||
|
|
||||||
|
state -= cpu_flag::ret;
|
||||||
|
}
|
||||||
|
while (!is_stopped());
|
||||||
|
|
||||||
on_exit();
|
on_exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -778,8 +785,11 @@ namespace rsx
|
|||||||
|
|
||||||
rsx::overlays::reset_performance_overlay();
|
rsx::overlays::reset_performance_overlay();
|
||||||
|
|
||||||
|
if (!is_initialized)
|
||||||
|
{
|
||||||
g_fxo->get<rsx::dma_manager>().init();
|
g_fxo->get<rsx::dma_manager>().init();
|
||||||
on_init_thread();
|
on_init_thread();
|
||||||
|
}
|
||||||
|
|
||||||
is_initialized = true;
|
is_initialized = true;
|
||||||
is_initialized.notify_all();
|
is_initialized.notify_all();
|
||||||
@ -797,10 +807,16 @@ namespace rsx
|
|||||||
|
|
||||||
const u64 event_flags = unsent_gcm_events.exchange(0);
|
const u64 event_flags = unsent_gcm_events.exchange(0);
|
||||||
|
|
||||||
Emu.CallFromMainThread([]{ Emu.RunPPU(); });
|
if (Emu.IsStarting())
|
||||||
|
{
|
||||||
|
Emu.CallFromMainThread([]
|
||||||
|
{
|
||||||
|
Emu.RunPPU();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// Wait for startup (TODO)
|
// Wait for startup (TODO)
|
||||||
while (m_rsx_thread_exiting || Emu.IsPaused())
|
while (!rsx_thread_running || Emu.IsPaused())
|
||||||
{
|
{
|
||||||
// Execute backend-local tasks first
|
// Execute backend-local tasks first
|
||||||
do_local_task(performance_counters.state);
|
do_local_task(performance_counters.state);
|
||||||
@ -835,7 +851,7 @@ namespace rsx
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
g_fxo->init<named_thread>("VBlank Thread", [this]()
|
g_fxo->get<vblank_thread>().set_thread(std::make_shared<named_thread<std::function<void()>>>("VBlank Thread", [this]()
|
||||||
{
|
{
|
||||||
// See sys_timer_usleep for details
|
// See sys_timer_usleep for details
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
@ -909,7 +925,16 @@ namespace rsx
|
|||||||
start_time = rsx::uclock() - start_time;
|
start_time = rsx::uclock() - start_time;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
}));
|
||||||
|
|
||||||
|
struct join_vblank
|
||||||
|
{
|
||||||
|
~join_vblank() noexcept
|
||||||
|
{
|
||||||
|
g_fxo->get<vblank_thread>() = thread_state::finished;
|
||||||
|
}
|
||||||
|
|
||||||
|
} join_vblank_obj{};
|
||||||
|
|
||||||
// Raise priority above other threads
|
// Raise priority above other threads
|
||||||
thread_ctrl::scoped_priority high_prio(+1);
|
thread_ctrl::scoped_priority high_prio(+1);
|
||||||
@ -925,6 +950,11 @@ namespace rsx
|
|||||||
if (external_interrupt_lock)
|
if (external_interrupt_lock)
|
||||||
{
|
{
|
||||||
wait_pause();
|
wait_pause();
|
||||||
|
|
||||||
|
if (!rsx_thread_running)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Note a possible rollback address
|
// Note a possible rollback address
|
||||||
@ -967,6 +997,7 @@ namespace rsx
|
|||||||
do_local_task(rsx::FIFO_state::lock_wait);
|
do_local_task(rsx::FIFO_state::lock_wait);
|
||||||
|
|
||||||
g_fxo->get<rsx::dma_manager>().join();
|
g_fxo->get<rsx::dma_manager>().join();
|
||||||
|
g_fxo->get<vblank_thread>() = thread_state::finished;
|
||||||
state += cpu_flag::exit;
|
state += cpu_flag::exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1266,6 +1297,21 @@ namespace rsx
|
|||||||
m_invalidated_memory_range = utils::address_range::start_end(0x2 << 28, constants::local_mem_base + local_mem_size - 1);
|
m_invalidated_memory_range = utils::address_range::start_end(0x2 << 28, constants::local_mem_base + local_mem_size - 1);
|
||||||
handle_invalidated_memory_range();
|
handle_invalidated_memory_range();
|
||||||
}
|
}
|
||||||
|
else if (new_get_put != umax && state != FIFO_state::lock_wait)
|
||||||
|
{
|
||||||
|
const u64 get_put = new_get_put.exchange(u64{umax});
|
||||||
|
|
||||||
|
// Recheck in case aborted externally
|
||||||
|
if (get_put != umax)
|
||||||
|
{
|
||||||
|
vm::_ref<atomic_be_t<u64>>(dma_address + ::offset32(&RsxDmaControl::put)).release(get_put);
|
||||||
|
fifo_ctrl->set_get(static_cast<u32>(get_put));
|
||||||
|
fifo_ctrl->abort();
|
||||||
|
fifo_ret_addr = RSX_CALL_STACK_EMPTY;
|
||||||
|
last_known_code_start = static_cast<u32>(get_put);
|
||||||
|
sync_point_request.release(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::array<u32, 4> thread::get_color_surface_addresses() const
|
std::array<u32, 4> thread::get_color_surface_addresses() const
|
||||||
@ -2387,11 +2433,12 @@ namespace rsx
|
|||||||
dma_address = ctrlAddress;
|
dma_address = ctrlAddress;
|
||||||
ctrl = vm::_ptr<RsxDmaControl>(ctrlAddress);
|
ctrl = vm::_ptr<RsxDmaControl>(ctrlAddress);
|
||||||
flip_status = CELL_GCM_DISPLAY_FLIP_STATUS_DONE;
|
flip_status = CELL_GCM_DISPLAY_FLIP_STATUS_DONE;
|
||||||
|
fifo_ret_addr = RSX_CALL_STACK_EMPTY;
|
||||||
|
|
||||||
vm::write32(device_addr + 0x30, 1);
|
vm::write32(device_addr + 0x30, 1);
|
||||||
std::memset(display_buffers, 0, sizeof(display_buffers));
|
std::memset(display_buffers, 0, sizeof(display_buffers));
|
||||||
|
|
||||||
m_rsx_thread_exiting = false;
|
rsx_thread_running = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::pair<u32, u32> thread::calculate_memory_requirements(const vertex_input_layout& layout, u32 first_vertex, u32 vertex_count)
|
std::pair<u32, u32> thread::calculate_memory_requirements(const vertex_input_layout& layout, u32 first_vertex, u32 vertex_count)
|
||||||
@ -3098,7 +3145,7 @@ namespace rsx
|
|||||||
// we must block until RSX has invalidated the memory
|
// we must block until RSX has invalidated the memory
|
||||||
// or lock m_mtx_task and do it ourselves
|
// or lock m_mtx_task and do it ourselves
|
||||||
|
|
||||||
if (m_rsx_thread_exiting)
|
if (!rsx_thread_running)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
reader_lock lock(m_mtx_task);
|
reader_lock lock(m_mtx_task);
|
||||||
@ -3117,7 +3164,7 @@ namespace rsx
|
|||||||
|
|
||||||
void thread::on_notify_memory_unmapped(u32 address, u32 size)
|
void thread::on_notify_memory_unmapped(u32 address, u32 size)
|
||||||
{
|
{
|
||||||
if (!m_rsx_thread_exiting && address < rsx::constants::local_mem_base)
|
if (rsx_thread_running && address < rsx::constants::local_mem_base)
|
||||||
{
|
{
|
||||||
if (!isHLE)
|
if (!isHLE)
|
||||||
{
|
{
|
||||||
@ -3245,7 +3292,7 @@ namespace rsx
|
|||||||
|
|
||||||
external_interrupt_ack.store(true);
|
external_interrupt_ack.store(true);
|
||||||
|
|
||||||
while (external_interrupt_lock)
|
while (external_interrupt_lock && (cpu_flag::ret - state))
|
||||||
{
|
{
|
||||||
// TODO: Investigate non busy-spinning method
|
// TODO: Investigate non busy-spinning method
|
||||||
utils::pause();
|
utils::pause();
|
||||||
@ -3253,7 +3300,7 @@ namespace rsx
|
|||||||
|
|
||||||
external_interrupt_ack.store(false);
|
external_interrupt_ack.store(false);
|
||||||
}
|
}
|
||||||
while (external_interrupt_lock);
|
while (external_interrupt_lock && (cpu_flag::ret - state));
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 thread::get_load()
|
u32 thread::get_load()
|
||||||
@ -3734,4 +3781,19 @@ namespace rsx
|
|||||||
|
|
||||||
frame_times.push_back(frame_time_t{preempt_count, current_time, current_tsc});
|
frame_times.push_back(frame_time_t{preempt_count, current_time, current_tsc});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void vblank_thread::set_thread(std::shared_ptr<named_thread<std::function<void()>>> thread)
|
||||||
|
{
|
||||||
|
std::swap(m_thread, thread);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
vblank_thread& vblank_thread::operator=(thread_state state)
|
||||||
|
{
|
||||||
|
if (m_thread)
|
||||||
|
{
|
||||||
|
*m_thread = state;
|
||||||
|
}
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
} // namespace rsx
|
||||||
|
@ -450,6 +450,20 @@ namespace rsx
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class vblank_thread
|
||||||
|
{
|
||||||
|
std::shared_ptr<named_thread<std::function<void()>>> m_thread;
|
||||||
|
|
||||||
|
public:
|
||||||
|
vblank_thread() = default;
|
||||||
|
vblank_thread(const vblank_thread&) = delete;
|
||||||
|
|
||||||
|
void set_thread(std::shared_ptr<named_thread<std::function<void()>>> thread);
|
||||||
|
|
||||||
|
vblank_thread& operator=(thread_state);
|
||||||
|
vblank_thread& operator=(const vblank_thread&) = delete;
|
||||||
|
};
|
||||||
|
|
||||||
struct backend_configuration
|
struct backend_configuration
|
||||||
{
|
{
|
||||||
bool supports_multidraw; // Draw call batching
|
bool supports_multidraw; // Draw call batching
|
||||||
@ -489,7 +503,6 @@ namespace rsx
|
|||||||
|
|
||||||
void cpu_task() override;
|
void cpu_task() override;
|
||||||
protected:
|
protected:
|
||||||
atomic_t<bool> m_rsx_thread_exiting{ true };
|
|
||||||
|
|
||||||
std::array<push_buffer_vertex_info, 16> vertex_push_buffers;
|
std::array<push_buffer_vertex_info, 16> vertex_push_buffers;
|
||||||
std::vector<u32> element_push_buffer;
|
std::vector<u32> element_push_buffer;
|
||||||
@ -504,6 +517,7 @@ namespace rsx
|
|||||||
// FIFO
|
// FIFO
|
||||||
public:
|
public:
|
||||||
std::unique_ptr<FIFO::FIFO_control> fifo_ctrl;
|
std::unique_ptr<FIFO::FIFO_control> fifo_ctrl;
|
||||||
|
atomic_t<bool> rsx_thread_running{ false };
|
||||||
std::vector<std::pair<u32, u32>> dump_callstack_list() const override;
|
std::vector<std::pair<u32, u32>> dump_callstack_list() const override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
@ -541,6 +555,7 @@ namespace rsx
|
|||||||
u32 dma_address{0};
|
u32 dma_address{0};
|
||||||
rsx_iomap_table iomap_table;
|
rsx_iomap_table iomap_table;
|
||||||
u32 restore_point = 0;
|
u32 restore_point = 0;
|
||||||
|
atomic_t<u64> new_get_put = u64{umax};
|
||||||
u32 dbg_step_pc = 0;
|
u32 dbg_step_pc = 0;
|
||||||
u32 last_known_code_start = 0;
|
u32 last_known_code_start = 0;
|
||||||
atomic_t<u32> external_interrupt_lock{ 0 };
|
atomic_t<u32> external_interrupt_lock{ 0 };
|
||||||
|
@ -40,7 +40,7 @@ SERIALIZATION_VER(ppu, 1, 1)
|
|||||||
SERIALIZATION_VER(spu, 2, 1, 2 /*spu_limits_t ctor*/)
|
SERIALIZATION_VER(spu, 2, 1, 2 /*spu_limits_t ctor*/)
|
||||||
SERIALIZATION_VER(lv2_sync, 3, 1)
|
SERIALIZATION_VER(lv2_sync, 3, 1)
|
||||||
SERIALIZATION_VER(lv2_vm, 4, 1)
|
SERIALIZATION_VER(lv2_vm, 4, 1)
|
||||||
SERIALIZATION_VER(lv2_net, 5, 1)
|
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*/, 3/*Conditionally Loaded Local Exports*/)
|
||||||
SERIALIZATION_VER(lv2_memory, 8, 1)
|
SERIALIZATION_VER(lv2_memory, 8, 1)
|
||||||
|
@ -828,9 +828,20 @@ void game_list_frame::OnRefreshFinished()
|
|||||||
|
|
||||||
m_size_watcher_cancel = std::make_shared<atomic_t<bool>>(false);
|
m_size_watcher_cancel = std::make_shared<atomic_t<bool>>(false);
|
||||||
|
|
||||||
m_size_watcher.setFuture(QtConcurrent::map(m_game_data, [this, cancel = m_size_watcher_cancel](const game_info& game) -> void
|
m_size_watcher.setFuture(QtConcurrent::map(m_game_data, [this, cancel = m_size_watcher_cancel, dev_flash = g_cfg_vfs.get_dev_flash()](const game_info& game) -> void
|
||||||
{
|
{
|
||||||
if (game) game->info.size_on_disk = fs::get_dir_size(game->info.path, 1, cancel.get());
|
if (game)
|
||||||
|
{
|
||||||
|
if (game->info.path.starts_with(dev_flash))
|
||||||
|
{
|
||||||
|
// Do not report size of apps inside /dev_flash (it does not make sense to do so)
|
||||||
|
game->info.size_on_disk = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
game->info.size_on_disk = fs::get_dir_size(game->info.path, 1, cancel.get());
|
||||||
|
}
|
||||||
|
}
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user