Skip to content

Commit 172f7aa

Browse files
cyrilbur-ibmmpe
authored andcommitted
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 <[email protected]> [mpe: Rewrite comment entirely, bugs in it are mine] Signed-off-by: Michael Ellerman <[email protected]>
1 parent d986d6f commit 172f7aa

File tree

1 file changed

+29
-0
lines changed

1 file changed

+29
-0
lines changed

arch/powerpc/kernel/traps.c

+29
Original file line numberDiff line numberDiff line change
@@ -1390,6 +1390,13 @@ void vsx_unavailable_exception(struct pt_regs *regs)
13901390
}
13911391

13921392
#ifdef CONFIG_PPC64
1393+
static 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+
13931400
void facility_unavailable_exception(struct pt_regs *regs)
13941401
{
13951402
static char *facility_strings[] = {
@@ -1469,6 +1476,27 @@ void facility_unavailable_exception(struct pt_regs *regs)
14691476
return;
14701477
}
14711478

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

1512+
out:
14841513
if (user_mode(regs)) {
14851514
_exception(SIGILL, regs, ILL_ILLOPC, regs->nip);
14861515
return;

0 commit comments

Comments
 (0)