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.c89
1 files changed, 59 insertions, 30 deletions
diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c
index f18c79c324ef..bf33c22e38a4 100644
--- a/arch/powerpc/kernel/traps.c
+++ b/arch/powerpc/kernel/traps.c
@@ -866,6 +866,10 @@ static int emulate_string_inst(struct pt_regs *regs, u32 instword)
866 u8 val; 866 u8 val;
867 u32 shift = 8 * (3 - (pos & 0x3)); 867 u32 shift = 8 * (3 - (pos & 0x3));
868 868
869 /* if process is 32-bit, clear upper 32 bits of EA */
870 if ((regs->msr & MSR_64BIT) == 0)
871 EA &= 0xFFFFFFFF;
872
869 switch ((instword & PPC_INST_STRING_MASK)) { 873 switch ((instword & PPC_INST_STRING_MASK)) {
870 case PPC_INST_LSWX: 874 case PPC_INST_LSWX:
871 case PPC_INST_LSWI: 875 case PPC_INST_LSWI:
@@ -1125,7 +1129,17 @@ void __kprobes program_check_exception(struct pt_regs *regs)
1125 * ESR_DST (!?) or 0. In the process of chasing this with the 1129 * ESR_DST (!?) or 0. In the process of chasing this with the
1126 * hardware people - not sure if it can happen on any illegal 1130 * hardware people - not sure if it can happen on any illegal
1127 * instruction or only on FP instructions, whether there is a 1131 * instruction or only on FP instructions, whether there is a
1128 * pattern to occurrences etc. -dgibson 31/Mar/2003 */ 1132 * pattern to occurrences etc. -dgibson 31/Mar/2003
1133 */
1134
1135 /*
1136 * If we support a HW FPU, we need to ensure the FP state
1137 * if flushed into the thread_struct before attempting
1138 * emulation
1139 */
1140#ifdef CONFIG_PPC_FPU
1141 flush_fp_to_thread(current);
1142#endif
1129 switch (do_mathemu(regs)) { 1143 switch (do_mathemu(regs)) {
1130 case 0: 1144 case 0:
1131 emulate_single_step(regs); 1145 emulate_single_step(regs);
@@ -1165,6 +1179,16 @@ bail:
1165 exception_exit(prev_state); 1179 exception_exit(prev_state);
1166} 1180}
1167 1181
1182/*
1183 * This occurs when running in hypervisor mode on POWER6 or later
1184 * and an illegal instruction is encountered.
1185 */
1186void __kprobes emulation_assist_interrupt(struct pt_regs *regs)
1187{
1188 regs->msr |= REASON_ILLEGAL;
1189 program_check_exception(regs);
1190}
1191
1168void alignment_exception(struct pt_regs *regs) 1192void alignment_exception(struct pt_regs *regs)
1169{ 1193{
1170 enum ctx_state prev_state = exception_enter(); 1194 enum ctx_state prev_state = exception_enter();
@@ -1272,25 +1296,50 @@ void vsx_unavailable_exception(struct pt_regs *regs)
1272 die("Unrecoverable VSX Unavailable Exception", regs, SIGABRT); 1296 die("Unrecoverable VSX Unavailable Exception", regs, SIGABRT);
1273} 1297}
1274 1298
1275void tm_unavailable_exception(struct pt_regs *regs) 1299void facility_unavailable_exception(struct pt_regs *regs)
1276{ 1300{
1301 static char *facility_strings[] = {
1302 "FPU",
1303 "VMX/VSX",
1304 "DSCR",
1305 "PMU SPRs",
1306 "BHRB",
1307 "TM",
1308 "AT",
1309 "EBB",
1310 "TAR",
1311 };
1312 char *facility, *prefix;
1313 u64 value;
1314
1315 if (regs->trap == 0xf60) {
1316 value = mfspr(SPRN_FSCR);
1317 prefix = "";
1318 } else {
1319 value = mfspr(SPRN_HFSCR);
1320 prefix = "Hypervisor ";
1321 }
1322
1323 value = value >> 56;
1324
1277 /* We restore the interrupt state now */ 1325 /* We restore the interrupt state now */
1278 if (!arch_irq_disabled_regs(regs)) 1326 if (!arch_irq_disabled_regs(regs))
1279 local_irq_enable(); 1327 local_irq_enable();
1280 1328
1281 /* Currently we never expect a TMU exception. Catch 1329 if (value < ARRAY_SIZE(facility_strings))
1282 * this and kill the process! 1330 facility = facility_strings[value];
1283 */ 1331 else
1284 printk(KERN_EMERG "Unexpected TM unavailable exception at %lx " 1332 facility = "unknown";
1285 "(msr %lx)\n", 1333
1286 regs->nip, regs->msr); 1334 pr_err("%sFacility '%s' unavailable, exception at 0x%lx, MSR=%lx\n",
1335 prefix, facility, regs->nip, regs->msr);
1287 1336
1288 if (user_mode(regs)) { 1337 if (user_mode(regs)) {
1289 _exception(SIGILL, regs, ILL_ILLOPC, regs->nip); 1338 _exception(SIGILL, regs, ILL_ILLOPC, regs->nip);
1290 return; 1339 return;
1291 } 1340 }
1292 1341
1293 die("Unexpected TM unavailable exception", regs, SIGABRT); 1342 die("Unexpected facility unavailable exception", regs, SIGABRT);
1294} 1343}
1295 1344
1296#ifdef CONFIG_PPC_TRANSACTIONAL_MEM 1345#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
@@ -1386,8 +1435,7 @@ void performance_monitor_exception(struct pt_regs *regs)
1386void SoftwareEmulation(struct pt_regs *regs) 1435void SoftwareEmulation(struct pt_regs *regs)
1387{ 1436{
1388 extern int do_mathemu(struct pt_regs *); 1437 extern int do_mathemu(struct pt_regs *);
1389 extern int Soft_emulate_8xx(struct pt_regs *); 1438#if defined(CONFIG_MATH_EMULATION)
1390#if defined(CONFIG_MATH_EMULATION) || defined(CONFIG_8XX_MINIMAL_FPEMU)
1391 int errcode; 1439 int errcode;
1392#endif 1440#endif
1393 1441
@@ -1420,23 +1468,6 @@ void SoftwareEmulation(struct pt_regs *regs)
1420 _exception(SIGILL, regs, ILL_ILLOPC, regs->nip); 1468 _exception(SIGILL, regs, ILL_ILLOPC, regs->nip);
1421 return; 1469 return;
1422 } 1470 }
1423
1424#elif defined(CONFIG_8XX_MINIMAL_FPEMU)
1425 errcode = Soft_emulate_8xx(regs);
1426 if (errcode >= 0)
1427 PPC_WARN_EMULATED(8xx, regs);
1428
1429 switch (errcode) {
1430 case 0:
1431 emulate_single_step(regs);
1432 return;
1433 case 1:
1434 _exception(SIGILL, regs, ILL_ILLOPC, regs->nip);
1435 return;
1436 case -EFAULT:
1437 _exception(SIGSEGV, regs, SEGV_MAPERR, regs->nip);
1438 return;
1439 }
1440#else 1471#else
1441 _exception(SIGILL, regs, ILL_ILLOPC, regs->nip); 1472 _exception(SIGILL, regs, ILL_ILLOPC, regs->nip);
1442#endif 1473#endif
@@ -1786,8 +1817,6 @@ struct ppc_emulated ppc_emulated = {
1786 WARN_EMULATED_SETUP(unaligned), 1817 WARN_EMULATED_SETUP(unaligned),
1787#ifdef CONFIG_MATH_EMULATION 1818#ifdef CONFIG_MATH_EMULATION
1788 WARN_EMULATED_SETUP(math), 1819 WARN_EMULATED_SETUP(math),
1789#elif defined(CONFIG_8XX_MINIMAL_FPEMU)
1790 WARN_EMULATED_SETUP(8xx),
1791#endif 1820#endif
1792#ifdef CONFIG_VSX 1821#ifdef CONFIG_VSX
1793 WARN_EMULATED_SETUP(vsx), 1822 WARN_EMULATED_SETUP(vsx),