aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/kernel/traps.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/kernel/traps.c')
-rw-r--r--arch/powerpc/kernel/traps.c58
1 files changed, 34 insertions, 24 deletions
diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c
index bf33c22e38a4..e435bc089ea3 100644
--- a/arch/powerpc/kernel/traps.c
+++ b/arch/powerpc/kernel/traps.c
@@ -44,9 +44,7 @@
44#include <asm/machdep.h> 44#include <asm/machdep.h>
45#include <asm/rtas.h> 45#include <asm/rtas.h>
46#include <asm/pmc.h> 46#include <asm/pmc.h>
47#ifdef CONFIG_PPC32
48#include <asm/reg.h> 47#include <asm/reg.h>
49#endif
50#ifdef CONFIG_PMAC_BACKLIGHT 48#ifdef CONFIG_PMAC_BACKLIGHT
51#include <asm/backlight.h> 49#include <asm/backlight.h>
52#endif 50#endif
@@ -1296,43 +1294,54 @@ void vsx_unavailable_exception(struct pt_regs *regs)
1296 die("Unrecoverable VSX Unavailable Exception", regs, SIGABRT); 1294 die("Unrecoverable VSX Unavailable Exception", regs, SIGABRT);
1297} 1295}
1298 1296
1297#ifdef CONFIG_PPC64
1299void facility_unavailable_exception(struct pt_regs *regs) 1298void facility_unavailable_exception(struct pt_regs *regs)
1300{ 1299{
1301 static char *facility_strings[] = { 1300 static char *facility_strings[] = {
1302 "FPU", 1301 [FSCR_FP_LG] = "FPU",
1303 "VMX/VSX", 1302 [FSCR_VECVSX_LG] = "VMX/VSX",
1304 "DSCR", 1303 [FSCR_DSCR_LG] = "DSCR",
1305 "PMU SPRs", 1304 [FSCR_PM_LG] = "PMU SPRs",
1306 "BHRB", 1305 [FSCR_BHRB_LG] = "BHRB",
1307 "TM", 1306 [FSCR_TM_LG] = "TM",
1308 "AT", 1307 [FSCR_EBB_LG] = "EBB",
1309 "EBB", 1308 [FSCR_TAR_LG] = "TAR",
1310 "TAR",
1311 }; 1309 };
1312 char *facility, *prefix; 1310 char *facility = "unknown";
1313 u64 value; 1311 u64 value;
1312 u8 status;
1313 bool hv;
1314 1314
1315 if (regs->trap == 0xf60) { 1315 hv = (regs->trap == 0xf80);
1316 value = mfspr(SPRN_FSCR); 1316 if (hv)
1317 prefix = "";
1318 } else {
1319 value = mfspr(SPRN_HFSCR); 1317 value = mfspr(SPRN_HFSCR);
1320 prefix = "Hypervisor "; 1318 else
1319 value = mfspr(SPRN_FSCR);
1320
1321 status = value >> 56;
1322 if (status == FSCR_DSCR_LG) {
1323 /* User is acessing the DSCR. Set the inherit bit and allow
1324 * the user to set it directly in future by setting via the
1325 * H/FSCR DSCR bit.
1326 */
1327 current->thread.dscr_inherit = 1;
1328 if (hv)
1329 mtspr(SPRN_HFSCR, value | HFSCR_DSCR);
1330 else
1331 mtspr(SPRN_FSCR, value | FSCR_DSCR);
1332 return;
1321 } 1333 }
1322 1334
1323 value = value >> 56; 1335 if ((status < ARRAY_SIZE(facility_strings)) &&
1336 facility_strings[status])
1337 facility = facility_strings[status];
1324 1338
1325 /* We restore the interrupt state now */ 1339 /* We restore the interrupt state now */
1326 if (!arch_irq_disabled_regs(regs)) 1340 if (!arch_irq_disabled_regs(regs))
1327 local_irq_enable(); 1341 local_irq_enable();
1328 1342
1329 if (value < ARRAY_SIZE(facility_strings))
1330 facility = facility_strings[value];
1331 else
1332 facility = "unknown";
1333
1334 pr_err("%sFacility '%s' unavailable, exception at 0x%lx, MSR=%lx\n", 1343 pr_err("%sFacility '%s' unavailable, exception at 0x%lx, MSR=%lx\n",
1335 prefix, facility, regs->nip, regs->msr); 1344 hv ? "Hypervisor " : "", facility, regs->nip, regs->msr);
1336 1345
1337 if (user_mode(regs)) { 1346 if (user_mode(regs)) {
1338 _exception(SIGILL, regs, ILL_ILLOPC, regs->nip); 1347 _exception(SIGILL, regs, ILL_ILLOPC, regs->nip);
@@ -1341,6 +1350,7 @@ void facility_unavailable_exception(struct pt_regs *regs)
1341 1350
1342 die("Unexpected facility unavailable exception", regs, SIGABRT); 1351 die("Unexpected facility unavailable exception", regs, SIGABRT);
1343} 1352}
1353#endif
1344 1354
1345#ifdef CONFIG_PPC_TRANSACTIONAL_MEM 1355#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
1346 1356