162306a36Sopenharmony_ci/* 262306a36Sopenharmony_ci * This file is subject to the terms and conditions of the GNU General Public 362306a36Sopenharmony_ci * License. See the file "COPYING" in the main directory of this archive 462306a36Sopenharmony_ci * for more details. 562306a36Sopenharmony_ci * 662306a36Sopenharmony_ci * Copyright (C) 2009 Wind River Systems, 762306a36Sopenharmony_ci * written by Ralf Baechle <ralf@linux-mips.org> 862306a36Sopenharmony_ci */ 962306a36Sopenharmony_ci#include <linux/init.h> 1062306a36Sopenharmony_ci#include <linux/irqflags.h> 1162306a36Sopenharmony_ci#include <linux/notifier.h> 1262306a36Sopenharmony_ci#include <linux/prefetch.h> 1362306a36Sopenharmony_ci#include <linux/ptrace.h> 1462306a36Sopenharmony_ci#include <linux/sched.h> 1562306a36Sopenharmony_ci#include <linux/sched/task_stack.h> 1662306a36Sopenharmony_ci 1762306a36Sopenharmony_ci#include <asm/cop2.h> 1862306a36Sopenharmony_ci#include <asm/current.h> 1962306a36Sopenharmony_ci#include <asm/mipsregs.h> 2062306a36Sopenharmony_ci#include <asm/page.h> 2162306a36Sopenharmony_ci#include <asm/octeon/octeon.h> 2262306a36Sopenharmony_ci 2362306a36Sopenharmony_cistatic int cnmips_cu2_call(struct notifier_block *nfb, unsigned long action, 2462306a36Sopenharmony_ci void *data) 2562306a36Sopenharmony_ci{ 2662306a36Sopenharmony_ci unsigned long flags; 2762306a36Sopenharmony_ci unsigned int status; 2862306a36Sopenharmony_ci 2962306a36Sopenharmony_ci switch (action) { 3062306a36Sopenharmony_ci case CU2_EXCEPTION: 3162306a36Sopenharmony_ci prefetch(¤t->thread.cp2); 3262306a36Sopenharmony_ci local_irq_save(flags); 3362306a36Sopenharmony_ci KSTK_STATUS(current) |= ST0_CU2; 3462306a36Sopenharmony_ci status = read_c0_status(); 3562306a36Sopenharmony_ci write_c0_status(status | ST0_CU2); 3662306a36Sopenharmony_ci octeon_cop2_restore(&(current->thread.cp2)); 3762306a36Sopenharmony_ci write_c0_status(status & ~ST0_CU2); 3862306a36Sopenharmony_ci local_irq_restore(flags); 3962306a36Sopenharmony_ci 4062306a36Sopenharmony_ci return NOTIFY_BAD; /* Don't call default notifier */ 4162306a36Sopenharmony_ci } 4262306a36Sopenharmony_ci 4362306a36Sopenharmony_ci return NOTIFY_OK; /* Let default notifier send signals */ 4462306a36Sopenharmony_ci} 4562306a36Sopenharmony_ci 4662306a36Sopenharmony_cistatic int __init cnmips_cu2_setup(void) 4762306a36Sopenharmony_ci{ 4862306a36Sopenharmony_ci return cu2_notifier(cnmips_cu2_call, 0); 4962306a36Sopenharmony_ci} 5062306a36Sopenharmony_ciearly_initcall(cnmips_cu2_setup); 51