CPU: Save and restore the TPIDR_EL0 system register on every context switch.
Note that there's currently a dynarmic bug preventing this register from being written.
This commit is contained in:
parent
f36affdbe3
commit
d84eb9dac6
|
@ -104,6 +104,10 @@ public:
|
|||
|
||||
virtual void SetTlsAddress(VAddr address) = 0;
|
||||
|
||||
virtual u64 GetTPIDR_EL0() const = 0;
|
||||
|
||||
virtual void SetTPIDR_EL0(u64 value) = 0;
|
||||
|
||||
/**
|
||||
* Saves the current CPU context
|
||||
* @param ctx Thread context to save
|
||||
|
|
|
@ -196,6 +196,14 @@ void ARM_Dynarmic::SetTlsAddress(u64 address) {
|
|||
cb->tpidrro_el0 = address;
|
||||
}
|
||||
|
||||
u64 ARM_Dynarmic::GetTPIDR_EL0() const {
|
||||
return cb->tpidr_el0;
|
||||
}
|
||||
|
||||
void ARM_Dynarmic::SetTPIDR_EL0(u64 value) {
|
||||
cb->tpidr_el0 = value;
|
||||
}
|
||||
|
||||
void ARM_Dynarmic::SaveContext(ARM_Interface::ThreadContext& ctx) {
|
||||
ctx.cpu_registers = jit->GetRegisters();
|
||||
ctx.sp = jit->GetSP();
|
||||
|
|
|
@ -34,6 +34,8 @@ public:
|
|||
void SetCPSR(u32 cpsr) override;
|
||||
VAddr GetTlsAddress() const override;
|
||||
void SetTlsAddress(VAddr address) override;
|
||||
void SetTPIDR_EL0(u64 value) override;
|
||||
u64 GetTPIDR_EL0() const override;
|
||||
|
||||
void SaveContext(ThreadContext& ctx) override;
|
||||
void LoadContext(const ThreadContext& ctx) override;
|
||||
|
|
|
@ -169,6 +169,16 @@ void ARM_Unicorn::SetTlsAddress(VAddr base) {
|
|||
CHECKED(uc_reg_write(uc, UC_ARM64_REG_TPIDRRO_EL0, &base));
|
||||
}
|
||||
|
||||
u64 ARM_Unicorn::GetTPIDR_EL0() const {
|
||||
u64 value{};
|
||||
CHECKED(uc_reg_read(uc, UC_ARM64_REG_TPIDR_EL0, &value));
|
||||
return value;
|
||||
}
|
||||
|
||||
void ARM_Unicorn::SetTPIDR_EL0(u64 value) {
|
||||
CHECKED(uc_reg_write(uc, UC_ARM64_REG_TPIDR_EL0, &value));
|
||||
}
|
||||
|
||||
void ARM_Unicorn::Run() {
|
||||
if (GDBStub::IsServerEnabled()) {
|
||||
ExecuteInstructions(std::max(4000000, 0));
|
||||
|
|
|
@ -28,6 +28,8 @@ public:
|
|||
void SetCPSR(u32 cpsr) override;
|
||||
VAddr GetTlsAddress() const override;
|
||||
void SetTlsAddress(VAddr address) override;
|
||||
void SetTPIDR_EL0(u64 value) override;
|
||||
u64 GetTPIDR_EL0() const override;
|
||||
void SaveContext(ThreadContext& ctx) override;
|
||||
void LoadContext(const ThreadContext& ctx) override;
|
||||
void PrepareReschedule() override;
|
||||
|
|
|
@ -56,6 +56,8 @@ void Scheduler::SwitchContext(Thread* new_thread) {
|
|||
if (previous_thread) {
|
||||
previous_thread->last_running_ticks = CoreTiming::GetTicks();
|
||||
cpu_core->SaveContext(previous_thread->context);
|
||||
// Save the TPIDR_EL0 system register in case it was modified.
|
||||
previous_thread->tpidr_el0 = cpu_core->GetTPIDR_EL0();
|
||||
|
||||
if (previous_thread->status == THREADSTATUS_RUNNING) {
|
||||
// This is only the case when a reschedule is triggered without the current thread
|
||||
|
@ -87,6 +89,7 @@ void Scheduler::SwitchContext(Thread* new_thread) {
|
|||
|
||||
cpu_core->LoadContext(new_thread->context);
|
||||
cpu_core->SetTlsAddress(new_thread->GetTLSAddress());
|
||||
cpu_core->SetTPIDR_EL0(new_thread->GetTPIDR_EL0());
|
||||
cpu_core->ClearExclusiveState();
|
||||
} else {
|
||||
current_thread = nullptr;
|
||||
|
|
|
@ -313,6 +313,7 @@ ResultVal<SharedPtr<Thread>> Thread::Create(std::string name, VAddr entry_point,
|
|||
thread->status = THREADSTATUS_DORMANT;
|
||||
thread->entry_point = entry_point;
|
||||
thread->stack_top = stack_top;
|
||||
thread->tpidr_el0 = 0;
|
||||
thread->nominal_priority = thread->current_priority = priority;
|
||||
thread->last_running_ticks = CoreTiming::GetTicks();
|
||||
thread->processor_id = processor_id;
|
||||
|
|
|
@ -182,6 +182,14 @@ public:
|
|||
return tls_address;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the value of the TPIDR_EL0 Read/Write system register for this thread.
|
||||
* @returns The value of the TPIDR_EL0 register.
|
||||
*/
|
||||
u64 GetTPIDR_EL0() const {
|
||||
return tpidr_el0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the address of the current thread's command buffer, located in the TLS.
|
||||
* @returns VAddr of the thread's command buffer.
|
||||
|
@ -213,6 +221,7 @@ public:
|
|||
s32 processor_id;
|
||||
|
||||
VAddr tls_address; ///< Virtual address of the Thread Local Storage of the thread
|
||||
u64 tpidr_el0; ///< TPIDR_EL0 read/write system register.
|
||||
|
||||
SharedPtr<Process> owner_process; ///< Process that owns this thread
|
||||
|
||||
|
|
Reference in New Issue