1*4882a593Smuzhiyun /* 2*4882a593Smuzhiyun * This file is subject to the terms and conditions of the GNU General Public 3*4882a593Smuzhiyun * License. See the file "COPYING" in the main directory of this archive 4*4882a593Smuzhiyun * for more details. 5*4882a593Smuzhiyun * 6*4882a593Smuzhiyun * Copyright (C) 2009 Wind River Systems, 7*4882a593Smuzhiyun * written by Ralf Baechle <ralf@linux-mips.org> 8*4882a593Smuzhiyun */ 9*4882a593Smuzhiyun #include <linux/init.h> 10*4882a593Smuzhiyun #include <linux/irqflags.h> 11*4882a593Smuzhiyun #include <linux/notifier.h> 12*4882a593Smuzhiyun #include <linux/prefetch.h> 13*4882a593Smuzhiyun #include <linux/ptrace.h> 14*4882a593Smuzhiyun #include <linux/sched.h> 15*4882a593Smuzhiyun #include <linux/sched/task_stack.h> 16*4882a593Smuzhiyun 17*4882a593Smuzhiyun #include <asm/cop2.h> 18*4882a593Smuzhiyun #include <asm/current.h> 19*4882a593Smuzhiyun #include <asm/mipsregs.h> 20*4882a593Smuzhiyun #include <asm/page.h> 21*4882a593Smuzhiyun #include <asm/octeon/octeon.h> 22*4882a593Smuzhiyun cnmips_cu2_call(struct notifier_block * nfb,unsigned long action,void * data)23*4882a593Smuzhiyunstatic int cnmips_cu2_call(struct notifier_block *nfb, unsigned long action, 24*4882a593Smuzhiyun void *data) 25*4882a593Smuzhiyun { 26*4882a593Smuzhiyun unsigned long flags; 27*4882a593Smuzhiyun unsigned int status; 28*4882a593Smuzhiyun 29*4882a593Smuzhiyun switch (action) { 30*4882a593Smuzhiyun case CU2_EXCEPTION: 31*4882a593Smuzhiyun prefetch(¤t->thread.cp2); 32*4882a593Smuzhiyun local_irq_save(flags); 33*4882a593Smuzhiyun KSTK_STATUS(current) |= ST0_CU2; 34*4882a593Smuzhiyun status = read_c0_status(); 35*4882a593Smuzhiyun write_c0_status(status | ST0_CU2); 36*4882a593Smuzhiyun octeon_cop2_restore(&(current->thread.cp2)); 37*4882a593Smuzhiyun write_c0_status(status & ~ST0_CU2); 38*4882a593Smuzhiyun local_irq_restore(flags); 39*4882a593Smuzhiyun 40*4882a593Smuzhiyun return NOTIFY_BAD; /* Don't call default notifier */ 41*4882a593Smuzhiyun } 42*4882a593Smuzhiyun 43*4882a593Smuzhiyun return NOTIFY_OK; /* Let default notifier send signals */ 44*4882a593Smuzhiyun } 45*4882a593Smuzhiyun cnmips_cu2_setup(void)46*4882a593Smuzhiyunstatic int __init cnmips_cu2_setup(void) 47*4882a593Smuzhiyun { 48*4882a593Smuzhiyun return cu2_notifier(cnmips_cu2_call, 0); 49*4882a593Smuzhiyun } 50*4882a593Smuzhiyun early_initcall(cnmips_cu2_setup); 51