diff options
Diffstat (limited to 'arch/arm/vfp/vfphw.S')
-rw-r--r-- | arch/arm/vfp/vfphw.S | 26 |
1 files changed, 24 insertions, 2 deletions
diff --git a/arch/arm/vfp/vfphw.S b/arch/arm/vfp/vfphw.S index e51e6679c402..d4b7b229631d 100644 --- a/arch/arm/vfp/vfphw.S +++ b/arch/arm/vfp/vfphw.S | |||
@@ -65,6 +65,7 @@ | |||
65 | @ r2 = faulted PC+4 | 65 | @ r2 = faulted PC+4 |
66 | @ r9 = successful return | 66 | @ r9 = successful return |
67 | @ r10 = vfp_state union | 67 | @ r10 = vfp_state union |
68 | @ r11 = CPU number | ||
68 | @ lr = failure return | 69 | @ lr = failure return |
69 | 70 | ||
70 | .globl vfp_support_entry | 71 | .globl vfp_support_entry |
@@ -79,7 +80,7 @@ vfp_support_entry: | |||
79 | DBGSTR1 "enable %x", r10 | 80 | DBGSTR1 "enable %x", r10 |
80 | ldr r3, last_VFP_context_address | 81 | ldr r3, last_VFP_context_address |
81 | orr r1, r1, #FPEXC_ENABLE @ user FPEXC has the enable bit set | 82 | orr r1, r1, #FPEXC_ENABLE @ user FPEXC has the enable bit set |
82 | ldr r4, [r3] @ last_VFP_context pointer | 83 | ldr r4, [r3, r11, lsl #2] @ last_VFP_context pointer |
83 | bic r5, r1, #FPEXC_EXCEPTION @ make sure exceptions are disabled | 84 | bic r5, r1, #FPEXC_EXCEPTION @ make sure exceptions are disabled |
84 | cmp r4, r10 | 85 | cmp r4, r10 |
85 | beq check_for_exception @ we are returning to the same | 86 | beq check_for_exception @ we are returning to the same |
@@ -91,7 +92,9 @@ vfp_support_entry: | |||
91 | @ exceptions, so we can get at the | 92 | @ exceptions, so we can get at the |
92 | @ rest of it | 93 | @ rest of it |
93 | 94 | ||
95 | #ifndef CONFIG_SMP | ||
94 | @ Save out the current registers to the old thread state | 96 | @ Save out the current registers to the old thread state |
97 | @ No need for SMP since this is not done lazily | ||
95 | 98 | ||
96 | DBGSTR1 "save old state %p", r4 | 99 | DBGSTR1 "save old state %p", r4 |
97 | cmp r4, #0 | 100 | cmp r4, #0 |
@@ -105,10 +108,11 @@ vfp_support_entry: | |||
105 | stmia r4, {r1, r5, r6, r8} @ save FPEXC, FPSCR, FPINST, FPINST2 | 108 | stmia r4, {r1, r5, r6, r8} @ save FPEXC, FPSCR, FPINST, FPINST2 |
106 | @ and point r4 at the word at the | 109 | @ and point r4 at the word at the |
107 | @ start of the register dump | 110 | @ start of the register dump |
111 | #endif | ||
108 | 112 | ||
109 | no_old_VFP_process: | 113 | no_old_VFP_process: |
110 | DBGSTR1 "load state %p", r10 | 114 | DBGSTR1 "load state %p", r10 |
111 | str r10, [r3] @ update the last_VFP_context pointer | 115 | str r10, [r3, r11, lsl #2] @ update the last_VFP_context pointer |
112 | @ Load the saved state back into the VFP | 116 | @ Load the saved state back into the VFP |
113 | VFPFLDMIA r10 @ reload the working registers while | 117 | VFPFLDMIA r10 @ reload the working registers while |
114 | @ FPEXC is in a safe state | 118 | @ FPEXC is in a safe state |
@@ -162,6 +166,24 @@ process_exception: | |||
162 | @ required. If not, the user code will | 166 | @ required. If not, the user code will |
163 | @ retry the faulted instruction | 167 | @ retry the faulted instruction |
164 | 168 | ||
169 | #ifdef CONFIG_SMP | ||
170 | .globl vfp_save_state | ||
171 | .type vfp_save_state, %function | ||
172 | vfp_save_state: | ||
173 | @ Save the current VFP state | ||
174 | @ r0 - save location | ||
175 | @ r1 - FPEXC | ||
176 | DBGSTR1 "save VFP state %p", r0 | ||
177 | VFPFMRX r2, FPSCR @ current status | ||
178 | VFPFMRX r3, FPINST @ FPINST (always there, rev0 onwards) | ||
179 | tst r1, #FPEXC_FPV2 @ is there an FPINST2 to read? | ||
180 | VFPFMRX r12, FPINST2, NE @ FPINST2 if needed - avoids reading | ||
181 | @ nonexistant reg on rev0 | ||
182 | VFPFSTMIA r0 @ save the working registers | ||
183 | stmia r0, {r1, r2, r3, r12} @ save FPEXC, FPSCR, FPINST, FPINST2 | ||
184 | mov pc, lr | ||
185 | #endif | ||
186 | |||
165 | last_VFP_context_address: | 187 | last_VFP_context_address: |
166 | .word last_VFP_context | 188 | .word last_VFP_context |
167 | 189 | ||