Skip to content

Commit

Permalink
powerpc/tm: Add TM Unavailable Exception
Browse files Browse the repository at this point in the history
If the kernel disables transactional memory (TM) and userspace still
tries TM related actions (TM instructions or TM SPR accesses) TM aware
hardware will cause the kernel to take a facility unavailable
exception.

Add checks for the exception being caused by illegal TM access in
userspace.

Signed-off-by: Cyril Bur <cyrilbur@gmail.com>
[mpe: Rewrite comment entirely, bugs in it are mine]
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
  • Loading branch information
Cyril Bur authored and Michael Ellerman committed Oct 4, 2016
1 parent d986d6f commit 172f7aa
Showing 1 changed file with 29 additions and 0 deletions.
29 changes: 29 additions & 0 deletions arch/powerpc/kernel/traps.c
Original file line number Diff line number Diff line change
Expand Up @@ -1390,6 +1390,13 @@ void vsx_unavailable_exception(struct pt_regs *regs)
}

#ifdef CONFIG_PPC64
static void tm_unavailable(struct pt_regs *regs)
{
pr_emerg("Unrecoverable TM Unavailable Exception "
"%lx at %lx\n", regs->trap, regs->nip);
die("Unrecoverable TM Unavailable Exception", regs, SIGABRT);
}

void facility_unavailable_exception(struct pt_regs *regs)
{
static char *facility_strings[] = {
Expand Down Expand Up @@ -1469,6 +1476,27 @@ void facility_unavailable_exception(struct pt_regs *regs)
return;
}

if (status == FSCR_TM_LG) {
/*
* If we're here then the hardware is TM aware because it
* generated an exception with FSRM_TM set.
*
* If cpu_has_feature(CPU_FTR_TM) is false, then either firmware
* told us not to do TM, or the kernel is not built with TM
* support.
*
* If both of those things are true, then userspace can spam the
* console by triggering the printk() below just by continually
* doing tbegin (or any TM instruction). So in that case just
* send the process a SIGILL immediately.
*/
if (!cpu_has_feature(CPU_FTR_TM))
goto out;

tm_unavailable(regs);
return;
}

if ((status < ARRAY_SIZE(facility_strings)) &&
facility_strings[status])
facility = facility_strings[status];
Expand All @@ -1481,6 +1509,7 @@ void facility_unavailable_exception(struct pt_regs *regs)
"%sFacility '%s' unavailable, exception at 0x%lx, MSR=%lx\n",
hv ? "Hypervisor " : "", facility, regs->nip, regs->msr);

out:
if (user_mode(regs)) {
_exception(SIGILL, regs, ILL_ILLOPC, regs->nip);
return;
Expand Down

0 comments on commit 172f7aa

Please sign in to comment.