aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/vfp/vfphw.S
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/vfp/vfphw.S')
-rw-r--r--arch/arm/vfp/vfphw.S63
1 files changed, 43 insertions, 20 deletions
diff --git a/arch/arm/vfp/vfphw.S b/arch/arm/vfp/vfphw.S
index 9897dcfc16d6..2d30c7f6edd3 100644
--- a/arch/arm/vfp/vfphw.S
+++ b/arch/arm/vfp/vfphw.S
@@ -77,27 +77,27 @@ ENTRY(vfp_support_entry)
77 bne look_for_VFP_exceptions @ VFP is already enabled 77 bne look_for_VFP_exceptions @ VFP is already enabled
78 78
79 DBGSTR1 "enable %x", r10 79 DBGSTR1 "enable %x", r10
80 ldr r3, last_VFP_context_address 80 ldr r3, vfp_current_hw_state_address
81 orr r1, r1, #FPEXC_EN @ user FPEXC has the enable bit set 81 orr r1, r1, #FPEXC_EN @ user FPEXC has the enable bit set
82 ldr r4, [r3, r11, lsl #2] @ last_VFP_context pointer 82 ldr r4, [r3, r11, lsl #2] @ vfp_current_hw_state pointer
83 bic r5, r1, #FPEXC_EX @ make sure exceptions are disabled 83 bic r5, r1, #FPEXC_EX @ make sure exceptions are disabled
84 cmp r4, r10 84 cmp r4, r10 @ this thread owns the hw context?
85 beq check_for_exception @ we are returning to the same 85#ifndef CONFIG_SMP
86 @ process, so the registers are 86 @ For UP, checking that this thread owns the hw context is
87 @ still there. In this case, we do 87 @ sufficient to determine that the hardware state is valid.
88 @ not want to drop a pending exception. 88 beq vfp_hw_state_valid
89
90 @ On UP, we lazily save the VFP context. As a different
91 @ thread wants ownership of the VFP hardware, save the old
92 @ state if there was a previous (valid) owner.
89 93
90 VFPFMXR FPEXC, r5 @ enable VFP, disable any pending 94 VFPFMXR FPEXC, r5 @ enable VFP, disable any pending
91 @ exceptions, so we can get at the 95 @ exceptions, so we can get at the
92 @ rest of it 96 @ rest of it
93 97
94#ifndef CONFIG_SMP
95 @ Save out the current registers to the old thread state
96 @ No need for SMP since this is not done lazily
97
98 DBGSTR1 "save old state %p", r4 98 DBGSTR1 "save old state %p", r4
99 cmp r4, #0 99 cmp r4, #0 @ if the vfp_current_hw_state is NULL
100 beq no_old_VFP_process 100 beq vfp_reload_hw @ then the hw state needs reloading
101 VFPFSTMIA r4, r5 @ save the working registers 101 VFPFSTMIA r4, r5 @ save the working registers
102 VFPFMRX r5, FPSCR @ current status 102 VFPFMRX r5, FPSCR @ current status
103#ifndef CONFIG_CPU_FEROCEON 103#ifndef CONFIG_CPU_FEROCEON
@@ -110,13 +110,35 @@ ENTRY(vfp_support_entry)
1101: 1101:
111#endif 111#endif
112 stmia r4, {r1, r5, r6, r8} @ save FPEXC, FPSCR, FPINST, FPINST2 112 stmia r4, {r1, r5, r6, r8} @ save FPEXC, FPSCR, FPINST, FPINST2
113 @ and point r4 at the word at the 113vfp_reload_hw:
114 @ start of the register dump 114
115#else
116 @ For SMP, if this thread does not own the hw context, then we
117 @ need to reload it. No need to save the old state as on SMP,
118 @ we always save the state when we switch away from a thread.
119 bne vfp_reload_hw
120
121 @ This thread has ownership of the current hardware context.
122 @ However, it may have been migrated to another CPU, in which
123 @ case the saved state is newer than the hardware context.
124 @ Check this by looking at the CPU number which the state was
125 @ last loaded onto.
126 ldr ip, [r10, #VFP_CPU]
127 teq ip, r11
128 beq vfp_hw_state_valid
129
130vfp_reload_hw:
131 @ We're loading this threads state into the VFP hardware. Update
132 @ the CPU number which contains the most up to date VFP context.
133 str r11, [r10, #VFP_CPU]
134
135 VFPFMXR FPEXC, r5 @ enable VFP, disable any pending
136 @ exceptions, so we can get at the
137 @ rest of it
115#endif 138#endif
116 139
117no_old_VFP_process:
118 DBGSTR1 "load state %p", r10 140 DBGSTR1 "load state %p", r10
119 str r10, [r3, r11, lsl #2] @ update the last_VFP_context pointer 141 str r10, [r3, r11, lsl #2] @ update the vfp_current_hw_state pointer
120 @ Load the saved state back into the VFP 142 @ Load the saved state back into the VFP
121 VFPFLDMIA r10, r5 @ reload the working registers while 143 VFPFLDMIA r10, r5 @ reload the working registers while
122 @ FPEXC is in a safe state 144 @ FPEXC is in a safe state
@@ -132,7 +154,8 @@ no_old_VFP_process:
132#endif 154#endif
133 VFPFMXR FPSCR, r5 @ restore status 155 VFPFMXR FPSCR, r5 @ restore status
134 156
135check_for_exception: 157@ The context stored in the VFP hardware is up to date with this thread
158vfp_hw_state_valid:
136 tst r1, #FPEXC_EX 159 tst r1, #FPEXC_EX
137 bne process_exception @ might as well handle the pending 160 bne process_exception @ might as well handle the pending
138 @ exception before retrying branch 161 @ exception before retrying branch
@@ -207,8 +230,8 @@ ENTRY(vfp_save_state)
207ENDPROC(vfp_save_state) 230ENDPROC(vfp_save_state)
208 231
209 .align 232 .align
210last_VFP_context_address: 233vfp_current_hw_state_address:
211 .word last_VFP_context 234 .word vfp_current_hw_state
212 235
213 .macro tbl_branch, base, tmp, shift 236 .macro tbl_branch, base, tmp, shift
214#ifdef CONFIG_THUMB2_KERNEL 237#ifdef CONFIG_THUMB2_KERNEL