Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 69f3a7de authored by Ralf Baechle's avatar Ralf Baechle
Browse files

MIPS: Modularize COP2 handling



Away with the daemons of ifdef; get ready for future COP2 users.

Signed-off-by: default avatarRalf Baechle <ralf@linux-mips.org>
Patchwork: http://patchwork.linux-mips.org/patch/708/
parent 4dd92e15
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -9,7 +9,7 @@
# Copyright (C) 2005-2009 Cavium Networks
#

obj-y := setup.o serial.o octeon-platform.o octeon-irq.o csrc-octeon.o
obj-y := cpu.o setup.o serial.o octeon-platform.o octeon-irq.o csrc-octeon.o
obj-y += dma-octeon.o flash_setup.o
obj-y += octeon-memcpy.o

+52 −0
Original line number Diff line number Diff line
/*
 * This file is subject to the terms and conditions of the GNU General Public
 * License.  See the file "COPYING" in the main directory of this archive
 * for more details.
 *
 * Copyright (C) 2009 Wind River Systems,
 *   written by Ralf Baechle <ralf@linux-mips.org>
 */
#include <linux/init.h>
#include <linux/irqflags.h>
#include <linux/notifier.h>
#include <linux/prefetch.h>
#include <linux/sched.h>

#include <asm/cop2.h>
#include <asm/current.h>
#include <asm/mipsregs.h>
#include <asm/page.h>
#include <asm/octeon/octeon.h>

static int cnmips_cu2_call(struct notifier_block *nfb, unsigned long action,
	void *data)
{
	unsigned long flags;
	unsigned int status;

	switch (action) {
	case CU2_EXCEPTION:
		prefetch(&current->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 NOTIFY_BAD;	/* Don't call default notifier */
	}

	return NOTIFY_OK;		/* Let default notifier send signals */
}

static struct notifier_block cnmips_cu2_notifier = {
	.notifier_call = cnmips_cu2_call,
};

static int cnmips_cu2_setup(void)
{
	return register_cu2_notifier(&cnmips_cu2_notifier);
}
early_initcall(cnmips_cu2_setup);
+23 −0
Original line number Diff line number Diff line
/*
 * This file is subject to the terms and conditions of the GNU General Public
 * License.  See the file "COPYING" in the main directory of this archive
 * for more details.
 *
 * Copyright (C) 2009 Wind River Systems,
 *   written by Ralf Baechle <ralf@linux-mips.org>
 */
#ifndef __ASM_COP2_H
#define __ASM_COP2_H

enum cu2_ops {
	CU2_EXCEPTION,
	CU2_LWC2_OP,
	CU2_LDC2_OP,
	CU2_SWC2_OP,
	CU2_SDC2_OP,
};

extern int register_cu2_notifier(struct notifier_block *nb);
extern int cu2_notifier_call_chain(unsigned long val, void *v);

#endif /* __ASM_COP2_H */
+1 −0
Original line number Diff line number Diff line
@@ -47,6 +47,7 @@ struct octeon_cop2_state;
extern unsigned long octeon_crypto_enable(struct octeon_cop2_state *state);
extern void octeon_crypto_disable(struct octeon_cop2_state *state,
				  unsigned long flags);
extern asmlinkage void octeon_cop2_restore(struct octeon_cop2_state *task);

extern void octeon_init_cvmcount(void);

+45 −15
Original line number Diff line number Diff line
@@ -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(&current->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);
}
Loading