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
8 changed files with 39 additions and 0 deletions
|
@ -104,6 +104,10 @@ public:
|
||||||
|
|
||||||
virtual void SetTlsAddress(VAddr address) = 0;
|
virtual void SetTlsAddress(VAddr address) = 0;
|
||||||
|
|
||||||
|
virtual u64 GetTPIDR_EL0() const = 0;
|
||||||
|
|
||||||
|
virtual void SetTPIDR_EL0(u64 value) = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Saves the current CPU context
|
* Saves the current CPU context
|
||||||
* @param ctx Thread context to save
|
* @param ctx Thread context to save
|
||||||
|
|
|
@ -196,6 +196,14 @@ void ARM_Dynarmic::SetTlsAddress(u64 address) {
|
||||||
cb->tpidrro_el0 = 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) {
|
void ARM_Dynarmic::SaveContext(ARM_Interface::ThreadContext& ctx) {
|
||||||
ctx.cpu_registers = jit->GetRegisters();
|
ctx.cpu_registers = jit->GetRegisters();
|
||||||
ctx.sp = jit->GetSP();
|
ctx.sp = jit->GetSP();
|
||||||
|
|
|
@ -34,6 +34,8 @@ public:
|
||||||
void SetCPSR(u32 cpsr) override;
|
void SetCPSR(u32 cpsr) override;
|
||||||
VAddr GetTlsAddress() const override;
|
VAddr GetTlsAddress() const override;
|
||||||
void SetTlsAddress(VAddr address) override;
|
void SetTlsAddress(VAddr address) override;
|
||||||
|
void SetTPIDR_EL0(u64 value) override;
|
||||||
|
u64 GetTPIDR_EL0() const override;
|
||||||
|
|
||||||
void SaveContext(ThreadContext& ctx) override;
|
void SaveContext(ThreadContext& ctx) override;
|
||||||
void LoadContext(const 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));
|
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() {
|
void ARM_Unicorn::Run() {
|
||||||
if (GDBStub::IsServerEnabled()) {
|
if (GDBStub::IsServerEnabled()) {
|
||||||
ExecuteInstructions(std::max(4000000, 0));
|
ExecuteInstructions(std::max(4000000, 0));
|
||||||
|
|
|
@ -28,6 +28,8 @@ public:
|
||||||
void SetCPSR(u32 cpsr) override;
|
void SetCPSR(u32 cpsr) override;
|
||||||
VAddr GetTlsAddress() const override;
|
VAddr GetTlsAddress() const override;
|
||||||
void SetTlsAddress(VAddr address) override;
|
void SetTlsAddress(VAddr address) override;
|
||||||
|
void SetTPIDR_EL0(u64 value) override;
|
||||||
|
u64 GetTPIDR_EL0() const override;
|
||||||
void SaveContext(ThreadContext& ctx) override;
|
void SaveContext(ThreadContext& ctx) override;
|
||||||
void LoadContext(const ThreadContext& ctx) override;
|
void LoadContext(const ThreadContext& ctx) override;
|
||||||
void PrepareReschedule() override;
|
void PrepareReschedule() override;
|
||||||
|
|
|
@ -56,6 +56,8 @@ void Scheduler::SwitchContext(Thread* new_thread) {
|
||||||
if (previous_thread) {
|
if (previous_thread) {
|
||||||
previous_thread->last_running_ticks = CoreTiming::GetTicks();
|
previous_thread->last_running_ticks = CoreTiming::GetTicks();
|
||||||
cpu_core->SaveContext(previous_thread->context);
|
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) {
|
if (previous_thread->status == THREADSTATUS_RUNNING) {
|
||||||
// This is only the case when a reschedule is triggered without the current thread
|
// 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->LoadContext(new_thread->context);
|
||||||
cpu_core->SetTlsAddress(new_thread->GetTLSAddress());
|
cpu_core->SetTlsAddress(new_thread->GetTLSAddress());
|
||||||
|
cpu_core->SetTPIDR_EL0(new_thread->GetTPIDR_EL0());
|
||||||
cpu_core->ClearExclusiveState();
|
cpu_core->ClearExclusiveState();
|
||||||
} else {
|
} else {
|
||||||
current_thread = nullptr;
|
current_thread = nullptr;
|
||||||
|
|
|
@ -313,6 +313,7 @@ ResultVal<SharedPtr<Thread>> Thread::Create(std::string name, VAddr entry_point,
|
||||||
thread->status = THREADSTATUS_DORMANT;
|
thread->status = THREADSTATUS_DORMANT;
|
||||||
thread->entry_point = entry_point;
|
thread->entry_point = entry_point;
|
||||||
thread->stack_top = stack_top;
|
thread->stack_top = stack_top;
|
||||||
|
thread->tpidr_el0 = 0;
|
||||||
thread->nominal_priority = thread->current_priority = priority;
|
thread->nominal_priority = thread->current_priority = priority;
|
||||||
thread->last_running_ticks = CoreTiming::GetTicks();
|
thread->last_running_ticks = CoreTiming::GetTicks();
|
||||||
thread->processor_id = processor_id;
|
thread->processor_id = processor_id;
|
||||||
|
|
|
@ -182,6 +182,14 @@ public:
|
||||||
return tls_address;
|
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 the address of the current thread's command buffer, located in the TLS.
|
||||||
* @returns VAddr of the thread's command buffer.
|
* @returns VAddr of the thread's command buffer.
|
||||||
|
@ -213,6 +221,7 @@ public:
|
||||||
s32 processor_id;
|
s32 processor_id;
|
||||||
|
|
||||||
VAddr tls_address; ///< Virtual address of the Thread Local Storage of the thread
|
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
|
SharedPtr<Process> owner_process; ///< Process that owns this thread
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue