mirror of
https://github.com/RPCS3/rpcs3.git
synced 2024-11-22 10:42:36 +01:00
vm::g_exec_addr added
s_ppu_compiled renamed Exception handling enabled
This commit is contained in:
parent
e4d1bdef07
commit
37a97a71e3
@ -1229,7 +1229,8 @@ static bool is_leaf_function(u64 rip)
|
|||||||
|
|
||||||
static LONG exception_handler(PEXCEPTION_POINTERS pExp)
|
static LONG exception_handler(PEXCEPTION_POINTERS pExp)
|
||||||
{
|
{
|
||||||
const u64 addr64 = pExp->ExceptionRecord->ExceptionInformation[1] - (u64)vm::base(0);
|
const u64 addr64 = pExp->ExceptionRecord->ExceptionInformation[1] - (u64)vm::g_base_addr;
|
||||||
|
const u64 exec64 = pExp->ExceptionRecord->ExceptionInformation[1] - (u64)vm::g_exec_addr;
|
||||||
const bool is_writing = pExp->ExceptionRecord->ExceptionInformation[0] != 0;
|
const bool is_writing = pExp->ExceptionRecord->ExceptionInformation[0] != 0;
|
||||||
|
|
||||||
if (pExp->ExceptionRecord->ExceptionCode == EXCEPTION_ACCESS_VIOLATION && addr64 < 0x100000000ull)
|
if (pExp->ExceptionRecord->ExceptionCode == EXCEPTION_ACCESS_VIOLATION && addr64 < 0x100000000ull)
|
||||||
@ -1240,6 +1241,14 @@ static LONG exception_handler(PEXCEPTION_POINTERS pExp)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (pExp->ExceptionRecord->ExceptionCode == EXCEPTION_ACCESS_VIOLATION && exec64 < 0x100000000ull)
|
||||||
|
{
|
||||||
|
if (thread_ctrl::get_current() && handle_access_violation((u32)exec64, is_writing, pExp->ContextRecord))
|
||||||
|
{
|
||||||
|
return EXCEPTION_CONTINUE_EXECUTION;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return EXCEPTION_CONTINUE_SEARCH;
|
return EXCEPTION_CONTINUE_SEARCH;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1249,7 +1258,6 @@ static LONG exception_filter(PEXCEPTION_POINTERS pExp)
|
|||||||
|
|
||||||
if (pExp->ExceptionRecord->ExceptionCode == EXCEPTION_ACCESS_VIOLATION)
|
if (pExp->ExceptionRecord->ExceptionCode == EXCEPTION_ACCESS_VIOLATION)
|
||||||
{
|
{
|
||||||
const u64 addr64 = pExp->ExceptionRecord->ExceptionInformation[1] - (u64)vm::base(0);
|
|
||||||
const auto cause = pExp->ExceptionRecord->ExceptionInformation[0] != 0 ? "writing" : "reading";
|
const auto cause = pExp->ExceptionRecord->ExceptionInformation[0] != 0 ? "writing" : "reading";
|
||||||
|
|
||||||
msg += fmt::format("Segfault %s location %p at %p.\n", cause, pExp->ExceptionRecord->ExceptionInformation[1], pExp->ExceptionRecord->ExceptionAddress);
|
msg += fmt::format("Segfault %s location %p at %p.\n", cause, pExp->ExceptionRecord->ExceptionInformation[1], pExp->ExceptionRecord->ExceptionAddress);
|
||||||
@ -1360,7 +1368,8 @@ static void signal_handler(int sig, siginfo_t* info, void* uct)
|
|||||||
const bool is_writing = context->uc_mcontext.gregs[REG_ERR] & 0x2;
|
const bool is_writing = context->uc_mcontext.gregs[REG_ERR] & 0x2;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
const u64 addr64 = (u64)info->si_addr - (u64)vm::base(0);
|
const u64 addr64 = (u64)info->si_addr - (u64)vm::g_base_addr;
|
||||||
|
const u64 exec64 = (u64)info->si_addr - (u64)vm::g_exec_addr;
|
||||||
const auto cause = is_writing ? "writing" : "reading";
|
const auto cause = is_writing ? "writing" : "reading";
|
||||||
|
|
||||||
if (addr64 < 0x100000000ull)
|
if (addr64 < 0x100000000ull)
|
||||||
@ -1372,6 +1381,14 @@ static void signal_handler(int sig, siginfo_t* info, void* uct)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (exec64 < 0x100000000ull)
|
||||||
|
{
|
||||||
|
if (thread_ctrl::get_current() && handle_access_violation((u32)exec64, is_writing, context))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// TODO (debugger interaction)
|
// TODO (debugger interaction)
|
||||||
report_fatal_error(fmt::format("Segfault %s location %p at %p.", cause, info->si_addr, RIP(context)));
|
report_fatal_error(fmt::format("Segfault %s location %p at %p.", cause, info->si_addr, RIP(context)));
|
||||||
std::abort();
|
std::abort();
|
||||||
|
@ -106,11 +106,10 @@ extern void ppu_initialize();
|
|||||||
extern void ppu_initialize(const ppu_module& info);
|
extern void ppu_initialize(const ppu_module& info);
|
||||||
extern void ppu_execute_syscall(ppu_thread& ppu, u64 code);
|
extern void ppu_execute_syscall(ppu_thread& ppu, u64 code);
|
||||||
|
|
||||||
const auto s_ppu_compiled = static_cast<u32*>(utils::memory_reserve(0x100000000));
|
// Get pointer to executable cache
|
||||||
|
static u32& ppu_ref(u32 addr)
|
||||||
extern void ppu_finalize()
|
|
||||||
{
|
{
|
||||||
utils::memory_decommit(s_ppu_compiled, 0x100000000);
|
return *reinterpret_cast<u32*>(vm::g_exec_addr + addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get interpreter cache value
|
// Get interpreter cache value
|
||||||
@ -132,7 +131,7 @@ static bool ppu_fallback(ppu_thread& ppu, ppu_opcode_t op)
|
|||||||
fmt::throw_exception("Unregistered PPU function [0x%08x]", ppu.cia);
|
fmt::throw_exception("Unregistered PPU function [0x%08x]", ppu.cia);
|
||||||
}
|
}
|
||||||
|
|
||||||
s_ppu_compiled[ppu.cia / 4] = ppu_cache(ppu.cia);
|
ppu_ref(ppu.cia) = ppu_cache(ppu.cia);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -145,13 +144,13 @@ extern void ppu_register_range(u32 addr, u32 size)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Register executable range at
|
// Register executable range at
|
||||||
utils::memory_commit(s_ppu_compiled + addr / 4, size);
|
utils::memory_commit(&ppu_ref(addr), size);
|
||||||
|
|
||||||
const u32 fallback = ::narrow<u32>(reinterpret_cast<std::uintptr_t>(ppu_fallback));
|
const u32 fallback = ::narrow<u32>(reinterpret_cast<std::uintptr_t>(ppu_fallback));
|
||||||
|
|
||||||
while (size)
|
while (size)
|
||||||
{
|
{
|
||||||
s_ppu_compiled[addr / 4] = fallback;
|
ppu_ref(addr) = fallback;
|
||||||
addr += 4;
|
addr += 4;
|
||||||
size -= 4;
|
size -= 4;
|
||||||
}
|
}
|
||||||
@ -162,7 +161,7 @@ extern void ppu_register_function_at(u32 addr, u32 size, ppu_function_t ptr)
|
|||||||
// Initialize specific function
|
// Initialize specific function
|
||||||
if (ptr)
|
if (ptr)
|
||||||
{
|
{
|
||||||
s_ppu_compiled[addr / 4] = ::narrow<u32>(reinterpret_cast<std::uintptr_t>(ptr));
|
ppu_ref(addr) = ::narrow<u32>(reinterpret_cast<std::uintptr_t>(ptr));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -182,9 +181,9 @@ extern void ppu_register_function_at(u32 addr, u32 size, ppu_function_t ptr)
|
|||||||
|
|
||||||
while (size)
|
while (size)
|
||||||
{
|
{
|
||||||
if (s_ppu_compiled[addr / 4] == fallback)
|
if (ppu_ref(addr) == fallback)
|
||||||
{
|
{
|
||||||
s_ppu_compiled[addr / 4] = ppu_cache(addr);
|
ppu_ref(addr) = ppu_cache(addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
addr += 4;
|
addr += 4;
|
||||||
@ -220,15 +219,15 @@ extern void ppu_breakpoint(u32 addr)
|
|||||||
|
|
||||||
const auto _break = ::narrow<u32>(reinterpret_cast<std::uintptr_t>(&ppu_break));
|
const auto _break = ::narrow<u32>(reinterpret_cast<std::uintptr_t>(&ppu_break));
|
||||||
|
|
||||||
if (s_ppu_compiled[addr / 4] == _break)
|
if (ppu_ref(addr) == _break)
|
||||||
{
|
{
|
||||||
// Remove breakpoint
|
// Remove breakpoint
|
||||||
s_ppu_compiled[addr / 4] = ppu_cache(addr);
|
ppu_ref(addr) = ppu_cache(addr);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Set breakpoint
|
// Set breakpoint
|
||||||
s_ppu_compiled[addr / 4] = _break;
|
ppu_ref(addr) = _break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -391,12 +390,12 @@ void ppu_thread::exec_task()
|
|||||||
{
|
{
|
||||||
if (g_cfg_ppu_decoder.get() == ppu_decoder_type::llvm)
|
if (g_cfg_ppu_decoder.get() == ppu_decoder_type::llvm)
|
||||||
{
|
{
|
||||||
reinterpret_cast<ppu_function_t>(static_cast<std::uintptr_t>(s_ppu_compiled[cia / 4]))(*this);
|
reinterpret_cast<ppu_function_t>(static_cast<std::uintptr_t>(ppu_ref(cia)))(*this);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto base = vm::_ptr<const u8>(0);
|
const auto base = vm::_ptr<const u8>(0);
|
||||||
const auto cache = reinterpret_cast<const u8*>(s_ppu_compiled);
|
const auto cache = vm::g_exec_addr;
|
||||||
const auto bswap4 = _mm_set_epi8(12, 13, 14, 15, 8, 9, 10, 11, 4, 5, 6, 7, 0, 1, 2, 3);
|
const auto bswap4 = _mm_set_epi8(12, 13, 14, 15, 8, 9, 10, 11, 4, 5, 6, 7, 0, 1, 2, 3);
|
||||||
|
|
||||||
v128 _op;
|
v128 _op;
|
||||||
@ -411,7 +410,7 @@ void ppu_thread::exec_task()
|
|||||||
|
|
||||||
// Decode single instruction (may be step)
|
// Decode single instruction (may be step)
|
||||||
const u32 op = *reinterpret_cast<const be_t<u32>*>(base + cia);
|
const u32 op = *reinterpret_cast<const be_t<u32>*>(base + cia);
|
||||||
if (reinterpret_cast<func_t>((std::uintptr_t)s_ppu_compiled[cia / 4])(*this, {op})) { cia += 4; }
|
if (reinterpret_cast<func_t>((std::uintptr_t)ppu_ref(cia))(*this, {op})) { cia += 4; }
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -419,7 +418,7 @@ void ppu_thread::exec_task()
|
|||||||
{
|
{
|
||||||
// Unaligned
|
// Unaligned
|
||||||
const u32 op = *reinterpret_cast<const be_t<u32>*>(base + cia);
|
const u32 op = *reinterpret_cast<const be_t<u32>*>(base + cia);
|
||||||
if (reinterpret_cast<func_t>((std::uintptr_t)s_ppu_compiled[cia / 4])(*this, {op})) { cia += 4; }
|
if (reinterpret_cast<func_t>((std::uintptr_t)ppu_ref(cia))(*this, {op})) { cia += 4; }
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -878,7 +877,7 @@ extern void ppu_initialize(const ppu_module& info)
|
|||||||
std::unordered_map<std::string, std::uintptr_t> link_table
|
std::unordered_map<std::string, std::uintptr_t> link_table
|
||||||
{
|
{
|
||||||
{ "__mptr", (u64)&vm::g_base_addr },
|
{ "__mptr", (u64)&vm::g_base_addr },
|
||||||
{ "__cptr", (u64)&s_ppu_compiled },
|
{ "__cptr", (u64)&vm::g_exec_addr },
|
||||||
{ "__trap", (u64)&ppu_trap },
|
{ "__trap", (u64)&ppu_trap },
|
||||||
{ "__end", (u64)&ppu_unreachable },
|
{ "__end", (u64)&ppu_unreachable },
|
||||||
{ "__check", (u64)&ppu_check },
|
{ "__check", (u64)&ppu_check },
|
||||||
@ -957,8 +956,8 @@ extern void ppu_initialize(const ppu_module& info)
|
|||||||
{
|
{
|
||||||
if (func.size)
|
if (func.size)
|
||||||
{
|
{
|
||||||
const std::uintptr_t link = jit->get(fmt::format("__0x%x", func.addr));
|
const std::uintptr_t uptr = jit->get(fmt::format("__0x%x", func.addr));
|
||||||
s_ppu_compiled[func.addr / 4] = ::narrow<u32>(link);
|
ppu_ref(func.addr) = ::narrow<u32>(uptr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1133,8 +1132,8 @@ extern void ppu_initialize(const ppu_module& info)
|
|||||||
{
|
{
|
||||||
if (func.size)
|
if (func.size)
|
||||||
{
|
{
|
||||||
const std::uintptr_t link = jit->get(fmt::format("__0x%x", func.addr));
|
const std::uintptr_t uptr = jit->get(fmt::format("__0x%x", func.addr));
|
||||||
s_ppu_compiled[func.addr / 4] = ::narrow<u32>(link);
|
ppu_ref(func.addr) = ::narrow<u32>(uptr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -27,8 +27,25 @@
|
|||||||
|
|
||||||
namespace vm
|
namespace vm
|
||||||
{
|
{
|
||||||
// Emulated virtual memory (4 GiB)
|
static u8* memory_reserve_4GiB(std::uintptr_t addr = 0)
|
||||||
u8* const g_base_addr = static_cast<u8*>(utils::memory_reserve(0x100000000));
|
{
|
||||||
|
for (u64 addr = 0x100000000;; addr += 0x100000000)
|
||||||
|
{
|
||||||
|
if (auto ptr = utils::memory_reserve(0x100000000, (void*)addr))
|
||||||
|
{
|
||||||
|
return static_cast<u8*>(ptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: a condition to break loop
|
||||||
|
return static_cast<u8*>(utils::memory_reserve(0x100000000));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Emulated virtual memory
|
||||||
|
u8* const g_base_addr = memory_reserve_4GiB(0);
|
||||||
|
|
||||||
|
// Auxiliary virtual memory for executable areas
|
||||||
|
u8* const g_exec_addr = memory_reserve_4GiB((std::uintptr_t)g_base_addr);
|
||||||
|
|
||||||
// Memory locations
|
// Memory locations
|
||||||
std::vector<std::shared_ptr<block_t>> g_locations;
|
std::vector<std::shared_ptr<block_t>> g_locations;
|
||||||
@ -805,6 +822,7 @@ namespace vm
|
|||||||
g_locations.clear();
|
g_locations.clear();
|
||||||
|
|
||||||
utils::memory_decommit(g_base_addr, 0x100000000);
|
utils::memory_decommit(g_base_addr, 0x100000000);
|
||||||
|
utils::memory_decommit(g_exec_addr, 0x100000000);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10,6 +10,7 @@ class cpu_thread;
|
|||||||
namespace vm
|
namespace vm
|
||||||
{
|
{
|
||||||
extern u8* const g_base_addr;
|
extern u8* const g_base_addr;
|
||||||
|
extern u8* const g_exec_addr;
|
||||||
|
|
||||||
enum memory_location_t : uint
|
enum memory_location_t : uint
|
||||||
{
|
{
|
||||||
|
@ -50,7 +50,6 @@ extern void ppu_load_exec(const ppu_exec_object&);
|
|||||||
extern void spu_load_exec(const spu_exec_object&);
|
extern void spu_load_exec(const spu_exec_object&);
|
||||||
extern void arm_load_exec(const arm_exec_object&);
|
extern void arm_load_exec(const arm_exec_object&);
|
||||||
extern std::shared_ptr<struct lv2_prx> ppu_load_prx(const ppu_prx_object&, const std::string&);
|
extern std::shared_ptr<struct lv2_prx> ppu_load_prx(const ppu_prx_object&, const std::string&);
|
||||||
extern void ppu_finalize();
|
|
||||||
|
|
||||||
fs::file g_tty;
|
fs::file g_tty;
|
||||||
|
|
||||||
@ -525,7 +524,6 @@ void Emulator::Stop()
|
|||||||
|
|
||||||
RSXIOMem.Clear();
|
RSXIOMem.Clear();
|
||||||
vm::close();
|
vm::close();
|
||||||
ppu_finalize();
|
|
||||||
|
|
||||||
if (g_cfg_autoexit)
|
if (g_cfg_autoexit)
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user