diff --git a/sys/powerpc/powerpc/swtch64.S b/sys/powerpc/powerpc/swtch64.S index e5b03dce483..4efc0f13386 100644 --- a/sys/powerpc/powerpc/swtch64.S +++ b/sys/powerpc/powerpc/swtch64.S @@ -76,8 +76,14 @@ TOC_ENTRY(blocked_lock) * void cpu_throw(struct thread *old, struct thread *new) */ ENTRY(cpu_throw) + cmpdi %r3,0 + bne 1f + mr %r3, %r13 /* Use curthread if 'old' is NULL */ +1: mr %r13, %r4 li %r14,0 /* Tell cpu_switchin not to release a thread */ + ld %r6,TD_PCB(%r3) + ld %r18,PCB_FLAGS(%r6) b cpu_switchin @@ -87,6 +93,10 @@ ENTRY(cpu_throw) * struct mutex *mtx); * * Switch to a new thread saving the current state in the old thread. + * + * Internally clobbers (not visible outside of this file): + * r18 - old thread pcb_flags + * r19 - new thread pcb_flags */ ENTRY(cpu_switch) ld %r6,TD_PCB(%r3) /* Get the old thread's PCB ptr */ @@ -125,26 +135,29 @@ ENTRY(cpu_switch) stdu %r1,-48(%r1) - lwz %r7, PCB_FLAGS(%r17) - andi. %r7, %r7, PCB_CDSCR + lwz %r18, PCB_FLAGS(%r17) + andi. %r7, %r18, PCB_CFSCR + beq 1f + mfspr %r6, SPR_FSCR + std %r6, PCB_FSCR(%r17) +1: + andi. %r7, %r18, PCB_CDSCR beq .L0 /* Custom DSCR was set. Reseting it to enter kernel */ - li %r7, 0x0 - mtspr SPR_DSCR, %r7 + mfspr %r6, SPR_DSCR + std %r6, PCB_DSCR(%r17) .L0: - lwz %r7,PCB_FLAGS(%r17) /* Save FPU context if needed */ - andi. %r7, %r7, PCB_FPU + andi. %r7, %r18, PCB_FPU beq .L1 bl save_fpu nop .L1: mr %r3,%r14 /* restore old thread ptr */ - lwz %r7,PCB_FLAGS(%r17) /* Save Altivec context if needed */ - andi. %r7, %r7, PCB_VEC + andi. %r7, %r18, PCB_VEC beq .L2 bl save_vec nop @@ -186,30 +199,47 @@ blocked_loop: bl pmap_activate /* Activate the new address space */ nop - lwz %r6, PCB_FLAGS(%r17) + lwz %r19, PCB_FLAGS(%r17) /* Restore FPU context if needed */ - andi. %r6, %r6, PCB_FPU + andi. %r6, %r19, PCB_FPU beq .L3 mr %r3,%r13 /* Pass curthread to enable_fpu */ bl enable_fpu nop .L3: - lwz %r6, PCB_FLAGS(%r17) /* Restore Altivec context if needed */ - andi. %r6, %r6, PCB_VEC - beq .L31 + andi. %r6, %r19, PCB_VEC + beq .L30 mr %r3,%r13 /* Pass curthread to enable_vec */ bl enable_vec nop +.L30: + /* Load custom DSCR on PowerISA 2.06+ CPUs. */ + /* Load updated FSCR on PowerISA 2.07+ CPUs. */ + /* If these bits are set in the new PCB, don't zero the regs. */ + andc %r18,%r18,%r19 + andi. %r6, %r18, PCB_CDSCR + /* If no custom DSCR, we know there's no change to FSCR right now. */ + beq .L31 + li %r3, 0 + mtspr SPR_DSCR, %r3 + andi. %r6, %r18, PCB_CFSCR + beq .L31 + mtspr SPR_FSCR, %r3 .L31: - lwz %r6, PCB_FLAGS(%r17) /* Restore Custom DSCR if needed */ - andi. %r6, %r6, PCB_CDSCR - beq .L4 + andi. %r6, %r19, PCB_CDSCR + beq .L32 ld %r6, PCB_DSCR(%r17) /* Load the DSCR register*/ mtspr SPR_DSCR, %r6 +.L32: + /* Restore FSCR if needed */ + andi. %r6, %r19, PCB_CFSCR + beq .L4 + ld %r6, PCB_FSCR(%r17) /* Load the DSCR register*/ + mtspr SPR_FSCR, %r6 /* thread to restore is in r3 */ .L4: