diff options
author | Michael Neuling <mikey@neuling.org> | 2013-09-25 23:29:09 -0400 |
---|---|---|
committer | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2013-10-03 03:25:51 -0400 |
commit | e9bdc3d6143d1c4b8d8ce5231fc958268331f983 (patch) | |
tree | 1892620b40d70713d28dfdaf266ad993e41248eb /arch/powerpc | |
parent | c69e63b0f135fa51d6e1c38b5ac8a1def15ea3fa (diff) |
powerpc/tm: Switch out userspace PPR and DSCR sooner
When we do a treclaim or trecheckpoint we end up running with userspace
PPR and DSCR values. Currently we don't do anything special to avoid
running with user values which could cause a severe performance
degradation.
This patch moves the PPR and DSCR save and restore around treclaim and
trecheckpoint so that we run with user values for a much shorter period.
More care is taken with the PPR as it's impact is greater than the DSCR.
This is similar to user exceptions, where we run HTM_MEDIUM early to
ensure that we don't run with a userspace PPR values in the kernel.
Signed-off-by: Michael Neuling <mikey@neuling.org>
Cc: <stable@vger.kernel.org> # 3.9+
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Diffstat (limited to 'arch/powerpc')
-rw-r--r-- | arch/powerpc/kernel/tm.S | 94 |
1 files changed, 63 insertions, 31 deletions
diff --git a/arch/powerpc/kernel/tm.S b/arch/powerpc/kernel/tm.S index 8ece1908be1a..cd809eaa8b5c 100644 --- a/arch/powerpc/kernel/tm.S +++ b/arch/powerpc/kernel/tm.S | |||
@@ -79,6 +79,11 @@ _GLOBAL(tm_abort) | |||
79 | TABORT(R3) | 79 | TABORT(R3) |
80 | blr | 80 | blr |
81 | 81 | ||
82 | .section ".toc","aw" | ||
83 | DSCR_DEFAULT: | ||
84 | .tc dscr_default[TC],dscr_default | ||
85 | |||
86 | .section ".text" | ||
82 | 87 | ||
83 | /* void tm_reclaim(struct thread_struct *thread, | 88 | /* void tm_reclaim(struct thread_struct *thread, |
84 | * unsigned long orig_msr, | 89 | * unsigned long orig_msr, |
@@ -188,11 +193,18 @@ dont_backup_fp: | |||
188 | std r1, PACATMSCRATCH(r13) | 193 | std r1, PACATMSCRATCH(r13) |
189 | ld r1, PACAR1(r13) | 194 | ld r1, PACAR1(r13) |
190 | 195 | ||
196 | /* Store the PPR in r11 and reset to decent value */ | ||
197 | std r11, GPR11(r1) /* Temporary stash */ | ||
198 | mfspr r11, SPRN_PPR | ||
199 | HMT_MEDIUM | ||
200 | |||
191 | /* Now get some more GPRS free */ | 201 | /* Now get some more GPRS free */ |
192 | std r7, GPR7(r1) /* Temporary stash */ | 202 | std r7, GPR7(r1) /* Temporary stash */ |
193 | std r12, GPR12(r1) /* '' '' '' */ | 203 | std r12, GPR12(r1) /* '' '' '' */ |
194 | ld r12, STACK_PARAM(0)(r1) /* Param 0, thread_struct * */ | 204 | ld r12, STACK_PARAM(0)(r1) /* Param 0, thread_struct * */ |
195 | 205 | ||
206 | std r11, THREAD_TM_PPR(r12) /* Store PPR and free r11 */ | ||
207 | |||
196 | addi r7, r12, PT_CKPT_REGS /* Thread's ckpt_regs */ | 208 | addi r7, r12, PT_CKPT_REGS /* Thread's ckpt_regs */ |
197 | 209 | ||
198 | /* Make r7 look like an exception frame so that we | 210 | /* Make r7 look like an exception frame so that we |
@@ -204,15 +216,19 @@ dont_backup_fp: | |||
204 | SAVE_GPR(0, r7) /* user r0 */ | 216 | SAVE_GPR(0, r7) /* user r0 */ |
205 | SAVE_GPR(2, r7) /* user r2 */ | 217 | SAVE_GPR(2, r7) /* user r2 */ |
206 | SAVE_4GPRS(3, r7) /* user r3-r6 */ | 218 | SAVE_4GPRS(3, r7) /* user r3-r6 */ |
207 | SAVE_4GPRS(8, r7) /* user r8-r11 */ | 219 | SAVE_GPR(8, r7) /* user r8 */ |
220 | SAVE_GPR(9, r7) /* user r9 */ | ||
221 | SAVE_GPR(10, r7) /* user r10 */ | ||
208 | ld r3, PACATMSCRATCH(r13) /* user r1 */ | 222 | ld r3, PACATMSCRATCH(r13) /* user r1 */ |
209 | ld r4, GPR7(r1) /* user r7 */ | 223 | ld r4, GPR7(r1) /* user r7 */ |
210 | ld r5, GPR12(r1) /* user r12 */ | 224 | ld r5, GPR11(r1) /* user r11 */ |
211 | GET_SCRATCH0(6) /* user r13 */ | 225 | ld r6, GPR12(r1) /* user r12 */ |
226 | GET_SCRATCH0(8) /* user r13 */ | ||
212 | std r3, GPR1(r7) | 227 | std r3, GPR1(r7) |
213 | std r4, GPR7(r7) | 228 | std r4, GPR7(r7) |
214 | std r5, GPR12(r7) | 229 | std r5, GPR11(r7) |
215 | std r6, GPR13(r7) | 230 | std r6, GPR12(r7) |
231 | std r8, GPR13(r7) | ||
216 | 232 | ||
217 | SAVE_NVGPRS(r7) /* user r14-r31 */ | 233 | SAVE_NVGPRS(r7) /* user r14-r31 */ |
218 | 234 | ||
@@ -235,14 +251,12 @@ dont_backup_fp: | |||
235 | std r6, _XER(r7) | 251 | std r6, _XER(r7) |
236 | 252 | ||
237 | 253 | ||
238 | /* ******************** TAR, PPR, DSCR ********** */ | 254 | /* ******************** TAR, DSCR ********** */ |
239 | mfspr r3, SPRN_TAR | 255 | mfspr r3, SPRN_TAR |
240 | mfspr r4, SPRN_PPR | 256 | mfspr r4, SPRN_DSCR |
241 | mfspr r5, SPRN_DSCR | ||
242 | 257 | ||
243 | std r3, THREAD_TM_TAR(r12) | 258 | std r3, THREAD_TM_TAR(r12) |
244 | std r4, THREAD_TM_PPR(r12) | 259 | std r4, THREAD_TM_DSCR(r12) |
245 | std r5, THREAD_TM_DSCR(r12) | ||
246 | 260 | ||
247 | /* MSR and flags: We don't change CRs, and we don't need to alter | 261 | /* MSR and flags: We don't change CRs, and we don't need to alter |
248 | * MSR. | 262 | * MSR. |
@@ -259,7 +273,7 @@ dont_backup_fp: | |||
259 | std r3, THREAD_TM_TFHAR(r12) | 273 | std r3, THREAD_TM_TFHAR(r12) |
260 | std r4, THREAD_TM_TFIAR(r12) | 274 | std r4, THREAD_TM_TFIAR(r12) |
261 | 275 | ||
262 | /* AMR and PPR are checkpointed too, but are unsupported by Linux. */ | 276 | /* AMR is checkpointed too, but is unsupported by Linux. */ |
263 | 277 | ||
264 | /* Restore original MSR/IRQ state & clear TM mode */ | 278 | /* Restore original MSR/IRQ state & clear TM mode */ |
265 | ld r14, TM_FRAME_L0(r1) /* Orig MSR */ | 279 | ld r14, TM_FRAME_L0(r1) /* Orig MSR */ |
@@ -275,6 +289,12 @@ dont_backup_fp: | |||
275 | mtcr r4 | 289 | mtcr r4 |
276 | mtlr r0 | 290 | mtlr r0 |
277 | ld r2, 40(r1) | 291 | ld r2, 40(r1) |
292 | |||
293 | /* Load system default DSCR */ | ||
294 | ld r4, DSCR_DEFAULT@toc(r2) | ||
295 | ld r0, 0(r4) | ||
296 | mtspr SPRN_DSCR, r0 | ||
297 | |||
278 | blr | 298 | blr |
279 | 299 | ||
280 | 300 | ||
@@ -359,25 +379,24 @@ dont_restore_fp: | |||
359 | 379 | ||
360 | restore_gprs: | 380 | restore_gprs: |
361 | 381 | ||
362 | /* ******************** TAR, PPR, DSCR ********** */ | 382 | /* ******************** CR,LR,CCR,MSR ********** */ |
363 | ld r4, THREAD_TM_TAR(r3) | 383 | ld r4, _CTR(r7) |
364 | ld r5, THREAD_TM_PPR(r3) | 384 | ld r5, _LINK(r7) |
365 | ld r6, THREAD_TM_DSCR(r3) | 385 | ld r6, _CCR(r7) |
386 | ld r8, _XER(r7) | ||
366 | 387 | ||
367 | mtspr SPRN_TAR, r4 | 388 | mtctr r4 |
368 | mtspr SPRN_PPR, r5 | 389 | mtlr r5 |
369 | mtspr SPRN_DSCR, r6 | 390 | mtcr r6 |
391 | mtxer r8 | ||
370 | 392 | ||
371 | /* ******************** CR,LR,CCR,MSR ********** */ | 393 | /* ******************** TAR ******************** */ |
372 | ld r3, _CTR(r7) | 394 | ld r4, THREAD_TM_TAR(r3) |
373 | ld r4, _LINK(r7) | 395 | mtspr SPRN_TAR, r4 |
374 | ld r5, _CCR(r7) | ||
375 | ld r6, _XER(r7) | ||
376 | 396 | ||
377 | mtctr r3 | 397 | /* Load up the PPR and DSCR in GPRs only at this stage */ |
378 | mtlr r4 | 398 | ld r5, THREAD_TM_DSCR(r3) |
379 | mtcr r5 | 399 | ld r6, THREAD_TM_PPR(r3) |
380 | mtxer r6 | ||
381 | 400 | ||
382 | /* Clear the MSR RI since we are about to change R1. EE is already off | 401 | /* Clear the MSR RI since we are about to change R1. EE is already off |
383 | */ | 402 | */ |
@@ -385,19 +404,26 @@ restore_gprs: | |||
385 | mtmsrd r4, 1 | 404 | mtmsrd r4, 1 |
386 | 405 | ||
387 | REST_4GPRS(0, r7) /* GPR0-3 */ | 406 | REST_4GPRS(0, r7) /* GPR0-3 */ |
388 | REST_GPR(4, r7) /* GPR4-6 */ | 407 | REST_GPR(4, r7) /* GPR4 */ |
389 | REST_GPR(5, r7) | ||
390 | REST_GPR(6, r7) | ||
391 | REST_4GPRS(8, r7) /* GPR8-11 */ | 408 | REST_4GPRS(8, r7) /* GPR8-11 */ |
392 | REST_2GPRS(12, r7) /* GPR12-13 */ | 409 | REST_2GPRS(12, r7) /* GPR12-13 */ |
393 | 410 | ||
394 | REST_NVGPRS(r7) /* GPR14-31 */ | 411 | REST_NVGPRS(r7) /* GPR14-31 */ |
395 | 412 | ||
396 | ld r7, GPR7(r7) /* GPR7 */ | 413 | /* Load up PPR and DSCR here so we don't run with user values for long |
414 | */ | ||
415 | mtspr SPRN_DSCR, r5 | ||
416 | mtspr SPRN_PPR, r6 | ||
417 | |||
418 | REST_GPR(5, r7) /* GPR5-7 */ | ||
419 | REST_GPR(6, r7) | ||
420 | ld r7, GPR7(r7) | ||
397 | 421 | ||
398 | /* Commit register state as checkpointed state: */ | 422 | /* Commit register state as checkpointed state: */ |
399 | TRECHKPT | 423 | TRECHKPT |
400 | 424 | ||
425 | HMT_MEDIUM | ||
426 | |||
401 | /* Our transactional state has now changed. | 427 | /* Our transactional state has now changed. |
402 | * | 428 | * |
403 | * Now just get out of here. Transactional (current) state will be | 429 | * Now just get out of here. Transactional (current) state will be |
@@ -420,6 +446,12 @@ restore_gprs: | |||
420 | mtcr r4 | 446 | mtcr r4 |
421 | mtlr r0 | 447 | mtlr r0 |
422 | ld r2, 40(r1) | 448 | ld r2, 40(r1) |
449 | |||
450 | /* Load system default DSCR */ | ||
451 | ld r4, DSCR_DEFAULT@toc(r2) | ||
452 | ld r0, 0(r4) | ||
453 | mtspr SPRN_DSCR, r0 | ||
454 | |||
423 | blr | 455 | blr |
424 | 456 | ||
425 | /* ****************************************************************** */ | 457 | /* ****************************************************************** */ |