mirror of
https://github.com/RPCS3/rpcs3.git
synced 2026-07-10 18:14:42 -06:00
Initail
This commit is contained in:
parent
63542309ca
commit
12feb8cc98
@ -432,6 +432,40 @@ namespace asmjit
|
||||
c.bind(next);
|
||||
}
|
||||
#endif
|
||||
|
||||
inline void emit_get_thread_pointer(native_asm& c, auto dst)
|
||||
{
|
||||
#if defined(_WIN64)
|
||||
|
||||
// mov dst, gs:[0x30]
|
||||
const asmjit::x86::Mem mmm = FN(x.setSegment(x86::gs), x)(x86::qword_ptr_abs(0x30));
|
||||
c.mov(x86::r15, mmm );
|
||||
|
||||
#elif defined(_WIN32)
|
||||
|
||||
// mov dst, fs:[0x18]
|
||||
c.mov(dst.r32(), FN(x.setSegment(x86::fs), x)(x86::dword_ptr_abs(0x18)));
|
||||
|
||||
#elif defined(__x86_64__)
|
||||
|
||||
// mov dst, fs:[0]
|
||||
c.mov(dst, FN(x.setSegment(x86::fs), x)(x86::qword_ptr_abs(0x0)));
|
||||
|
||||
#elif defined(__i386__)
|
||||
|
||||
// mov dst, gs:[0]
|
||||
c.mov(dst.r32(), FN(x.setSegment(x86::gs), x)(x86::dword_ptr_abs(0x0)));
|
||||
|
||||
#elif defined(__APPLE__)
|
||||
|
||||
// mrs dst, TPIDRRO_EL0
|
||||
c.emit(0xd53bd060 | dst.id());
|
||||
|
||||
#else
|
||||
// mrs dst, TPIDR_EL0
|
||||
c.emit(0xd53bd040 | dst.id());
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef __APPLE__
|
||||
|
||||
@ -652,7 +652,7 @@ namespace cpu_counter
|
||||
|
||||
void cpu_thread::operator()()
|
||||
{
|
||||
const auto ptr6 = lv2_process::acquire_globals(id_manager::g_process);
|
||||
const auto vm_globals_access = lv2_process::acquire_globals(id_manager::g_process);
|
||||
|
||||
const auto old_prefix = g_tls_log_prefix;
|
||||
|
||||
|
||||
@ -1146,7 +1146,7 @@ static import_result_t ppu_load_imports(const ppu_module<lv2_obj>& _module, std:
|
||||
// For _sys_prx_register_module
|
||||
void ppu_manual_load_imports_exports(u32 imports_start, u32 imports_size, u32 exports_start, u32 exports_size, std::basic_string<char>& loaded_flags)
|
||||
{
|
||||
ensure(cpu_thread::get_current<ppu_thread>());
|
||||
ensure(id_manager::g_process);
|
||||
|
||||
const auto process = ensure(idm::get_unlocked<lv2_obj, lv2_process>(id_manager::g_process));
|
||||
auto& _main = *process;
|
||||
@ -2206,6 +2206,12 @@ shared_ptr<lv2_process> ppu_load_self(const ppu_exec_object& elf, shared_ptr<lv2
|
||||
}
|
||||
}
|
||||
|
||||
if (!ar)
|
||||
{
|
||||
g_fxo->init<id_manager::id_map<lv2_memory_container>>();
|
||||
g_fxo->init<id_manager::id_map<named_thread<ppu_thread>>>();
|
||||
g_fxo->init<id_manager::id_map<lv2_obj>>();
|
||||
}
|
||||
|
||||
// Set for delayed initialization in ppu_initialize()
|
||||
const auto process_ptr = ar ? ensure(idm::get_unlocked<lv2_obj, lv2_process>(idm::last_id<lv2_process>())) : idm::make_ptr<lv2_obj, lv2_process>();
|
||||
@ -2836,6 +2842,8 @@ shared_ptr<lv2_process> ppu_load_self(const ppu_exec_object& elf, shared_ptr<lv2
|
||||
}
|
||||
}
|
||||
|
||||
const auto allows_VM_write_scope = lv2_process::acquire_globals(id_manager::g_process);
|
||||
|
||||
// Initialize main thread
|
||||
ppu_thread_params p{};
|
||||
p.stack_addr = vm::cast(vm::alloc(primary_stacksize, vm::stack, 4096));
|
||||
|
||||
@ -221,7 +221,9 @@ const auto ppu_gateway = build_function_asm<void(*)(ppu_thread*)>("ppu_gateway",
|
||||
c.mov(x86::qword_ptr(args[0], ::offset32(&ppu_thread::hv_ctx, &rpcs3::hypervisor_context_t::regs)), x86::rsp);
|
||||
|
||||
// Initialize args
|
||||
c.movabs(x86::r13, reinterpret_cast<u64>(&vm::g_exec_addr));
|
||||
asmjit::emit_get_thread_pointer(c, x86::r15);
|
||||
c.mov(x86::r13, x86::r15);
|
||||
c.add(x86::r13, utils::get_thread_storage_offset(&vm::g_exec_addr));
|
||||
c.mov(x86::r13, x86::qword_ptr(x86::r13));
|
||||
c.mov(x86::rbp, args[0]);
|
||||
c.mov(x86::edx, x86::dword_ptr(x86::rbp, ::offset32(&ppu_thread::cia))); // Load PC
|
||||
@ -234,7 +236,8 @@ const auto ppu_gateway = build_function_asm<void(*)(ppu_thread*)>("ppu_gateway",
|
||||
c.shl(x86::edx, 13);
|
||||
c.mov(x86::r12d, x86::edx); // Set relocation base
|
||||
|
||||
c.movabs(x86::rbx, reinterpret_cast<u64>(&vm::g_base_addr));
|
||||
c.mov(x86::rbx, x86::r15);
|
||||
c.add(x86::rbx, utils::get_thread_storage_offset(&vm::g_base_addr));
|
||||
c.mov(x86::rbx, x86::qword_ptr(x86::rbx));
|
||||
c.mov(x86::r14, x86::qword_ptr(x86::rbp, ::offset32(&ppu_thread::gpr, 0))); // Load some registers
|
||||
c.mov(x86::rsi, x86::qword_ptr(x86::rbp, ::offset32(&ppu_thread::gpr, 1)));
|
||||
|
||||
@ -460,7 +460,7 @@ error_code sys_rsx_context_iomap(cpu_thread& cpu, u32 context_id, u64 io, u64 ea
|
||||
|
||||
const auto render = rsx::get_current_renderer();
|
||||
|
||||
if (!size || io & 0xFFFFF || size > 0x200'00000 || size > std::min<u64>(~io, ~size) || ea & 0xFFFFF || size & 0xFFFFF)
|
||||
if (!size || io & 0xFFFFF || size > 0x200'00000 || size > std::min<u64>(~io, ~ea) || ea & 0xFFFFF || size & 0xFFFFF)
|
||||
{
|
||||
return CELL_EINVAL;
|
||||
}
|
||||
|
||||
@ -73,6 +73,12 @@ id_manager::id_key* idm::allocate_id(std::span<id_manager::id_key> keys, u32& hi
|
||||
return &(keys[highest_index++] = (id_manager::id_key(_next, type_id, dst_id.owning_process)));
|
||||
}
|
||||
|
||||
// id_map is not initialized
|
||||
if (highest_index == 0xCCCCCCCC)
|
||||
{
|
||||
fmt::throw_exception("id_map() is not initialized!");
|
||||
}
|
||||
|
||||
// Check all IDs starting from "next id" (TODO)
|
||||
for (u32 i = 0, next = base; i < count; i++, next += step)
|
||||
{
|
||||
|
||||
@ -857,13 +857,13 @@ namespace vm
|
||||
}
|
||||
else if (!shm)
|
||||
{
|
||||
utils::memory_protect(g_base_addr + addr, size, prot);
|
||||
utils::memory_protect(memory_4GB_model->base_addr + addr, size, prot);
|
||||
|
||||
perf_meter<"PAGE_LCK"_u64> perf;
|
||||
utils::memory_lock(g_base_addr + addr, size);
|
||||
utils::memory_lock(g_sudo_addr + addr, size);
|
||||
utils::memory_lock(memory_4GB_model->base_addr + addr, size);
|
||||
utils::memory_lock(memory_4GB_model->sudo_addr + addr, size);
|
||||
}
|
||||
else if (!map_critical(g_base_addr + addr, prot) || !map_critical(g_sudo_addr + addr, utils::protection::rw) || (map_error = "map_self()", !shm->map_self()))
|
||||
else if (!map_critical(memory_4GB_model->base_addr + addr, prot) || !map_critical(memory_4GB_model->sudo_addr + addr, utils::protection::rw) || (map_error = "map_self()", !shm->map_self()))
|
||||
{
|
||||
fmt::throw_exception("Memory mapping failed (addr=0x%x, size=0x%x, flags=0x%x): %s", addr, size, flags, map_error);
|
||||
}
|
||||
@ -871,11 +871,11 @@ namespace vm
|
||||
if (flags & page_executable && !is_noop)
|
||||
{
|
||||
// TODO (dead code)
|
||||
utils::memory_commit(g_exec_addr + addr * 2, size * 2);
|
||||
utils::memory_commit(memory_4GB_model->exec_addr + addr * 2, size * 2);
|
||||
|
||||
if (g_cfg.core.ppu_debug)
|
||||
{
|
||||
utils::memory_commit(g_stat_addr + addr, size);
|
||||
utils::memory_commit(memory_4GB_model->stat_addr + addr, size);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1057,19 +1057,19 @@ namespace vm
|
||||
}
|
||||
else
|
||||
{
|
||||
shm->unmap_critical(g_base_addr + addr);
|
||||
shm->unmap_critical(memory_4GB_model->base_addr + addr);
|
||||
#ifdef _WIN32
|
||||
shm->unmap_critical(g_sudo_addr + addr);
|
||||
shm->unmap_critical(memory_4GB_model->sudo_addr + addr);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (is_exec && !is_noop)
|
||||
{
|
||||
utils::memory_decommit(g_exec_addr + addr * 2, size * 2);
|
||||
utils::memory_decommit(memory_4GB_model->exec_addr + addr * 2, size * 2);
|
||||
|
||||
if (g_cfg.core.ppu_debug)
|
||||
{
|
||||
utils::memory_decommit(g_stat_addr + addr, size);
|
||||
utils::memory_decommit(memory_4GB_model->stat_addr + addr, size);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1091,13 +1091,14 @@ namespace vm
|
||||
}
|
||||
|
||||
const auto memory_4GB_model = get_current_memory_object();
|
||||
const auto pages = memory_4GB_model->pages;
|
||||
|
||||
// Always check this flag
|
||||
flags |= page_allocated;
|
||||
|
||||
for (u64 i = addr / 4096, max = (addr + size - 1) / 4096; i <= max;)
|
||||
{
|
||||
auto state = +memory_4GB_model->pages[i];
|
||||
auto state = +pages[i];
|
||||
|
||||
if (~state & flags) [[unlikely]]
|
||||
{
|
||||
@ -1335,7 +1336,8 @@ namespace vm
|
||||
// Special path for whole-allocated areas allowing 4k granularity
|
||||
m_common = std::make_shared<utils::shm>(size, fmt::format("_block_x%08x", addr));
|
||||
|
||||
if (!map_critical(vm::_ptr<u8>(addr), this->flags & page_size_4k && utils::get_page_size() > 4096 ? utils::protection::rw : utils::protection::no) || !map_critical(vm::get_super_ptr(addr), utils::protection::rw))
|
||||
if (!map_critical(memory_4GB_model->base_addr + addr, this->flags & page_size_4k && utils::get_page_size() > 4096 ? utils::protection::rw : utils::protection::no)
|
||||
|| !map_critical(memory_4GB_model->sudo_addr + addr, utils::protection::rw))
|
||||
{
|
||||
fmt::throw_exception("Memory mapping failed (addr=0x%x, size=0x%x, flags=0x%x): %s", addr, size, flags, map_error);
|
||||
}
|
||||
@ -1781,7 +1783,7 @@ namespace vm
|
||||
|
||||
// Save raw binary image
|
||||
const u32 guard_size = flags & stack_guarded ? 0x1000 : 0;
|
||||
serialize_memory_bytes(ar, vm::get_super_ptr<u8>(addr + guard_size), shm.first - guard_size * 2);
|
||||
serialize_memory_bytes(ar, memory_4GB_model->sudo_addr + (addr + guard_size), shm.first - guard_size * 2);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1804,8 +1806,8 @@ namespace vm
|
||||
if (flags & preallocated)
|
||||
{
|
||||
m_common = std::make_shared<utils::shm>(size, fmt::format("_block_x%08x", addr));
|
||||
m_common->map_critical(vm::base(addr), this->flags & page_size_4k && utils::get_page_size() > 4096 ? utils::protection::rw : utils::protection::no);
|
||||
m_common->map_critical(vm::get_super_ptr(addr));
|
||||
m_common->map_critical(memory_4GB_model->base_addr + addr, this->flags & page_size_4k && utils::get_page_size() > 4096 ? utils::protection::rw : utils::protection::no);
|
||||
m_common->map_critical(memory_4GB_model->sudo_addr + addr);
|
||||
}
|
||||
|
||||
std::shared_ptr<utils::shm> null_shm;
|
||||
@ -1857,7 +1859,7 @@ namespace vm
|
||||
{
|
||||
// Load binary image
|
||||
const u32 guard_size = flags & stack_guarded ? 0x1000 : 0;
|
||||
serialize_memory_bytes(ar, vm::get_super_ptr<u8>(addr0 + guard_size), size0 - guard_size * 2);
|
||||
serialize_memory_bytes(ar, memory_4GB_model->sudo_addr + (addr0 + guard_size), size0 - guard_size * 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2316,13 +2318,15 @@ namespace vm
|
||||
|
||||
void initialize_ps3_mmemory_object(ps3_virtual_memory_object* ptr)
|
||||
{
|
||||
ptr->base_addr = memory_reserve_4GiB(reinterpret_cast<void*>(0x2'0000'0000), 0x2'0000'0000, true);
|
||||
ptr->sudo_addr = ptr->base_addr + 0x1'0000'0000;
|
||||
ptr->exec_addr = memory_reserve_4GiB(ptr->sudo_addr, 0x300000000);
|
||||
ptr->hook_addr = memory_reserve_4GiB(ptr->exec_addr, 0x800000000);
|
||||
ptr->stat_addr = memory_reserve_4GiB(ptr->hook_addr);
|
||||
ptr->pages = static_cast<memory_page*>(utils::memory_reserve(0x10000000 / 4096));
|
||||
utils::memory_commit(ptr->pages, 0x10000000 / 4096);
|
||||
constexpr u64 pow32 = u64{1} << 32;
|
||||
|
||||
ptr->base_addr = memory_reserve_4GiB(reinterpret_cast<void*>(pow32 * 2), pow32 * 2, true);
|
||||
ptr->sudo_addr = ptr->base_addr + pow32;
|
||||
ptr->exec_addr = memory_reserve_4GiB(ptr->sudo_addr, pow32 * 4);
|
||||
ptr->hook_addr = memory_reserve_4GiB(ptr->exec_addr, pow32 * 8);
|
||||
ptr->stat_addr = memory_reserve_4GiB(ptr->exec_addr);
|
||||
ptr->pages = static_cast<memory_page*>(utils::memory_reserve(pow32 / 4096));
|
||||
utils::memory_commit(ptr->pages, pow32 / 4096);
|
||||
|
||||
vm_log.notice("Guest memory bases address ranges:\n"
|
||||
"vm::g_base_addr = %p - %p\n"
|
||||
@ -2338,7 +2342,7 @@ namespace vm
|
||||
ptr->stat_addr, ptr->stat_addr + 0xffff'ffff,
|
||||
g_reservations, g_reservations + sizeof(g_reservations) - 1);
|
||||
|
||||
std::memset(ptr->pages, 0, sizeof(0x10000000 / 4096));
|
||||
std::memset(ptr->pages, 0, sizeof(pow32 / 4096));
|
||||
|
||||
ptr->locations =
|
||||
{
|
||||
@ -2366,6 +2370,8 @@ namespace vm
|
||||
|
||||
void deinitialize_ps3_mmemory_object(ps3_virtual_memory_object* ptr)
|
||||
{
|
||||
constexpr u64 pow32 = u64{1} << 32;
|
||||
|
||||
{
|
||||
vm::writer_lock lock;
|
||||
|
||||
@ -2381,21 +2387,21 @@ namespace vm
|
||||
ptr->locations.clear();
|
||||
}
|
||||
|
||||
utils::memory_decommit(ptr->exec_addr, 0x200000000);
|
||||
utils::memory_decommit(ptr->stat_addr, 0x100000000);
|
||||
utils::memory_decommit(ptr->exec_addr, pow32 * 2);
|
||||
utils::memory_decommit(ptr->stat_addr, pow32);
|
||||
|
||||
#ifdef _WIN32
|
||||
s_hook.unmap(ptr->hook_addr);
|
||||
//ensure(utils::memory_reserve(0x800000000, ptr->hook_addr));
|
||||
//ensure(utils::memory_reserve(pow32 * 8, ptr->hook_addr));
|
||||
#else
|
||||
utils::memory_decommit(ptr->hook_addr, 0x800000000);
|
||||
utils::memory_decommit(ptr->hook_addr, pow32 * 8);
|
||||
#endif
|
||||
|
||||
utils::memory_release(ptr->base_addr, 0x2'0000'0000);
|
||||
utils::memory_release(ptr->exec_addr, 0x300000000);
|
||||
utils::memory_release(ptr->hook_addr, 0x800000000);
|
||||
utils::memory_release(ptr->stat_addr, 0x100000000);
|
||||
utils::memory_release(ptr->pages, 0x10000000 / 4096);
|
||||
utils::memory_release(ptr->base_addr, pow32 * 2);
|
||||
utils::memory_release(ptr->exec_addr, pow32 * 3);
|
||||
utils::memory_release(ptr->hook_addr, pow32 * 8);
|
||||
utils::memory_release(ptr->stat_addr, pow32);
|
||||
utils::memory_release(ptr->pages, pow32 / 4096);
|
||||
}
|
||||
|
||||
void save(ps3_virtual_memory_object* obj, utils::serial& ar)
|
||||
|
||||
@ -988,7 +988,7 @@ namespace rsx
|
||||
|
||||
performance_counters.state = FIFO::state::empty;
|
||||
|
||||
const u64 event_flags = lv2_context->unsent_gcm_events.exchange(0);
|
||||
const u64 event_flags = lv2_context ? lv2_context->unsent_gcm_events.exchange(0) : 0;
|
||||
|
||||
if (Emu.IsStarting())
|
||||
{
|
||||
|
||||
@ -1781,7 +1781,7 @@ void VKGSRender::do_local_task(rsx::FIFO::state state)
|
||||
{
|
||||
flush_command_queue(true);
|
||||
rsx::display_flip_info_t info{};
|
||||
info.buffer = lv2_context->current_display_buffer;
|
||||
info.buffer = lv2_context ? lv2_context->current_display_buffer : 0;
|
||||
flip(info);
|
||||
}
|
||||
}
|
||||
|
||||
@ -503,9 +503,9 @@ void VKGSRender::flip(const rsx::display_flip_info_t& info)
|
||||
return;
|
||||
}
|
||||
|
||||
u32 buffer_width = lv2_context->display_buffers[info.buffer].width;
|
||||
u32 buffer_height = lv2_context->display_buffers[info.buffer].height;
|
||||
u32 buffer_pitch = lv2_context->display_buffers[info.buffer].pitch;
|
||||
u32 buffer_width = lv2_context ? +lv2_context->display_buffers[info.buffer].width : 0;
|
||||
u32 buffer_height = lv2_context ? +lv2_context->display_buffers[info.buffer].height : 0;
|
||||
u32 buffer_pitch = lv2_context ? +lv2_context->display_buffers[info.buffer].pitch : 0;
|
||||
|
||||
u32 av_format;
|
||||
const auto& avconfig = g_fxo->get<rsx::avconf>();
|
||||
@ -537,7 +537,7 @@ void VKGSRender::flip(const rsx::display_flip_info_t& info)
|
||||
vk::viewable_image* image_to_flip = nullptr;
|
||||
vk::viewable_image* image_to_flip2 = nullptr;
|
||||
|
||||
if (info.buffer < lv2_context->display_buffers_count && buffer_width && buffer_height)
|
||||
if (lv2_context && info.buffer < lv2_context->display_buffers_count && buffer_width && buffer_height)
|
||||
{
|
||||
vk::present_surface_info present_info
|
||||
{
|
||||
|
||||
@ -1138,7 +1138,7 @@ void debugger_frame::UpdateUnitList()
|
||||
idm::select<named_thread<spu_thread>>(on_select, idm::unlocked);
|
||||
}
|
||||
|
||||
if (const auto render = g_fxo->try_get<rsx::thread>(); render && render->lv2_context->main_mem_size)
|
||||
if (const auto render = g_fxo->try_get<rsx::thread>(); render && render->lv2_context && render->lv2_context->main_mem_size)
|
||||
{
|
||||
on_select(render->id, *render);
|
||||
}
|
||||
|
||||
@ -497,6 +497,66 @@ namespace utils
|
||||
#error "Missing utils::trap() implementation"
|
||||
#endif
|
||||
}
|
||||
|
||||
inline void* get_thread_storage_pointer() noexcept
|
||||
{
|
||||
#if defined(_WIN64)
|
||||
|
||||
// TEB
|
||||
return (void*)__readgsqword(0x30);
|
||||
|
||||
#elif defined(_WIN32)
|
||||
|
||||
// TEB
|
||||
return (void*)__readfsdword(0x18);
|
||||
|
||||
#elif defined(__aarch64__) && defined(__APPLE__)
|
||||
|
||||
// Apple Silicon
|
||||
void* tp;
|
||||
asm volatile("mrs %0, TPIDRRO_EL0" : "=r"(tp));
|
||||
return tp;
|
||||
|
||||
#elif defined(__aarch64__)
|
||||
|
||||
// Linux/BSD AArch64
|
||||
void* tp;
|
||||
asm volatile("mrs %0, TPIDR_EL0" : "=r"(tp));
|
||||
return tp;
|
||||
|
||||
#elif defined(__x86_64__)
|
||||
|
||||
// SysV x86-64 (Linux, BSD, etc.)
|
||||
void* tp;
|
||||
asm volatile("mov %%fs:0, %0" : "=r"(tp));
|
||||
return tp;
|
||||
|
||||
#elif defined(__i386__)
|
||||
|
||||
// Linux/BSD i386
|
||||
void* tp;
|
||||
asm volatile("mov %%gs:0, %0" : "=r"(tp));
|
||||
return tp;
|
||||
#else
|
||||
#error Unsupported platform
|
||||
#endif
|
||||
}
|
||||
|
||||
inline usz get_thread_storage_offset(const void* ptr) noexcept
|
||||
{
|
||||
const usz ptr_addr = reinterpret_cast<usz>(ptr);
|
||||
const usz base = reinterpret_cast<usz>(get_thread_storage_pointer());
|
||||
|
||||
const usz ret_val = ptr_addr - base;
|
||||
|
||||
while (!ptr || ret_val > 0x100000000)
|
||||
{
|
||||
utils::trap();
|
||||
}
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
} // namespace utils
|
||||
|
||||
using utils::busy_wait;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user