XThread Save: Handle emulated instructions/MMIO/etc that call out of guest code

This commit is contained in:
Dr. Chat 2015-12-02 13:56:51 -06:00 committed by Ben Vanik
parent 785824531c
commit 442f063ddf
1 changed files with 21 additions and 2 deletions

View File

@ -924,12 +924,17 @@ uint32_t XThread::StepToSafePoint() {
// we are. // we are.
cpu::GuestFunction* thunk_func = nullptr; cpu::GuestFunction* thunk_func = nullptr;
cpu::Export* export_data = nullptr; cpu::Export* export_data = nullptr;
uint32_t first_pc = 0;
for (int i = 0; i < count; i++) { for (int i = 0; i < count; i++) {
auto& frame = cpu_frames[i]; auto& frame = cpu_frames[i];
if (frame.type == cpu::StackFrame::Type::kGuest && frame.guest_pc) { if (frame.type == cpu::StackFrame::Type::kGuest && frame.guest_pc) {
auto func = frame.guest_symbol.function; auto func = frame.guest_symbol.function;
assert_true(func->is_guest()); assert_true(func->is_guest());
if (!first_pc) {
first_pc = frame.guest_pc;
}
thunk_func = reinterpret_cast<cpu::GuestFunction*>(func); thunk_func = reinterpret_cast<cpu::GuestFunction*>(func);
export_data = thunk_func->export_data(); export_data = thunk_func->export_data();
if (export_data) { if (export_data) {
@ -947,8 +952,22 @@ uint32_t XThread::StepToSafePoint() {
// Non-blocking. Run until we return from the thunk. // Non-blocking. Run until we return from the thunk.
StepToAddress(uint32_t(thread_state_->context()->lr)); StepToAddress(uint32_t(thread_state_->context()->lr));
} else { } else {
// We're in the MMIO handler or something. TODO. // We're in the MMIO handler/mfmsr/something calling out of the guest
assert_always(); // that doesn't use an export. If the current instruction is
// synchronizing, we can just save here. Otherwise, step forward
// (and call ourselves again so we run the correct logic).
cpu::frontend::InstrData i;
i.address = first_pc;
i.code = xe::load_and_swap<uint32_t>(memory()->TranslateVirtual(first_pc));
i.type = cpu::frontend::GetInstrType(i.code);
if (i.type->type & cpu::frontend::kXEPPCInstrTypeSynchronizeContext) {
// Good to go.
return first_pc;
} else {
// Step forward.
StepToAddress(first_pc + 4);
StepToSafePoint();
}
} }
} }