mirror of
https://github.com/Vita3K/Vita3K.git
synced 2026-07-11 01:34:23 +02:00
cpu: move halt instruction block to KernelState, shared across all threads
Each thread was allocating its own identical 4-byte NOP+WFI block. Since all threads point LR at the same sentinel, one allocation in KernelState is sufficient. Note that this is a Dynarmic-specific "hack" to make it stop execution (`jit->Run()`) after the guest code returns (jumps back LR): - Prior JIT execution, we prepare LR to point to this NOP+WFI block. - When the guest function returns, it will jump into this NOP+WFI block and `Dynarmic::A32::Exception::WaitForInterrupt` will be called. Then we call `cpu->jit->HaltExecution()` which will make `jit->Run()` return
This commit is contained in:
@@ -19,7 +19,6 @@
|
||||
|
||||
#include <cpu/common.h>
|
||||
#include <cpu/disasm/state.h>
|
||||
#include <mem/block.h>
|
||||
#include <mem/state.h>
|
||||
#include <util/types.h>
|
||||
|
||||
@@ -32,9 +31,6 @@ struct CPUState {
|
||||
MemState *mem = nullptr;
|
||||
DisasmState disasm;
|
||||
|
||||
Block halt_instruction;
|
||||
Address halt_instruction_pc; // thumb mode pc
|
||||
|
||||
CPUInterfacePtr cpu;
|
||||
bool svc_called;
|
||||
uint32_t svc;
|
||||
|
||||
@@ -43,14 +43,6 @@ CPUStatePtr init_cpu(bool cpu_opt, SceUID thread_id, std::size_t processor_id, M
|
||||
state->mem = &mem;
|
||||
state->thread_id = thread_id;
|
||||
|
||||
// TODO: we can move this to kernel after we drop unicorn
|
||||
// unicorn is unable to detect whether the exit was because of halt or not
|
||||
state->halt_instruction = alloc_block(mem, 4, "halt_instruction");
|
||||
const auto halt_ptr = state->halt_instruction.get_ptr<uint16_t>();
|
||||
*halt_ptr.get(mem) = 0xBF00; // NOP
|
||||
*(halt_ptr.get(mem) + 1) = 0xBF30; // WFI
|
||||
state->halt_instruction_pc = state->halt_instruction.get() | 1;
|
||||
|
||||
if (!init(state->disasm)) {
|
||||
return CPUStatePtr();
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#include <kernel/sync_primitives.h>
|
||||
#include <kernel/types.h>
|
||||
#include <mem/allocator.h>
|
||||
#include <mem/block.h>
|
||||
#include <mem/ptr.h>
|
||||
#include <mem/util.h>
|
||||
#include <rtc/rtc.h>
|
||||
@@ -136,6 +137,10 @@ struct KernelState {
|
||||
CorenumAllocator corenum_allocator;
|
||||
CallImportFunc call_import;
|
||||
|
||||
// Shared NOP+WFI sentinel used by the Dynarmic as the halt return address
|
||||
Block halt_instruction;
|
||||
Address halt_instruction_pc;
|
||||
|
||||
ObjectStore obj_store;
|
||||
|
||||
uint64_t start_tick;
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
|
||||
#include <cpu/common.h>
|
||||
#include <kernel/state.h>
|
||||
#include <mem/functions.h>
|
||||
|
||||
#include <kernel/thread/thread_state.h>
|
||||
|
||||
@@ -90,6 +91,13 @@ bool KernelState::init(MemState &mem, const CallImportFunc &call_import, bool cp
|
||||
this->call_import = call_import;
|
||||
this->cpu_opt = cpu_opt;
|
||||
|
||||
// Generate halt instruction (NOP + WFI)
|
||||
halt_instruction = alloc_block(mem, 4, "halt_instruction");
|
||||
const auto halt_ptr = halt_instruction.get_ptr<uint16_t>().get(mem);
|
||||
halt_ptr[0] = 0xBF00; // NOP
|
||||
halt_ptr[1] = 0xBF30; // WFI
|
||||
halt_instruction_pc = halt_instruction.get() | 1; // thumb mode pc
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -138,7 +138,7 @@ int ThreadState::start(SceSize arglen, const Ptr<void> argp, bool run_entry_call
|
||||
call_level = 1;
|
||||
load_context(*cpu, init_cpu_ctx);
|
||||
write_pc(*cpu, entry_point);
|
||||
write_lr(*cpu, cpu->halt_instruction_pc);
|
||||
write_lr(*cpu, kernel.halt_instruction_pc);
|
||||
write_reg(*cpu, 0, arglen);
|
||||
|
||||
// Copy data to stack
|
||||
@@ -365,7 +365,7 @@ uint32_t ThreadState::run_callback(Address callback_address, const std::vector<u
|
||||
call_level++;
|
||||
// we shouldn't have to clean the context I believe
|
||||
write_pc(*cpu, callback_address);
|
||||
write_lr(*cpu, cpu->halt_instruction_pc);
|
||||
write_lr(*cpu, kernel.halt_instruction_pc);
|
||||
push_arguments(args);
|
||||
thread_lock.unlock();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user