Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 356427
b: refs/heads/master
c: fb09692
h: refs/heads/master
i:
  356425: 1f05e06
  356423: a658b06
v: v3
  • Loading branch information
Michael Neuling authored and Benjamin Herrenschmidt committed Feb 15, 2013
1 parent 275be2b commit b88956a
Show file tree
Hide file tree
Showing 2 changed files with 113 additions and 1 deletion.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: a2dcbb32f0647a3b8230c146a2f980654a7738af
refs/heads/master: fb09692e71f13af7298eb603a1975850b1c7a8d8
112 changes: 112 additions & 0 deletions trunk/arch/powerpc/kernel/process.c
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
#include <asm/runlatch.h>
#include <asm/syscalls.h>
#include <asm/switch_to.h>
#include <asm/tm.h>
#include <asm/debug.h>
#ifdef CONFIG_PPC64
#include <asm/firmware.h>
Expand Down Expand Up @@ -467,6 +468,117 @@ static inline bool hw_brk_match(struct arch_hw_breakpoint *a,
return false;
return true;
}
#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
static inline void tm_reclaim_task(struct task_struct *tsk)
{
/* We have to work out if we're switching from/to a task that's in the
* middle of a transaction.
*
* In switching we need to maintain a 2nd register state as
* oldtask->thread.ckpt_regs. We tm_reclaim(oldproc); this saves the
* checkpointed (tbegin) state in ckpt_regs and saves the transactional
* (current) FPRs into oldtask->thread.transact_fpr[].
*
* We also context switch (save) TFHAR/TEXASR/TFIAR in here.
*/
struct thread_struct *thr = &tsk->thread;

if (!thr->regs)
return;

if (!MSR_TM_ACTIVE(thr->regs->msr))
goto out_and_saveregs;

/* Stash the original thread MSR, as giveup_fpu et al will
* modify it. We hold onto it to see whether the task used
* FP & vector regs.
*/
thr->tm_orig_msr = thr->regs->msr;

TM_DEBUG("--- tm_reclaim on pid %d (NIP=%lx, "
"ccr=%lx, msr=%lx, trap=%lx)\n",
tsk->pid, thr->regs->nip,
thr->regs->ccr, thr->regs->msr,
thr->regs->trap);

tm_reclaim(thr, thr->regs->msr, TM_CAUSE_RESCHED);

TM_DEBUG("--- tm_reclaim on pid %d complete\n",
tsk->pid);

out_and_saveregs:
/* Always save the regs here, even if a transaction's not active.
* This context-switches a thread's TM info SPRs. We do it here to
* be consistent with the restore path (in recheckpoint) which
* cannot happen later in _switch().
*/
tm_save_sprs(thr);
}

static inline void __maybe_unused tm_recheckpoint_new_task(struct task_struct *new)
{
unsigned long msr;

if (!cpu_has_feature(CPU_FTR_TM))
return;

/* Recheckpoint the registers of the thread we're about to switch to.
*
* If the task was using FP, we non-lazily reload both the original and
* the speculative FP register states. This is because the kernel
* doesn't see if/when a TM rollback occurs, so if we take an FP
* unavoidable later, we are unable to determine which set of FP regs
* need to be restored.
*/
if (!new->thread.regs)
return;

/* The TM SPRs are restored here, so that TEXASR.FS can be set
* before the trecheckpoint and no explosion occurs.
*/
tm_restore_sprs(&new->thread);

if (!MSR_TM_ACTIVE(new->thread.regs->msr))
return;
msr = new->thread.tm_orig_msr;
/* Recheckpoint to restore original checkpointed register state. */
TM_DEBUG("*** tm_recheckpoint of pid %d "
"(new->msr 0x%lx, new->origmsr 0x%lx)\n",
new->pid, new->thread.regs->msr, msr);

/* This loads the checkpointed FP/VEC state, if used */
tm_recheckpoint(&new->thread, msr);

/* This loads the speculative FP/VEC state, if used */
if (msr & MSR_FP) {
do_load_up_transact_fpu(&new->thread);
new->thread.regs->msr |=
(MSR_FP | new->thread.fpexc_mode);
}
if (msr & MSR_VEC) {
do_load_up_transact_altivec(&new->thread);
new->thread.regs->msr |= MSR_VEC;
}
/* We may as well turn on VSX too since all the state is restored now */
if (msr & MSR_VSX)
new->thread.regs->msr |= MSR_VSX;

TM_DEBUG("*** tm_recheckpoint of pid %d complete "
"(kernel msr 0x%lx)\n",
new->pid, mfmsr());
}

static inline void __switch_to_tm(struct task_struct *prev)
{
if (cpu_has_feature(CPU_FTR_TM)) {
tm_enable();
tm_reclaim_task(prev);
}
}
#else
#define tm_recheckpoint_new_task(new)
#define __switch_to_tm(prev)
#endif /* CONFIG_PPC_TRANSACTIONAL_MEM */

struct task_struct *__switch_to(struct task_struct *prev,
struct task_struct *new)
Expand Down

0 comments on commit b88956a

Please sign in to comment.