aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCyril Bur <cyrilbur@gmail.com>2016-09-14 04:02:15 -0400
committerMichael Ellerman <mpe@ellerman.id.au>2016-10-04 05:33:17 -0400
commit172f7aaa75d0eaae167edde25c08aae9059e80fc (patch)
tree8c9cfd2f82424e77f5d870d2260bfd4e241c5fc2
parentd986d6f4d0ee30ad096ed7e59670f56ca8f23b57 (diff)
powerpc/tm: Add TM Unavailable Exception
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>
-rw-r--r--arch/powerpc/kernel/traps.c29
1 files changed, 29 insertions, 0 deletions
diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c
index 487e1b442473..2f5ef5a80353 100644
--- a/arch/powerpc/kernel/traps.c
+++ b/arch/powerpc/kernel/traps.c
@@ -1390,6 +1390,13 @@ void vsx_unavailable_exception(struct pt_regs *regs)
1390} 1390}
1391 1391
1392#ifdef CONFIG_PPC64 1392#ifdef CONFIG_PPC64
1393static void tm_unavailable(struct pt_regs *regs)
1394{
1395 pr_emerg("Unrecoverable TM Unavailable Exception "
1396 "%lx at %lx\n", regs->trap, regs->nip);
1397 die("Unrecoverable TM Unavailable Exception", regs, SIGABRT);
1398}
1399
1393void facility_unavailable_exception(struct pt_regs *regs) 1400void facility_unavailable_exception(struct pt_regs *regs)
1394{ 1401{
1395 static char *facility_strings[] = { 1402 static char *facility_strings[] = {
@@ -1469,6 +1476,27 @@ void facility_unavailable_exception(struct pt_regs *regs)
1469 return; 1476 return;
1470 } 1477 }
1471 1478
1479 if (status == FSCR_TM_LG) {
1480 /*
1481 * If we're here then the hardware is TM aware because it
1482 * generated an exception with FSRM_TM set.
1483 *
1484 * If cpu_has_feature(CPU_FTR_TM) is false, then either firmware
1485 * told us not to do TM, or the kernel is not built with TM
1486 * support.
1487 *
1488 * If both of those things are true, then userspace can spam the
1489 * console by triggering the printk() below just by continually
1490 * doing tbegin (or any TM instruction). So in that case just
1491 * send the process a SIGILL immediately.
1492 */
1493 if (!cpu_has_feature(CPU_FTR_TM))
1494 goto out;
1495
1496 tm_unavailable(regs);
1497 return;
1498 }
1499
1472 if ((status < ARRAY_SIZE(facility_strings)) && 1500 if ((status < ARRAY_SIZE(facility_strings)) &&
1473 facility_strings[status]) 1501 facility_strings[status])
1474 facility = facility_strings[status]; 1502 facility = facility_strings[status];
@@ -1481,6 +1509,7 @@ void facility_unavailable_exception(struct pt_regs *regs)
1481 "%sFacility '%s' unavailable, exception at 0x%lx, MSR=%lx\n", 1509 "%sFacility '%s' unavailable, exception at 0x%lx, MSR=%lx\n",
1482 hv ? "Hypervisor " : "", facility, regs->nip, regs->msr); 1510 hv ? "Hypervisor " : "", facility, regs->nip, regs->msr);
1483 1511
1512out:
1484 if (user_mode(regs)) { 1513 if (user_mode(regs)) {
1485 _exception(SIGILL, regs, ILL_ILLOPC, regs->nip); 1514 _exception(SIGILL, regs, ILL_ILLOPC, regs->nip);
1486 return; 1515 return;