aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/kernel/process.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/kernel/process.c')
-rw-r--r--arch/powerpc/kernel/process.c241
1 files changed, 220 insertions, 21 deletions
diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c
index 81430674e71c..59dd545fdde1 100644
--- a/arch/powerpc/kernel/process.c
+++ b/arch/powerpc/kernel/process.c
@@ -50,6 +50,7 @@
50#include <asm/runlatch.h> 50#include <asm/runlatch.h>
51#include <asm/syscalls.h> 51#include <asm/syscalls.h>
52#include <asm/switch_to.h> 52#include <asm/switch_to.h>
53#include <asm/tm.h>
53#include <asm/debug.h> 54#include <asm/debug.h>
54#ifdef CONFIG_PPC64 55#ifdef CONFIG_PPC64
55#include <asm/firmware.h> 56#include <asm/firmware.h>
@@ -57,6 +58,13 @@
57#include <linux/kprobes.h> 58#include <linux/kprobes.h>
58#include <linux/kdebug.h> 59#include <linux/kdebug.h>
59 60
61/* Transactional Memory debug */
62#ifdef TM_DEBUG_SW
63#define TM_DEBUG(x...) printk(KERN_INFO x)
64#else
65#define TM_DEBUG(x...) do { } while(0)
66#endif
67
60extern unsigned long _get_SP(void); 68extern unsigned long _get_SP(void);
61 69
62#ifndef CONFIG_SMP 70#ifndef CONFIG_SMP
@@ -271,7 +279,7 @@ void do_send_trap(struct pt_regs *regs, unsigned long address,
271 force_sig_info(SIGTRAP, &info, current); 279 force_sig_info(SIGTRAP, &info, current);
272} 280}
273#else /* !CONFIG_PPC_ADV_DEBUG_REGS */ 281#else /* !CONFIG_PPC_ADV_DEBUG_REGS */
274void do_dabr(struct pt_regs *regs, unsigned long address, 282void do_break (struct pt_regs *regs, unsigned long address,
275 unsigned long error_code) 283 unsigned long error_code)
276{ 284{
277 siginfo_t info; 285 siginfo_t info;
@@ -281,11 +289,11 @@ void do_dabr(struct pt_regs *regs, unsigned long address,
281 11, SIGSEGV) == NOTIFY_STOP) 289 11, SIGSEGV) == NOTIFY_STOP)
282 return; 290 return;
283 291
284 if (debugger_dabr_match(regs)) 292 if (debugger_break_match(regs))
285 return; 293 return;
286 294
287 /* Clear the DABR */ 295 /* Clear the breakpoint */
288 set_dabr(0, 0); 296 hw_breakpoint_disable();
289 297
290 /* Deliver the signal to userspace */ 298 /* Deliver the signal to userspace */
291 info.si_signo = SIGTRAP; 299 info.si_signo = SIGTRAP;
@@ -296,7 +304,7 @@ void do_dabr(struct pt_regs *regs, unsigned long address,
296} 304}
297#endif /* CONFIG_PPC_ADV_DEBUG_REGS */ 305#endif /* CONFIG_PPC_ADV_DEBUG_REGS */
298 306
299static DEFINE_PER_CPU(unsigned long, current_dabr); 307static DEFINE_PER_CPU(struct arch_hw_breakpoint, current_brk);
300 308
301#ifdef CONFIG_PPC_ADV_DEBUG_REGS 309#ifdef CONFIG_PPC_ADV_DEBUG_REGS
302/* 310/*
@@ -364,39 +372,214 @@ static void switch_booke_debug_regs(struct thread_struct *new_thread)
364#ifndef CONFIG_HAVE_HW_BREAKPOINT 372#ifndef CONFIG_HAVE_HW_BREAKPOINT
365static void set_debug_reg_defaults(struct thread_struct *thread) 373static void set_debug_reg_defaults(struct thread_struct *thread)
366{ 374{
367 if (thread->dabr) { 375 thread->hw_brk.address = 0;
368 thread->dabr = 0; 376 thread->hw_brk.type = 0;
369 thread->dabrx = 0; 377 set_breakpoint(&thread->hw_brk);
370 set_dabr(0, 0);
371 }
372} 378}
373#endif /* !CONFIG_HAVE_HW_BREAKPOINT */ 379#endif /* !CONFIG_HAVE_HW_BREAKPOINT */
374#endif /* CONFIG_PPC_ADV_DEBUG_REGS */ 380#endif /* CONFIG_PPC_ADV_DEBUG_REGS */
375 381
376int set_dabr(unsigned long dabr, unsigned long dabrx)
377{
378 __get_cpu_var(current_dabr) = dabr;
379
380 if (ppc_md.set_dabr)
381 return ppc_md.set_dabr(dabr, dabrx);
382
383 /* XXX should we have a CPU_FTR_HAS_DABR ? */
384#ifdef CONFIG_PPC_ADV_DEBUG_REGS 382#ifdef CONFIG_PPC_ADV_DEBUG_REGS
383static inline int __set_dabr(unsigned long dabr, unsigned long dabrx)
384{
385 mtspr(SPRN_DAC1, dabr); 385 mtspr(SPRN_DAC1, dabr);
386#ifdef CONFIG_PPC_47x 386#ifdef CONFIG_PPC_47x
387 isync(); 387 isync();
388#endif 388#endif
389 return 0;
390}
389#elif defined(CONFIG_PPC_BOOK3S) 391#elif defined(CONFIG_PPC_BOOK3S)
392static inline int __set_dabr(unsigned long dabr, unsigned long dabrx)
393{
390 mtspr(SPRN_DABR, dabr); 394 mtspr(SPRN_DABR, dabr);
391 mtspr(SPRN_DABRX, dabrx); 395 mtspr(SPRN_DABRX, dabrx);
396 return 0;
397}
398#else
399static inline int __set_dabr(unsigned long dabr, unsigned long dabrx)
400{
401 return -EINVAL;
402}
392#endif 403#endif
404
405static inline int set_dabr(struct arch_hw_breakpoint *brk)
406{
407 unsigned long dabr, dabrx;
408
409 dabr = brk->address | (brk->type & HW_BRK_TYPE_DABR);
410 dabrx = ((brk->type >> 3) & 0x7);
411
412 if (ppc_md.set_dabr)
413 return ppc_md.set_dabr(dabr, dabrx);
414
415 return __set_dabr(dabr, dabrx);
416}
417
418static inline int set_dawr(struct arch_hw_breakpoint *brk)
419{
420 unsigned long dawr, dawrx, mrd;
421
422 dawr = brk->address;
423
424 dawrx = (brk->type & (HW_BRK_TYPE_READ | HW_BRK_TYPE_WRITE)) \
425 << (63 - 58); //* read/write bits */
426 dawrx |= ((brk->type & (HW_BRK_TYPE_TRANSLATE)) >> 2) \
427 << (63 - 59); //* translate */
428 dawrx |= (brk->type & (HW_BRK_TYPE_PRIV_ALL)) \
429 >> 3; //* PRIM bits */
430 /* dawr length is stored in field MDR bits 48:53. Matches range in
431 doublewords (64 bits) baised by -1 eg. 0b000000=1DW and
432 0b111111=64DW.
433 brk->len is in bytes.
434 This aligns up to double word size, shifts and does the bias.
435 */
436 mrd = ((brk->len + 7) >> 3) - 1;
437 dawrx |= (mrd & 0x3f) << (63 - 53);
438
439 if (ppc_md.set_dawr)
440 return ppc_md.set_dawr(dawr, dawrx);
441 mtspr(SPRN_DAWR, dawr);
442 mtspr(SPRN_DAWRX, dawrx);
393 return 0; 443 return 0;
394} 444}
395 445
446int set_breakpoint(struct arch_hw_breakpoint *brk)
447{
448 __get_cpu_var(current_brk) = *brk;
449
450 if (cpu_has_feature(CPU_FTR_DAWR))
451 return set_dawr(brk);
452
453 return set_dabr(brk);
454}
455
396#ifdef CONFIG_PPC64 456#ifdef CONFIG_PPC64
397DEFINE_PER_CPU(struct cpu_usage, cpu_usage_array); 457DEFINE_PER_CPU(struct cpu_usage, cpu_usage_array);
398#endif 458#endif
399 459
460static inline bool hw_brk_match(struct arch_hw_breakpoint *a,
461 struct arch_hw_breakpoint *b)
462{
463 if (a->address != b->address)
464 return false;
465 if (a->type != b->type)
466 return false;
467 if (a->len != b->len)
468 return false;
469 return true;
470}
471#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
472static inline void tm_reclaim_task(struct task_struct *tsk)
473{
474 /* We have to work out if we're switching from/to a task that's in the
475 * middle of a transaction.
476 *
477 * In switching we need to maintain a 2nd register state as
478 * oldtask->thread.ckpt_regs. We tm_reclaim(oldproc); this saves the
479 * checkpointed (tbegin) state in ckpt_regs and saves the transactional
480 * (current) FPRs into oldtask->thread.transact_fpr[].
481 *
482 * We also context switch (save) TFHAR/TEXASR/TFIAR in here.
483 */
484 struct thread_struct *thr = &tsk->thread;
485
486 if (!thr->regs)
487 return;
488
489 if (!MSR_TM_ACTIVE(thr->regs->msr))
490 goto out_and_saveregs;
491
492 /* Stash the original thread MSR, as giveup_fpu et al will
493 * modify it. We hold onto it to see whether the task used
494 * FP & vector regs.
495 */
496 thr->tm_orig_msr = thr->regs->msr;
497
498 TM_DEBUG("--- tm_reclaim on pid %d (NIP=%lx, "
499 "ccr=%lx, msr=%lx, trap=%lx)\n",
500 tsk->pid, thr->regs->nip,
501 thr->regs->ccr, thr->regs->msr,
502 thr->regs->trap);
503
504 tm_reclaim(thr, thr->regs->msr, TM_CAUSE_RESCHED);
505
506 TM_DEBUG("--- tm_reclaim on pid %d complete\n",
507 tsk->pid);
508
509out_and_saveregs:
510 /* Always save the regs here, even if a transaction's not active.
511 * This context-switches a thread's TM info SPRs. We do it here to
512 * be consistent with the restore path (in recheckpoint) which
513 * cannot happen later in _switch().
514 */
515 tm_save_sprs(thr);
516}
517
518static inline void tm_recheckpoint_new_task(struct task_struct *new)
519{
520 unsigned long msr;
521
522 if (!cpu_has_feature(CPU_FTR_TM))
523 return;
524
525 /* Recheckpoint the registers of the thread we're about to switch to.
526 *
527 * If the task was using FP, we non-lazily reload both the original and
528 * the speculative FP register states. This is because the kernel
529 * doesn't see if/when a TM rollback occurs, so if we take an FP
530 * unavoidable later, we are unable to determine which set of FP regs
531 * need to be restored.
532 */
533 if (!new->thread.regs)
534 return;
535
536 /* The TM SPRs are restored here, so that TEXASR.FS can be set
537 * before the trecheckpoint and no explosion occurs.
538 */
539 tm_restore_sprs(&new->thread);
540
541 if (!MSR_TM_ACTIVE(new->thread.regs->msr))
542 return;
543 msr = new->thread.tm_orig_msr;
544 /* Recheckpoint to restore original checkpointed register state. */
545 TM_DEBUG("*** tm_recheckpoint of pid %d "
546 "(new->msr 0x%lx, new->origmsr 0x%lx)\n",
547 new->pid, new->thread.regs->msr, msr);
548
549 /* This loads the checkpointed FP/VEC state, if used */
550 tm_recheckpoint(&new->thread, msr);
551
552 /* This loads the speculative FP/VEC state, if used */
553 if (msr & MSR_FP) {
554 do_load_up_transact_fpu(&new->thread);
555 new->thread.regs->msr |=
556 (MSR_FP | new->thread.fpexc_mode);
557 }
558 if (msr & MSR_VEC) {
559 do_load_up_transact_altivec(&new->thread);
560 new->thread.regs->msr |= MSR_VEC;
561 }
562 /* We may as well turn on VSX too since all the state is restored now */
563 if (msr & MSR_VSX)
564 new->thread.regs->msr |= MSR_VSX;
565
566 TM_DEBUG("*** tm_recheckpoint of pid %d complete "
567 "(kernel msr 0x%lx)\n",
568 new->pid, mfmsr());
569}
570
571static inline void __switch_to_tm(struct task_struct *prev)
572{
573 if (cpu_has_feature(CPU_FTR_TM)) {
574 tm_enable();
575 tm_reclaim_task(prev);
576 }
577}
578#else
579#define tm_recheckpoint_new_task(new)
580#define __switch_to_tm(prev)
581#endif /* CONFIG_PPC_TRANSACTIONAL_MEM */
582
400struct task_struct *__switch_to(struct task_struct *prev, 583struct task_struct *__switch_to(struct task_struct *prev,
401 struct task_struct *new) 584 struct task_struct *new)
402{ 585{
@@ -407,6 +590,8 @@ struct task_struct *__switch_to(struct task_struct *prev,
407 struct ppc64_tlb_batch *batch; 590 struct ppc64_tlb_batch *batch;
408#endif 591#endif
409 592
593 __switch_to_tm(prev);
594
410#ifdef CONFIG_SMP 595#ifdef CONFIG_SMP
411 /* avoid complexity of lazy save/restore of fpu 596 /* avoid complexity of lazy save/restore of fpu
412 * by just saving it every time we switch out if 597 * by just saving it every time we switch out if
@@ -481,8 +666,8 @@ struct task_struct *__switch_to(struct task_struct *prev,
481 * schedule DABR 666 * schedule DABR
482 */ 667 */
483#ifndef CONFIG_HAVE_HW_BREAKPOINT 668#ifndef CONFIG_HAVE_HW_BREAKPOINT
484 if (unlikely(__get_cpu_var(current_dabr) != new->thread.dabr)) 669 if (unlikely(hw_brk_match(&__get_cpu_var(current_brk), &new->thread.hw_brk)))
485 set_dabr(new->thread.dabr, new->thread.dabrx); 670 set_breakpoint(&new->thread.hw_brk);
486#endif /* CONFIG_HAVE_HW_BREAKPOINT */ 671#endif /* CONFIG_HAVE_HW_BREAKPOINT */
487#endif 672#endif
488 673
@@ -522,6 +707,9 @@ struct task_struct *__switch_to(struct task_struct *prev,
522 * of sync. Hard disable here. 707 * of sync. Hard disable here.
523 */ 708 */
524 hard_irq_disable(); 709 hard_irq_disable();
710
711 tm_recheckpoint_new_task(new);
712
525 last = _switch(old_thread, new_thread); 713 last = _switch(old_thread, new_thread);
526 714
527#ifdef CONFIG_PPC_BOOK3S_64 715#ifdef CONFIG_PPC_BOOK3S_64
@@ -683,6 +871,9 @@ void show_regs(struct pt_regs * regs)
683 printk("NIP ["REG"] %pS\n", regs->nip, (void *)regs->nip); 871 printk("NIP ["REG"] %pS\n", regs->nip, (void *)regs->nip);
684 printk("LR ["REG"] %pS\n", regs->link, (void *)regs->link); 872 printk("LR ["REG"] %pS\n", regs->link, (void *)regs->link);
685#endif 873#endif
874#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
875 printk("PACATMSCRATCH [%llx]\n", get_paca()->tm_scratch);
876#endif
686 show_stack(current, (unsigned long *) regs->gpr[1]); 877 show_stack(current, (unsigned long *) regs->gpr[1]);
687 if (!user_mode(regs)) 878 if (!user_mode(regs))
688 show_instructions(regs); 879 show_instructions(regs);
@@ -813,6 +1004,8 @@ int copy_thread(unsigned long clone_flags, unsigned long usp,
813 p->thread.dscr_inherit = current->thread.dscr_inherit; 1004 p->thread.dscr_inherit = current->thread.dscr_inherit;
814 p->thread.dscr = current->thread.dscr; 1005 p->thread.dscr = current->thread.dscr;
815 } 1006 }
1007 if (cpu_has_feature(CPU_FTR_HAS_PPR))
1008 p->thread.ppr = INIT_PPR;
816#endif 1009#endif
817 /* 1010 /*
818 * The PPC64 ABI makes use of a TOC to contain function 1011 * The PPC64 ABI makes use of a TOC to contain function
@@ -892,7 +1085,6 @@ void start_thread(struct pt_regs *regs, unsigned long start, unsigned long sp)
892 regs->msr = MSR_USER32; 1085 regs->msr = MSR_USER32;
893 } 1086 }
894#endif 1087#endif
895
896 discard_lazy_cpu_state(); 1088 discard_lazy_cpu_state();
897#ifdef CONFIG_VSX 1089#ifdef CONFIG_VSX
898 current->thread.used_vsr = 0; 1090 current->thread.used_vsr = 0;
@@ -912,6 +1104,13 @@ void start_thread(struct pt_regs *regs, unsigned long start, unsigned long sp)
912 current->thread.spefscr = 0; 1104 current->thread.spefscr = 0;
913 current->thread.used_spe = 0; 1105 current->thread.used_spe = 0;
914#endif /* CONFIG_SPE */ 1106#endif /* CONFIG_SPE */
1107#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
1108 if (cpu_has_feature(CPU_FTR_TM))
1109 regs->msr |= MSR_TM;
1110 current->thread.tm_tfhar = 0;
1111 current->thread.tm_texasr = 0;
1112 current->thread.tm_tfiar = 0;
1113#endif /* CONFIG_PPC_TRANSACTIONAL_MEM */
915} 1114}
916 1115
917#define PR_FP_ALL_EXCEPT (PR_FP_EXC_DIV | PR_FP_EXC_OVF | PR_FP_EXC_UND \ 1116#define PR_FP_ALL_EXCEPT (PR_FP_EXC_DIV | PR_FP_EXC_OVF | PR_FP_EXC_UND \