|
@@ -44,9 +44,7 @@
|
|
|
#include <asm/machdep.h>
|
|
|
#include <asm/rtas.h>
|
|
|
#include <asm/pmc.h>
|
|
|
-#ifdef CONFIG_PPC32
|
|
|
#include <asm/reg.h>
|
|
|
-#endif
|
|
|
#ifdef CONFIG_PMAC_BACKLIGHT
|
|
|
#include <asm/backlight.h>
|
|
|
#endif
|
|
@@ -1296,43 +1294,54 @@ void vsx_unavailable_exception(struct pt_regs *regs)
|
|
|
die("Unrecoverable VSX Unavailable Exception", regs, SIGABRT);
|
|
|
}
|
|
|
|
|
|
+#ifdef CONFIG_PPC64
|
|
|
void facility_unavailable_exception(struct pt_regs *regs)
|
|
|
{
|
|
|
static char *facility_strings[] = {
|
|
|
- "FPU",
|
|
|
- "VMX/VSX",
|
|
|
- "DSCR",
|
|
|
- "PMU SPRs",
|
|
|
- "BHRB",
|
|
|
- "TM",
|
|
|
- "AT",
|
|
|
- "EBB",
|
|
|
- "TAR",
|
|
|
+ [FSCR_FP_LG] = "FPU",
|
|
|
+ [FSCR_VECVSX_LG] = "VMX/VSX",
|
|
|
+ [FSCR_DSCR_LG] = "DSCR",
|
|
|
+ [FSCR_PM_LG] = "PMU SPRs",
|
|
|
+ [FSCR_BHRB_LG] = "BHRB",
|
|
|
+ [FSCR_TM_LG] = "TM",
|
|
|
+ [FSCR_EBB_LG] = "EBB",
|
|
|
+ [FSCR_TAR_LG] = "TAR",
|
|
|
};
|
|
|
- char *facility, *prefix;
|
|
|
+ char *facility = "unknown";
|
|
|
u64 value;
|
|
|
+ u8 status;
|
|
|
+ bool hv;
|
|
|
|
|
|
- if (regs->trap == 0xf60) {
|
|
|
- value = mfspr(SPRN_FSCR);
|
|
|
- prefix = "";
|
|
|
- } else {
|
|
|
+ hv = (regs->trap == 0xf80);
|
|
|
+ if (hv)
|
|
|
value = mfspr(SPRN_HFSCR);
|
|
|
- prefix = "Hypervisor ";
|
|
|
+ else
|
|
|
+ value = mfspr(SPRN_FSCR);
|
|
|
+
|
|
|
+ status = value >> 56;
|
|
|
+ if (status == FSCR_DSCR_LG) {
|
|
|
+ /* User is acessing the DSCR. Set the inherit bit and allow
|
|
|
+ * the user to set it directly in future by setting via the
|
|
|
+ * H/FSCR DSCR bit.
|
|
|
+ */
|
|
|
+ current->thread.dscr_inherit = 1;
|
|
|
+ if (hv)
|
|
|
+ mtspr(SPRN_HFSCR, value | HFSCR_DSCR);
|
|
|
+ else
|
|
|
+ mtspr(SPRN_FSCR, value | FSCR_DSCR);
|
|
|
+ return;
|
|
|
}
|
|
|
|
|
|
- value = value >> 56;
|
|
|
+ if ((status < ARRAY_SIZE(facility_strings)) &&
|
|
|
+ facility_strings[status])
|
|
|
+ facility = facility_strings[status];
|
|
|
|
|
|
/* We restore the interrupt state now */
|
|
|
if (!arch_irq_disabled_regs(regs))
|
|
|
local_irq_enable();
|
|
|
|
|
|
- if (value < ARRAY_SIZE(facility_strings))
|
|
|
- facility = facility_strings[value];
|
|
|
- else
|
|
|
- facility = "unknown";
|
|
|
-
|
|
|
pr_err("%sFacility '%s' unavailable, exception at 0x%lx, MSR=%lx\n",
|
|
|
- prefix, facility, regs->nip, regs->msr);
|
|
|
+ hv ? "Hypervisor " : "", facility, regs->nip, regs->msr);
|
|
|
|
|
|
if (user_mode(regs)) {
|
|
|
_exception(SIGILL, regs, ILL_ILLOPC, regs->nip);
|
|
@@ -1341,6 +1350,7 @@ void facility_unavailable_exception(struct pt_regs *regs)
|
|
|
|
|
|
die("Unexpected facility unavailable exception", regs, SIGABRT);
|
|
|
}
|
|
|
+#endif
|
|
|
|
|
|
#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
|
|
|
|