|
@@ -25,10 +25,12 @@
|
|
|
#include <linux/ptrace.h>
|
|
|
#include <linux/kgdb.h>
|
|
|
#include <linux/kdebug.h>
|
|
|
+#include <linux/notifier.h>
|
|
|
|
|
|
#include <asm/bootinfo.h>
|
|
|
#include <asm/branch.h>
|
|
|
#include <asm/break.h>
|
|
|
+#include <asm/cop2.h>
|
|
|
#include <asm/cpu.h>
|
|
|
#include <asm/dsp.h>
|
|
|
#include <asm/fpu.h>
|
|
@@ -79,10 +81,6 @@ extern asmlinkage void handle_reserved(void);
|
|
|
extern int fpu_emulator_cop1Handler(struct pt_regs *xcp,
|
|
|
struct mips_fpu_struct *ctx, int has_fpu);
|
|
|
|
|
|
-#ifdef CONFIG_CPU_CAVIUM_OCTEON
|
|
|
-extern asmlinkage void octeon_cop2_restore(struct octeon_cop2_state *task);
|
|
|
-#endif
|
|
|
-
|
|
|
void (*board_be_init)(void);
|
|
|
int (*board_be_handler)(struct pt_regs *regs, int is_fixup);
|
|
|
void (*board_nmi_handler_setup)(void);
|
|
@@ -857,6 +855,44 @@ static void mt_ase_fp_affinity(void)
|
|
|
#endif /* CONFIG_MIPS_MT_FPAFF */
|
|
|
}
|
|
|
|
|
|
+/*
|
|
|
+ * No lock; only written during early bootup by CPU 0.
|
|
|
+ */
|
|
|
+static RAW_NOTIFIER_HEAD(cu2_chain);
|
|
|
+
|
|
|
+int __ref register_cu2_notifier(struct notifier_block *nb)
|
|
|
+{
|
|
|
+ return raw_notifier_chain_register(&cu2_chain, nb);
|
|
|
+}
|
|
|
+
|
|
|
+int cu2_notifier_call_chain(unsigned long val, void *v)
|
|
|
+{
|
|
|
+ return raw_notifier_call_chain(&cu2_chain, val, v);
|
|
|
+}
|
|
|
+
|
|
|
+static int default_cu2_call(struct notifier_block *nfb, unsigned long action,
|
|
|
+ void *data)
|
|
|
+{
|
|
|
+ struct pt_regs *regs = data;
|
|
|
+
|
|
|
+ switch (action) {
|
|
|
+ default:
|
|
|
+ die_if_kernel("Unhandled kernel unaligned access or invalid "
|
|
|
+ "instruction", regs);
|
|
|
+ /* Fall through */
|
|
|
+
|
|
|
+ case CU2_EXCEPTION:
|
|
|
+ force_sig(SIGILL, current);
|
|
|
+ }
|
|
|
+
|
|
|
+ return NOTIFY_OK;
|
|
|
+}
|
|
|
+
|
|
|
+static struct notifier_block default_cu2_notifier = {
|
|
|
+ .notifier_call = default_cu2_call,
|
|
|
+ .priority = 0x80000000, /* Run last */
|
|
|
+};
|
|
|
+
|
|
|
asmlinkage void do_cpu(struct pt_regs *regs)
|
|
|
{
|
|
|
unsigned int __user *epc;
|
|
@@ -920,17 +956,9 @@ asmlinkage void do_cpu(struct pt_regs *regs)
|
|
|
return;
|
|
|
|
|
|
case 2:
|
|
|
-#ifdef CONFIG_CPU_CAVIUM_OCTEON
|
|
|
- prefetch(¤t->thread.cp2);
|
|
|
- local_irq_save(flags);
|
|
|
- KSTK_STATUS(current) |= ST0_CU2;
|
|
|
- status = read_c0_status();
|
|
|
- write_c0_status(status | ST0_CU2);
|
|
|
- octeon_cop2_restore(&(current->thread.cp2));
|
|
|
- write_c0_status(status & ~ST0_CU2);
|
|
|
- local_irq_restore(flags);
|
|
|
- return;
|
|
|
-#endif
|
|
|
+ raw_notifier_call_chain(&cu2_chain, CU2_EXCEPTION, regs);
|
|
|
+ break;
|
|
|
+
|
|
|
case 3:
|
|
|
break;
|
|
|
}
|
|
@@ -1760,4 +1788,6 @@ void __init trap_init(void)
|
|
|
flush_tlb_handlers();
|
|
|
|
|
|
sort_extable(__start___dbe_table, __stop___dbe_table);
|
|
|
+
|
|
|
+ register_cu2_notifier(&default_cu2_notifier);
|
|
|
}
|