mirror of
				https://git.zaroz.cloud/nintendo-back-up/yuzu/yuzu-mainline.git
				synced 2025-03-21 01:53:15 +00:00 
			
		
		
		
	Merge pull request #751 from Subv/tpidr_el0
CPU: Save and restore the TPIDR_EL0 system register on every context switch
This commit is contained in:
		
						commit
						fe2498a650
					
				@ -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;
 | 
			
		||||
 | 
			
		||||
@ -312,6 +312,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
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user