Commit ce0ac1fc326b6a4116728be933ff46d75269baa1
Committed by
Benjamin Herrenschmidt
1 parent
fb5153d05a
Exists in
ti-lsk-linux-4.1.y
and in
10 other branches
powerpc/tm: Remove unnecessary r1 save
We save r1 to the scratch SPR and restore it from there after the trechkpt so saving r1 to the paca is not needed. Signed-off-by: Michael Neuling <mikey@neuling.org> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Showing 1 changed file with 0 additions and 2 deletions Inline Diff
arch/powerpc/kernel/tm.S
1 | /* | 1 | /* |
2 | * Transactional memory support routines to reclaim and recheckpoint | 2 | * Transactional memory support routines to reclaim and recheckpoint |
3 | * transactional process state. | 3 | * transactional process state. |
4 | * | 4 | * |
5 | * Copyright 2012 Matt Evans & Michael Neuling, IBM Corporation. | 5 | * Copyright 2012 Matt Evans & Michael Neuling, IBM Corporation. |
6 | */ | 6 | */ |
7 | 7 | ||
8 | #include <asm/asm-offsets.h> | 8 | #include <asm/asm-offsets.h> |
9 | #include <asm/ppc_asm.h> | 9 | #include <asm/ppc_asm.h> |
10 | #include <asm/ppc-opcode.h> | 10 | #include <asm/ppc-opcode.h> |
11 | #include <asm/ptrace.h> | 11 | #include <asm/ptrace.h> |
12 | #include <asm/reg.h> | 12 | #include <asm/reg.h> |
13 | 13 | ||
14 | #ifdef CONFIG_VSX | 14 | #ifdef CONFIG_VSX |
15 | /* See fpu.S, this is borrowed from there */ | 15 | /* See fpu.S, this is borrowed from there */ |
16 | #define __SAVE_32FPRS_VSRS(n,c,base) \ | 16 | #define __SAVE_32FPRS_VSRS(n,c,base) \ |
17 | BEGIN_FTR_SECTION \ | 17 | BEGIN_FTR_SECTION \ |
18 | b 2f; \ | 18 | b 2f; \ |
19 | END_FTR_SECTION_IFSET(CPU_FTR_VSX); \ | 19 | END_FTR_SECTION_IFSET(CPU_FTR_VSX); \ |
20 | SAVE_32FPRS(n,base); \ | 20 | SAVE_32FPRS(n,base); \ |
21 | b 3f; \ | 21 | b 3f; \ |
22 | 2: SAVE_32VSRS(n,c,base); \ | 22 | 2: SAVE_32VSRS(n,c,base); \ |
23 | 3: | 23 | 3: |
24 | #define __REST_32FPRS_VSRS(n,c,base) \ | 24 | #define __REST_32FPRS_VSRS(n,c,base) \ |
25 | BEGIN_FTR_SECTION \ | 25 | BEGIN_FTR_SECTION \ |
26 | b 2f; \ | 26 | b 2f; \ |
27 | END_FTR_SECTION_IFSET(CPU_FTR_VSX); \ | 27 | END_FTR_SECTION_IFSET(CPU_FTR_VSX); \ |
28 | REST_32FPRS(n,base); \ | 28 | REST_32FPRS(n,base); \ |
29 | b 3f; \ | 29 | b 3f; \ |
30 | 2: REST_32VSRS(n,c,base); \ | 30 | 2: REST_32VSRS(n,c,base); \ |
31 | 3: | 31 | 3: |
32 | #else | 32 | #else |
33 | #define __SAVE_32FPRS_VSRS(n,c,base) SAVE_32FPRS(n, base) | 33 | #define __SAVE_32FPRS_VSRS(n,c,base) SAVE_32FPRS(n, base) |
34 | #define __REST_32FPRS_VSRS(n,c,base) REST_32FPRS(n, base) | 34 | #define __REST_32FPRS_VSRS(n,c,base) REST_32FPRS(n, base) |
35 | #endif | 35 | #endif |
36 | #define SAVE_32FPRS_VSRS(n,c,base) \ | 36 | #define SAVE_32FPRS_VSRS(n,c,base) \ |
37 | __SAVE_32FPRS_VSRS(n,__REG_##c,__REG_##base) | 37 | __SAVE_32FPRS_VSRS(n,__REG_##c,__REG_##base) |
38 | #define REST_32FPRS_VSRS(n,c,base) \ | 38 | #define REST_32FPRS_VSRS(n,c,base) \ |
39 | __REST_32FPRS_VSRS(n,__REG_##c,__REG_##base) | 39 | __REST_32FPRS_VSRS(n,__REG_##c,__REG_##base) |
40 | 40 | ||
41 | /* Stack frame offsets for local variables. */ | 41 | /* Stack frame offsets for local variables. */ |
42 | #define TM_FRAME_L0 TM_FRAME_SIZE-16 | 42 | #define TM_FRAME_L0 TM_FRAME_SIZE-16 |
43 | #define TM_FRAME_L1 TM_FRAME_SIZE-8 | 43 | #define TM_FRAME_L1 TM_FRAME_SIZE-8 |
44 | #define STACK_PARAM(x) (48+((x)*8)) | 44 | #define STACK_PARAM(x) (48+((x)*8)) |
45 | 45 | ||
46 | 46 | ||
47 | /* In order to access the TM SPRs, TM must be enabled. So, do so: */ | 47 | /* In order to access the TM SPRs, TM must be enabled. So, do so: */ |
48 | _GLOBAL(tm_enable) | 48 | _GLOBAL(tm_enable) |
49 | mfmsr r4 | 49 | mfmsr r4 |
50 | li r3, MSR_TM >> 32 | 50 | li r3, MSR_TM >> 32 |
51 | sldi r3, r3, 32 | 51 | sldi r3, r3, 32 |
52 | and. r0, r4, r3 | 52 | and. r0, r4, r3 |
53 | bne 1f | 53 | bne 1f |
54 | or r4, r4, r3 | 54 | or r4, r4, r3 |
55 | mtmsrd r4 | 55 | mtmsrd r4 |
56 | 1: blr | 56 | 1: blr |
57 | 57 | ||
58 | _GLOBAL(tm_save_sprs) | 58 | _GLOBAL(tm_save_sprs) |
59 | mfspr r0, SPRN_TFHAR | 59 | mfspr r0, SPRN_TFHAR |
60 | std r0, THREAD_TM_TFHAR(r3) | 60 | std r0, THREAD_TM_TFHAR(r3) |
61 | mfspr r0, SPRN_TEXASR | 61 | mfspr r0, SPRN_TEXASR |
62 | std r0, THREAD_TM_TEXASR(r3) | 62 | std r0, THREAD_TM_TEXASR(r3) |
63 | mfspr r0, SPRN_TFIAR | 63 | mfspr r0, SPRN_TFIAR |
64 | std r0, THREAD_TM_TFIAR(r3) | 64 | std r0, THREAD_TM_TFIAR(r3) |
65 | blr | 65 | blr |
66 | 66 | ||
67 | _GLOBAL(tm_restore_sprs) | 67 | _GLOBAL(tm_restore_sprs) |
68 | ld r0, THREAD_TM_TFHAR(r3) | 68 | ld r0, THREAD_TM_TFHAR(r3) |
69 | mtspr SPRN_TFHAR, r0 | 69 | mtspr SPRN_TFHAR, r0 |
70 | ld r0, THREAD_TM_TEXASR(r3) | 70 | ld r0, THREAD_TM_TEXASR(r3) |
71 | mtspr SPRN_TEXASR, r0 | 71 | mtspr SPRN_TEXASR, r0 |
72 | ld r0, THREAD_TM_TFIAR(r3) | 72 | ld r0, THREAD_TM_TFIAR(r3) |
73 | mtspr SPRN_TFIAR, r0 | 73 | mtspr SPRN_TFIAR, r0 |
74 | blr | 74 | blr |
75 | 75 | ||
76 | /* Passed an 8-bit failure cause as first argument. */ | 76 | /* Passed an 8-bit failure cause as first argument. */ |
77 | _GLOBAL(tm_abort) | 77 | _GLOBAL(tm_abort) |
78 | TABORT(R3) | 78 | TABORT(R3) |
79 | blr | 79 | blr |
80 | 80 | ||
81 | .section ".toc","aw" | 81 | .section ".toc","aw" |
82 | DSCR_DEFAULT: | 82 | DSCR_DEFAULT: |
83 | .tc dscr_default[TC],dscr_default | 83 | .tc dscr_default[TC],dscr_default |
84 | 84 | ||
85 | .section ".text" | 85 | .section ".text" |
86 | 86 | ||
87 | /* void tm_reclaim(struct thread_struct *thread, | 87 | /* void tm_reclaim(struct thread_struct *thread, |
88 | * unsigned long orig_msr, | 88 | * unsigned long orig_msr, |
89 | * uint8_t cause) | 89 | * uint8_t cause) |
90 | * | 90 | * |
91 | * - Performs a full reclaim. This destroys outstanding | 91 | * - Performs a full reclaim. This destroys outstanding |
92 | * transactions and updates thread->regs.tm_ckpt_* with the | 92 | * transactions and updates thread->regs.tm_ckpt_* with the |
93 | * original checkpointed state. Note that thread->regs is | 93 | * original checkpointed state. Note that thread->regs is |
94 | * unchanged. | 94 | * unchanged. |
95 | * - FP regs are written back to thread->transact_fpr before | 95 | * - FP regs are written back to thread->transact_fpr before |
96 | * reclaiming. These are the transactional (current) versions. | 96 | * reclaiming. These are the transactional (current) versions. |
97 | * | 97 | * |
98 | * Purpose is to both abort transactions of, and preserve the state of, | 98 | * Purpose is to both abort transactions of, and preserve the state of, |
99 | * a transactions at a context switch. We preserve/restore both sets of process | 99 | * a transactions at a context switch. We preserve/restore both sets of process |
100 | * state to restore them when the thread's scheduled again. We continue in | 100 | * state to restore them when the thread's scheduled again. We continue in |
101 | * userland as though nothing happened, but when the transaction is resumed | 101 | * userland as though nothing happened, but when the transaction is resumed |
102 | * they will abort back to the checkpointed state we save out here. | 102 | * they will abort back to the checkpointed state we save out here. |
103 | * | 103 | * |
104 | * Call with IRQs off, stacks get all out of sync for some periods in here! | 104 | * Call with IRQs off, stacks get all out of sync for some periods in here! |
105 | */ | 105 | */ |
106 | _GLOBAL(tm_reclaim) | 106 | _GLOBAL(tm_reclaim) |
107 | mfcr r6 | 107 | mfcr r6 |
108 | mflr r0 | 108 | mflr r0 |
109 | stw r6, 8(r1) | 109 | stw r6, 8(r1) |
110 | std r0, 16(r1) | 110 | std r0, 16(r1) |
111 | std r2, 40(r1) | 111 | std r2, 40(r1) |
112 | stdu r1, -TM_FRAME_SIZE(r1) | 112 | stdu r1, -TM_FRAME_SIZE(r1) |
113 | 113 | ||
114 | /* We've a struct pt_regs at [r1+STACK_FRAME_OVERHEAD]. */ | 114 | /* We've a struct pt_regs at [r1+STACK_FRAME_OVERHEAD]. */ |
115 | 115 | ||
116 | std r3, STACK_PARAM(0)(r1) | 116 | std r3, STACK_PARAM(0)(r1) |
117 | SAVE_NVGPRS(r1) | 117 | SAVE_NVGPRS(r1) |
118 | 118 | ||
119 | /* We need to setup MSR for VSX register save instructions. Here we | 119 | /* We need to setup MSR for VSX register save instructions. Here we |
120 | * also clear the MSR RI since when we do the treclaim, we won't have a | 120 | * also clear the MSR RI since when we do the treclaim, we won't have a |
121 | * valid kernel pointer for a while. We clear RI here as it avoids | 121 | * valid kernel pointer for a while. We clear RI here as it avoids |
122 | * adding another mtmsr closer to the treclaim. This makes the region | 122 | * adding another mtmsr closer to the treclaim. This makes the region |
123 | * maked as non-recoverable wider than it needs to be but it saves on | 123 | * maked as non-recoverable wider than it needs to be but it saves on |
124 | * inserting another mtmsrd later. | 124 | * inserting another mtmsrd later. |
125 | */ | 125 | */ |
126 | mfmsr r14 | 126 | mfmsr r14 |
127 | mr r15, r14 | 127 | mr r15, r14 |
128 | ori r15, r15, MSR_FP | 128 | ori r15, r15, MSR_FP |
129 | li r16, MSR_RI | 129 | li r16, MSR_RI |
130 | ori r16, r16, MSR_EE /* IRQs hard off */ | 130 | ori r16, r16, MSR_EE /* IRQs hard off */ |
131 | andc r15, r15, r16 | 131 | andc r15, r15, r16 |
132 | oris r15, r15, MSR_VEC@h | 132 | oris r15, r15, MSR_VEC@h |
133 | #ifdef CONFIG_VSX | 133 | #ifdef CONFIG_VSX |
134 | BEGIN_FTR_SECTION | 134 | BEGIN_FTR_SECTION |
135 | oris r15,r15, MSR_VSX@h | 135 | oris r15,r15, MSR_VSX@h |
136 | END_FTR_SECTION_IFSET(CPU_FTR_VSX) | 136 | END_FTR_SECTION_IFSET(CPU_FTR_VSX) |
137 | #endif | 137 | #endif |
138 | mtmsrd r15 | 138 | mtmsrd r15 |
139 | std r14, TM_FRAME_L0(r1) | 139 | std r14, TM_FRAME_L0(r1) |
140 | 140 | ||
141 | /* Stash the stack pointer away for use after reclaim */ | 141 | /* Stash the stack pointer away for use after reclaim */ |
142 | std r1, PACAR1(r13) | 142 | std r1, PACAR1(r13) |
143 | 143 | ||
144 | /* ******************** FPR/VR/VSRs ************ | 144 | /* ******************** FPR/VR/VSRs ************ |
145 | * Before reclaiming, capture the current/transactional FPR/VR | 145 | * Before reclaiming, capture the current/transactional FPR/VR |
146 | * versions /if used/. | 146 | * versions /if used/. |
147 | * | 147 | * |
148 | * (If VSX used, FP and VMX are implied. Or, we don't need to look | 148 | * (If VSX used, FP and VMX are implied. Or, we don't need to look |
149 | * at MSR.VSX as copying FP regs if .FP, vector regs if .VMX covers it.) | 149 | * at MSR.VSX as copying FP regs if .FP, vector regs if .VMX covers it.) |
150 | * | 150 | * |
151 | * We're passed the thread's MSR as parameter 2. | 151 | * We're passed the thread's MSR as parameter 2. |
152 | * | 152 | * |
153 | * We enabled VEC/FP/VSX in the msr above, so we can execute these | 153 | * We enabled VEC/FP/VSX in the msr above, so we can execute these |
154 | * instructions! | 154 | * instructions! |
155 | */ | 155 | */ |
156 | andis. r0, r4, MSR_VEC@h | 156 | andis. r0, r4, MSR_VEC@h |
157 | beq dont_backup_vec | 157 | beq dont_backup_vec |
158 | 158 | ||
159 | addi r7, r3, THREAD_TRANSACT_VRSTATE | 159 | addi r7, r3, THREAD_TRANSACT_VRSTATE |
160 | SAVE_32VRS(0, r6, r7) /* r6 scratch, r7 transact vr state */ | 160 | SAVE_32VRS(0, r6, r7) /* r6 scratch, r7 transact vr state */ |
161 | mfvscr vr0 | 161 | mfvscr vr0 |
162 | li r6, VRSTATE_VSCR | 162 | li r6, VRSTATE_VSCR |
163 | stvx vr0, r7, r6 | 163 | stvx vr0, r7, r6 |
164 | dont_backup_vec: | 164 | dont_backup_vec: |
165 | mfspr r0, SPRN_VRSAVE | 165 | mfspr r0, SPRN_VRSAVE |
166 | std r0, THREAD_TRANSACT_VRSAVE(r3) | 166 | std r0, THREAD_TRANSACT_VRSAVE(r3) |
167 | 167 | ||
168 | andi. r0, r4, MSR_FP | 168 | andi. r0, r4, MSR_FP |
169 | beq dont_backup_fp | 169 | beq dont_backup_fp |
170 | 170 | ||
171 | addi r7, r3, THREAD_TRANSACT_FPSTATE | 171 | addi r7, r3, THREAD_TRANSACT_FPSTATE |
172 | SAVE_32FPRS_VSRS(0, R6, R7) /* r6 scratch, r7 transact fp state */ | 172 | SAVE_32FPRS_VSRS(0, R6, R7) /* r6 scratch, r7 transact fp state */ |
173 | 173 | ||
174 | mffs fr0 | 174 | mffs fr0 |
175 | stfd fr0,FPSTATE_FPSCR(r7) | 175 | stfd fr0,FPSTATE_FPSCR(r7) |
176 | 176 | ||
177 | dont_backup_fp: | 177 | dont_backup_fp: |
178 | /* The moment we treclaim, ALL of our GPRs will switch | 178 | /* The moment we treclaim, ALL of our GPRs will switch |
179 | * to user register state. (FPRs, CCR etc. also!) | 179 | * to user register state. (FPRs, CCR etc. also!) |
180 | * Use an sprg and a tm_scratch in the PACA to shuffle. | 180 | * Use an sprg and a tm_scratch in the PACA to shuffle. |
181 | */ | 181 | */ |
182 | TRECLAIM(R5) /* Cause in r5 */ | 182 | TRECLAIM(R5) /* Cause in r5 */ |
183 | 183 | ||
184 | /* ******************** GPRs ******************** */ | 184 | /* ******************** GPRs ******************** */ |
185 | /* Stash the checkpointed r13 away in the scratch SPR and get the real | 185 | /* Stash the checkpointed r13 away in the scratch SPR and get the real |
186 | * paca | 186 | * paca |
187 | */ | 187 | */ |
188 | SET_SCRATCH0(r13) | 188 | SET_SCRATCH0(r13) |
189 | GET_PACA(r13) | 189 | GET_PACA(r13) |
190 | 190 | ||
191 | /* Stash the checkpointed r1 away in paca tm_scratch and get the real | 191 | /* Stash the checkpointed r1 away in paca tm_scratch and get the real |
192 | * stack pointer back | 192 | * stack pointer back |
193 | */ | 193 | */ |
194 | std r1, PACATMSCRATCH(r13) | 194 | std r1, PACATMSCRATCH(r13) |
195 | ld r1, PACAR1(r13) | 195 | ld r1, PACAR1(r13) |
196 | 196 | ||
197 | /* Store the PPR in r11 and reset to decent value */ | 197 | /* Store the PPR in r11 and reset to decent value */ |
198 | std r11, GPR11(r1) /* Temporary stash */ | 198 | std r11, GPR11(r1) /* Temporary stash */ |
199 | mfspr r11, SPRN_PPR | 199 | mfspr r11, SPRN_PPR |
200 | HMT_MEDIUM | 200 | HMT_MEDIUM |
201 | 201 | ||
202 | /* Now get some more GPRS free */ | 202 | /* Now get some more GPRS free */ |
203 | std r7, GPR7(r1) /* Temporary stash */ | 203 | std r7, GPR7(r1) /* Temporary stash */ |
204 | std r12, GPR12(r1) /* '' '' '' */ | 204 | std r12, GPR12(r1) /* '' '' '' */ |
205 | ld r12, STACK_PARAM(0)(r1) /* Param 0, thread_struct * */ | 205 | ld r12, STACK_PARAM(0)(r1) /* Param 0, thread_struct * */ |
206 | 206 | ||
207 | std r11, THREAD_TM_PPR(r12) /* Store PPR and free r11 */ | 207 | std r11, THREAD_TM_PPR(r12) /* Store PPR and free r11 */ |
208 | 208 | ||
209 | addi r7, r12, PT_CKPT_REGS /* Thread's ckpt_regs */ | 209 | addi r7, r12, PT_CKPT_REGS /* Thread's ckpt_regs */ |
210 | 210 | ||
211 | /* Make r7 look like an exception frame so that we | 211 | /* Make r7 look like an exception frame so that we |
212 | * can use the neat GPRx(n) macros. r7 is NOT a pt_regs ptr! | 212 | * can use the neat GPRx(n) macros. r7 is NOT a pt_regs ptr! |
213 | */ | 213 | */ |
214 | subi r7, r7, STACK_FRAME_OVERHEAD | 214 | subi r7, r7, STACK_FRAME_OVERHEAD |
215 | 215 | ||
216 | /* Sync the userland GPRs 2-12, 14-31 to thread->regs: */ | 216 | /* Sync the userland GPRs 2-12, 14-31 to thread->regs: */ |
217 | SAVE_GPR(0, r7) /* user r0 */ | 217 | SAVE_GPR(0, r7) /* user r0 */ |
218 | SAVE_GPR(2, r7) /* user r2 */ | 218 | SAVE_GPR(2, r7) /* user r2 */ |
219 | SAVE_4GPRS(3, r7) /* user r3-r6 */ | 219 | SAVE_4GPRS(3, r7) /* user r3-r6 */ |
220 | SAVE_GPR(8, r7) /* user r8 */ | 220 | SAVE_GPR(8, r7) /* user r8 */ |
221 | SAVE_GPR(9, r7) /* user r9 */ | 221 | SAVE_GPR(9, r7) /* user r9 */ |
222 | SAVE_GPR(10, r7) /* user r10 */ | 222 | SAVE_GPR(10, r7) /* user r10 */ |
223 | ld r3, PACATMSCRATCH(r13) /* user r1 */ | 223 | ld r3, PACATMSCRATCH(r13) /* user r1 */ |
224 | ld r4, GPR7(r1) /* user r7 */ | 224 | ld r4, GPR7(r1) /* user r7 */ |
225 | ld r5, GPR11(r1) /* user r11 */ | 225 | ld r5, GPR11(r1) /* user r11 */ |
226 | ld r6, GPR12(r1) /* user r12 */ | 226 | ld r6, GPR12(r1) /* user r12 */ |
227 | GET_SCRATCH0(8) /* user r13 */ | 227 | GET_SCRATCH0(8) /* user r13 */ |
228 | std r3, GPR1(r7) | 228 | std r3, GPR1(r7) |
229 | std r4, GPR7(r7) | 229 | std r4, GPR7(r7) |
230 | std r5, GPR11(r7) | 230 | std r5, GPR11(r7) |
231 | std r6, GPR12(r7) | 231 | std r6, GPR12(r7) |
232 | std r8, GPR13(r7) | 232 | std r8, GPR13(r7) |
233 | 233 | ||
234 | SAVE_NVGPRS(r7) /* user r14-r31 */ | 234 | SAVE_NVGPRS(r7) /* user r14-r31 */ |
235 | 235 | ||
236 | /* ******************** NIP ******************** */ | 236 | /* ******************** NIP ******************** */ |
237 | mfspr r3, SPRN_TFHAR | 237 | mfspr r3, SPRN_TFHAR |
238 | std r3, _NIP(r7) /* Returns to failhandler */ | 238 | std r3, _NIP(r7) /* Returns to failhandler */ |
239 | /* The checkpointed NIP is ignored when rescheduling/rechkpting, | 239 | /* The checkpointed NIP is ignored when rescheduling/rechkpting, |
240 | * but is used in signal return to 'wind back' to the abort handler. | 240 | * but is used in signal return to 'wind back' to the abort handler. |
241 | */ | 241 | */ |
242 | 242 | ||
243 | /* ******************** CR,LR,CCR,MSR ********** */ | 243 | /* ******************** CR,LR,CCR,MSR ********** */ |
244 | mfctr r3 | 244 | mfctr r3 |
245 | mflr r4 | 245 | mflr r4 |
246 | mfcr r5 | 246 | mfcr r5 |
247 | mfxer r6 | 247 | mfxer r6 |
248 | 248 | ||
249 | std r3, _CTR(r7) | 249 | std r3, _CTR(r7) |
250 | std r4, _LINK(r7) | 250 | std r4, _LINK(r7) |
251 | std r5, _CCR(r7) | 251 | std r5, _CCR(r7) |
252 | std r6, _XER(r7) | 252 | std r6, _XER(r7) |
253 | 253 | ||
254 | 254 | ||
255 | /* ******************** TAR, DSCR ********** */ | 255 | /* ******************** TAR, DSCR ********** */ |
256 | mfspr r3, SPRN_TAR | 256 | mfspr r3, SPRN_TAR |
257 | mfspr r4, SPRN_DSCR | 257 | mfspr r4, SPRN_DSCR |
258 | 258 | ||
259 | std r3, THREAD_TM_TAR(r12) | 259 | std r3, THREAD_TM_TAR(r12) |
260 | std r4, THREAD_TM_DSCR(r12) | 260 | std r4, THREAD_TM_DSCR(r12) |
261 | 261 | ||
262 | /* MSR and flags: We don't change CRs, and we don't need to alter | 262 | /* MSR and flags: We don't change CRs, and we don't need to alter |
263 | * MSR. | 263 | * MSR. |
264 | */ | 264 | */ |
265 | 265 | ||
266 | /* TM regs, incl TEXASR -- these live in thread_struct. Note they've | 266 | /* TM regs, incl TEXASR -- these live in thread_struct. Note they've |
267 | * been updated by the treclaim, to explain to userland the failure | 267 | * been updated by the treclaim, to explain to userland the failure |
268 | * cause (aborted). | 268 | * cause (aborted). |
269 | */ | 269 | */ |
270 | mfspr r0, SPRN_TEXASR | 270 | mfspr r0, SPRN_TEXASR |
271 | mfspr r3, SPRN_TFHAR | 271 | mfspr r3, SPRN_TFHAR |
272 | mfspr r4, SPRN_TFIAR | 272 | mfspr r4, SPRN_TFIAR |
273 | std r0, THREAD_TM_TEXASR(r12) | 273 | std r0, THREAD_TM_TEXASR(r12) |
274 | std r3, THREAD_TM_TFHAR(r12) | 274 | std r3, THREAD_TM_TFHAR(r12) |
275 | std r4, THREAD_TM_TFIAR(r12) | 275 | std r4, THREAD_TM_TFIAR(r12) |
276 | 276 | ||
277 | /* AMR is checkpointed too, but is unsupported by Linux. */ | 277 | /* AMR is checkpointed too, but is unsupported by Linux. */ |
278 | 278 | ||
279 | /* Restore original MSR/IRQ state & clear TM mode */ | 279 | /* Restore original MSR/IRQ state & clear TM mode */ |
280 | ld r14, TM_FRAME_L0(r1) /* Orig MSR */ | 280 | ld r14, TM_FRAME_L0(r1) /* Orig MSR */ |
281 | li r15, 0 | 281 | li r15, 0 |
282 | rldimi r14, r15, MSR_TS_LG, (63-MSR_TS_LG)-1 | 282 | rldimi r14, r15, MSR_TS_LG, (63-MSR_TS_LG)-1 |
283 | mtmsrd r14 | 283 | mtmsrd r14 |
284 | 284 | ||
285 | REST_NVGPRS(r1) | 285 | REST_NVGPRS(r1) |
286 | 286 | ||
287 | addi r1, r1, TM_FRAME_SIZE | 287 | addi r1, r1, TM_FRAME_SIZE |
288 | lwz r4, 8(r1) | 288 | lwz r4, 8(r1) |
289 | ld r0, 16(r1) | 289 | ld r0, 16(r1) |
290 | mtcr r4 | 290 | mtcr r4 |
291 | mtlr r0 | 291 | mtlr r0 |
292 | ld r2, 40(r1) | 292 | ld r2, 40(r1) |
293 | 293 | ||
294 | /* Load system default DSCR */ | 294 | /* Load system default DSCR */ |
295 | ld r4, DSCR_DEFAULT@toc(r2) | 295 | ld r4, DSCR_DEFAULT@toc(r2) |
296 | ld r0, 0(r4) | 296 | ld r0, 0(r4) |
297 | mtspr SPRN_DSCR, r0 | 297 | mtspr SPRN_DSCR, r0 |
298 | 298 | ||
299 | blr | 299 | blr |
300 | 300 | ||
301 | 301 | ||
302 | /* void tm_recheckpoint(struct thread_struct *thread, | 302 | /* void tm_recheckpoint(struct thread_struct *thread, |
303 | * unsigned long orig_msr) | 303 | * unsigned long orig_msr) |
304 | * - Restore the checkpointed register state saved by tm_reclaim | 304 | * - Restore the checkpointed register state saved by tm_reclaim |
305 | * when we switch_to a process. | 305 | * when we switch_to a process. |
306 | * | 306 | * |
307 | * Call with IRQs off, stacks get all out of sync for | 307 | * Call with IRQs off, stacks get all out of sync for |
308 | * some periods in here! | 308 | * some periods in here! |
309 | */ | 309 | */ |
310 | _GLOBAL(__tm_recheckpoint) | 310 | _GLOBAL(__tm_recheckpoint) |
311 | mfcr r5 | 311 | mfcr r5 |
312 | mflr r0 | 312 | mflr r0 |
313 | stw r5, 8(r1) | 313 | stw r5, 8(r1) |
314 | std r0, 16(r1) | 314 | std r0, 16(r1) |
315 | std r2, 40(r1) | 315 | std r2, 40(r1) |
316 | stdu r1, -TM_FRAME_SIZE(r1) | 316 | stdu r1, -TM_FRAME_SIZE(r1) |
317 | 317 | ||
318 | /* We've a struct pt_regs at [r1+STACK_FRAME_OVERHEAD]. | 318 | /* We've a struct pt_regs at [r1+STACK_FRAME_OVERHEAD]. |
319 | * This is used for backing up the NVGPRs: | 319 | * This is used for backing up the NVGPRs: |
320 | */ | 320 | */ |
321 | SAVE_NVGPRS(r1) | 321 | SAVE_NVGPRS(r1) |
322 | 322 | ||
323 | std r1, PACAR1(r13) | ||
324 | |||
325 | /* Load complete register state from ts_ckpt* registers */ | 323 | /* Load complete register state from ts_ckpt* registers */ |
326 | 324 | ||
327 | addi r7, r3, PT_CKPT_REGS /* Thread's ckpt_regs */ | 325 | addi r7, r3, PT_CKPT_REGS /* Thread's ckpt_regs */ |
328 | 326 | ||
329 | /* Make r7 look like an exception frame so that we | 327 | /* Make r7 look like an exception frame so that we |
330 | * can use the neat GPRx(n) macros. r7 is now NOT a pt_regs ptr! | 328 | * can use the neat GPRx(n) macros. r7 is now NOT a pt_regs ptr! |
331 | */ | 329 | */ |
332 | subi r7, r7, STACK_FRAME_OVERHEAD | 330 | subi r7, r7, STACK_FRAME_OVERHEAD |
333 | 331 | ||
334 | SET_SCRATCH0(r1) | 332 | SET_SCRATCH0(r1) |
335 | 333 | ||
336 | mfmsr r6 | 334 | mfmsr r6 |
337 | /* R4 = original MSR to indicate whether thread used FP/Vector etc. */ | 335 | /* R4 = original MSR to indicate whether thread used FP/Vector etc. */ |
338 | 336 | ||
339 | /* Enable FP/vec in MSR if necessary! */ | 337 | /* Enable FP/vec in MSR if necessary! */ |
340 | lis r5, MSR_VEC@h | 338 | lis r5, MSR_VEC@h |
341 | ori r5, r5, MSR_FP | 339 | ori r5, r5, MSR_FP |
342 | and. r5, r4, r5 | 340 | and. r5, r4, r5 |
343 | beq restore_gprs /* if neither, skip both */ | 341 | beq restore_gprs /* if neither, skip both */ |
344 | 342 | ||
345 | #ifdef CONFIG_VSX | 343 | #ifdef CONFIG_VSX |
346 | BEGIN_FTR_SECTION | 344 | BEGIN_FTR_SECTION |
347 | oris r5, r5, MSR_VSX@h | 345 | oris r5, r5, MSR_VSX@h |
348 | END_FTR_SECTION_IFSET(CPU_FTR_VSX) | 346 | END_FTR_SECTION_IFSET(CPU_FTR_VSX) |
349 | #endif | 347 | #endif |
350 | or r5, r6, r5 /* Set MSR.FP+.VSX/.VEC */ | 348 | or r5, r6, r5 /* Set MSR.FP+.VSX/.VEC */ |
351 | mtmsr r5 | 349 | mtmsr r5 |
352 | 350 | ||
353 | #ifdef CONFIG_ALTIVEC | 351 | #ifdef CONFIG_ALTIVEC |
354 | /* FP and VEC registers: These are recheckpointed from thread.fpr[] | 352 | /* FP and VEC registers: These are recheckpointed from thread.fpr[] |
355 | * and thread.vr[] respectively. The thread.transact_fpr[] version | 353 | * and thread.vr[] respectively. The thread.transact_fpr[] version |
356 | * is more modern, and will be loaded subsequently by any FPUnavailable | 354 | * is more modern, and will be loaded subsequently by any FPUnavailable |
357 | * trap. | 355 | * trap. |
358 | */ | 356 | */ |
359 | andis. r0, r4, MSR_VEC@h | 357 | andis. r0, r4, MSR_VEC@h |
360 | beq dont_restore_vec | 358 | beq dont_restore_vec |
361 | 359 | ||
362 | addi r8, r3, THREAD_VRSTATE | 360 | addi r8, r3, THREAD_VRSTATE |
363 | li r5, VRSTATE_VSCR | 361 | li r5, VRSTATE_VSCR |
364 | lvx vr0, r8, r5 | 362 | lvx vr0, r8, r5 |
365 | mtvscr vr0 | 363 | mtvscr vr0 |
366 | REST_32VRS(0, r5, r8) /* r5 scratch, r8 ptr */ | 364 | REST_32VRS(0, r5, r8) /* r5 scratch, r8 ptr */ |
367 | dont_restore_vec: | 365 | dont_restore_vec: |
368 | ld r5, THREAD_VRSAVE(r3) | 366 | ld r5, THREAD_VRSAVE(r3) |
369 | mtspr SPRN_VRSAVE, r5 | 367 | mtspr SPRN_VRSAVE, r5 |
370 | #endif | 368 | #endif |
371 | 369 | ||
372 | andi. r0, r4, MSR_FP | 370 | andi. r0, r4, MSR_FP |
373 | beq dont_restore_fp | 371 | beq dont_restore_fp |
374 | 372 | ||
375 | addi r8, r3, THREAD_FPSTATE | 373 | addi r8, r3, THREAD_FPSTATE |
376 | lfd fr0, FPSTATE_FPSCR(r8) | 374 | lfd fr0, FPSTATE_FPSCR(r8) |
377 | MTFSF_L(fr0) | 375 | MTFSF_L(fr0) |
378 | REST_32FPRS_VSRS(0, R4, R8) | 376 | REST_32FPRS_VSRS(0, R4, R8) |
379 | 377 | ||
380 | dont_restore_fp: | 378 | dont_restore_fp: |
381 | mtmsr r6 /* FP/Vec off again! */ | 379 | mtmsr r6 /* FP/Vec off again! */ |
382 | 380 | ||
383 | restore_gprs: | 381 | restore_gprs: |
384 | 382 | ||
385 | /* ******************** CR,LR,CCR,MSR ********** */ | 383 | /* ******************** CR,LR,CCR,MSR ********** */ |
386 | ld r4, _CTR(r7) | 384 | ld r4, _CTR(r7) |
387 | ld r5, _LINK(r7) | 385 | ld r5, _LINK(r7) |
388 | ld r6, _CCR(r7) | 386 | ld r6, _CCR(r7) |
389 | ld r8, _XER(r7) | 387 | ld r8, _XER(r7) |
390 | 388 | ||
391 | mtctr r4 | 389 | mtctr r4 |
392 | mtlr r5 | 390 | mtlr r5 |
393 | mtcr r6 | 391 | mtcr r6 |
394 | mtxer r8 | 392 | mtxer r8 |
395 | 393 | ||
396 | /* ******************** TAR ******************** */ | 394 | /* ******************** TAR ******************** */ |
397 | ld r4, THREAD_TM_TAR(r3) | 395 | ld r4, THREAD_TM_TAR(r3) |
398 | mtspr SPRN_TAR, r4 | 396 | mtspr SPRN_TAR, r4 |
399 | 397 | ||
400 | /* Load up the PPR and DSCR in GPRs only at this stage */ | 398 | /* Load up the PPR and DSCR in GPRs only at this stage */ |
401 | ld r5, THREAD_TM_DSCR(r3) | 399 | ld r5, THREAD_TM_DSCR(r3) |
402 | ld r6, THREAD_TM_PPR(r3) | 400 | ld r6, THREAD_TM_PPR(r3) |
403 | 401 | ||
404 | /* Clear the MSR RI since we are about to change R1. EE is already off | 402 | /* Clear the MSR RI since we are about to change R1. EE is already off |
405 | */ | 403 | */ |
406 | li r4, 0 | 404 | li r4, 0 |
407 | mtmsrd r4, 1 | 405 | mtmsrd r4, 1 |
408 | 406 | ||
409 | REST_4GPRS(0, r7) /* GPR0-3 */ | 407 | REST_4GPRS(0, r7) /* GPR0-3 */ |
410 | REST_GPR(4, r7) /* GPR4 */ | 408 | REST_GPR(4, r7) /* GPR4 */ |
411 | REST_4GPRS(8, r7) /* GPR8-11 */ | 409 | REST_4GPRS(8, r7) /* GPR8-11 */ |
412 | REST_2GPRS(12, r7) /* GPR12-13 */ | 410 | REST_2GPRS(12, r7) /* GPR12-13 */ |
413 | 411 | ||
414 | REST_NVGPRS(r7) /* GPR14-31 */ | 412 | REST_NVGPRS(r7) /* GPR14-31 */ |
415 | 413 | ||
416 | /* Load up PPR and DSCR here so we don't run with user values for long | 414 | /* Load up PPR and DSCR here so we don't run with user values for long |
417 | */ | 415 | */ |
418 | mtspr SPRN_DSCR, r5 | 416 | mtspr SPRN_DSCR, r5 |
419 | mtspr SPRN_PPR, r6 | 417 | mtspr SPRN_PPR, r6 |
420 | 418 | ||
421 | REST_GPR(5, r7) /* GPR5-7 */ | 419 | REST_GPR(5, r7) /* GPR5-7 */ |
422 | REST_GPR(6, r7) | 420 | REST_GPR(6, r7) |
423 | ld r7, GPR7(r7) | 421 | ld r7, GPR7(r7) |
424 | 422 | ||
425 | /* Commit register state as checkpointed state: */ | 423 | /* Commit register state as checkpointed state: */ |
426 | TRECHKPT | 424 | TRECHKPT |
427 | 425 | ||
428 | HMT_MEDIUM | 426 | HMT_MEDIUM |
429 | 427 | ||
430 | /* Our transactional state has now changed. | 428 | /* Our transactional state has now changed. |
431 | * | 429 | * |
432 | * Now just get out of here. Transactional (current) state will be | 430 | * Now just get out of here. Transactional (current) state will be |
433 | * updated once restore is called on the return path in the _switch-ed | 431 | * updated once restore is called on the return path in the _switch-ed |
434 | * -to process. | 432 | * -to process. |
435 | */ | 433 | */ |
436 | 434 | ||
437 | GET_PACA(r13) | 435 | GET_PACA(r13) |
438 | GET_SCRATCH0(r1) | 436 | GET_SCRATCH0(r1) |
439 | 437 | ||
440 | /* R1 is restored, so we are recoverable again. EE is still off */ | 438 | /* R1 is restored, so we are recoverable again. EE is still off */ |
441 | li r4, MSR_RI | 439 | li r4, MSR_RI |
442 | mtmsrd r4, 1 | 440 | mtmsrd r4, 1 |
443 | 441 | ||
444 | REST_NVGPRS(r1) | 442 | REST_NVGPRS(r1) |
445 | 443 | ||
446 | addi r1, r1, TM_FRAME_SIZE | 444 | addi r1, r1, TM_FRAME_SIZE |
447 | lwz r4, 8(r1) | 445 | lwz r4, 8(r1) |
448 | ld r0, 16(r1) | 446 | ld r0, 16(r1) |
449 | mtcr r4 | 447 | mtcr r4 |
450 | mtlr r0 | 448 | mtlr r0 |
451 | ld r2, 40(r1) | 449 | ld r2, 40(r1) |
452 | 450 | ||
453 | /* Load system default DSCR */ | 451 | /* Load system default DSCR */ |
454 | ld r4, DSCR_DEFAULT@toc(r2) | 452 | ld r4, DSCR_DEFAULT@toc(r2) |
455 | ld r0, 0(r4) | 453 | ld r0, 0(r4) |
456 | mtspr SPRN_DSCR, r0 | 454 | mtspr SPRN_DSCR, r0 |
457 | 455 | ||
458 | blr | 456 | blr |
459 | 457 | ||
460 | /* ****************************************************************** */ | 458 | /* ****************************************************************** */ |
461 | 459 |