Hi, Ralf, I found that the V3 of Loongson's patchset has been merged into mips-for-linux-next. But the 7th patch (this one) should be updated for preemptible kernel. The reason is nearly the same as http://www.linux-mips.org/archives/linux-mips/2014-07/msg00237.html. Thanks. Huacai On Thu, Jul 31, 2014 at 9:06 AM, Huacai Chen <chenhc@xxxxxxxxxx> wrote: > Loongson-3 has some specific instructions (MMI/SIMD) in coprocessor 2. > COP2 isn't independent because it share COP1 (FPU)'s registers. This > patch enable the COP2 usage so user-space programs can use the MMI/SIMD > instructions. When COP2 exception happens, we enable both COP1 (FPU) > and COP2, only in this way the fp context can be saved and restored > correctly. > > V4: Make it work fine in preemptible kernel. > > Signed-off-by: Huacai Chen <chenhc@xxxxxxxxxx> > --- > arch/mips/include/asm/cop2.h | 8 ++++ > arch/mips/loongson/loongson-3/Makefile | 2 +- > arch/mips/loongson/loongson-3/cop2-ex.c | 63 +++++++++++++++++++++++++++++++ > 3 files changed, 72 insertions(+), 1 deletions(-) > create mode 100644 arch/mips/loongson/loongson-3/cop2-ex.c > > diff --git a/arch/mips/include/asm/cop2.h b/arch/mips/include/asm/cop2.h > index c1516cc..d035298 100644 > --- a/arch/mips/include/asm/cop2.h > +++ b/arch/mips/include/asm/cop2.h > @@ -32,6 +32,14 @@ extern void nlm_cop2_restore(struct nlm_cop2_state *); > #define cop2_present 1 > #define cop2_lazy_restore 0 > > +#elif defined(CONFIG_CPU_LOONGSON3) > + > +#define cop2_save(r) > +#define cop2_restore(r) > + > +#define cop2_present 1 > +#define cop2_lazy_restore 1 > + > #else > > #define cop2_present 0 > diff --git a/arch/mips/loongson/loongson-3/Makefile b/arch/mips/loongson/loongson-3/Makefile > index 471b0f2a..b4df775 100644 > --- a/arch/mips/loongson/loongson-3/Makefile > +++ b/arch/mips/loongson/loongson-3/Makefile > @@ -1,7 +1,7 @@ > # > # Makefile for Loongson-3 family machines > # > -obj-y += irq.o > +obj-y += irq.o cop2-ex.o > > obj-$(CONFIG_SMP) += smp.o > > diff --git a/arch/mips/loongson/loongson-3/cop2-ex.c b/arch/mips/loongson/loongson-3/cop2-ex.c > new file mode 100644 > index 0000000..c1e9503 > --- /dev/null > +++ b/arch/mips/loongson/loongson-3/cop2-ex.c > @@ -0,0 +1,63 @@ > +/* > + * 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) 2014 Lemote Corporation. > + * written by Huacai Chen <chenhc@xxxxxxxxxx> > + * > + * based on arch/mips/cavium-octeon/cpu.c > + * Copyright (C) 2009 Wind River Systems, > + * written by Ralf Baechle <ralf@xxxxxxxxxxxxxx> > + */ > +#include <linux/init.h> > +#include <linux/sched.h> > +#include <linux/notifier.h> > + > +#include <asm/fpu.h> > +#include <asm/cop2.h> > +#include <asm/current.h> > +#include <asm/mipsregs.h> > + > +static int loongson_cu2_call(struct notifier_block *nfb, unsigned long action, > + void *data) > +{ > + int fpu_owned; > + int fr = !test_thread_flag(TIF_32BIT_FPREGS); > + > + switch (action) { > + case CU2_EXCEPTION: > + preempt_disable(); > + fpu_owned = __is_fpu_owner(); > + if (!fr) > + set_c0_status(ST0_CU1 | ST0_CU2); > + else > + set_c0_status(ST0_CU1 | ST0_CU2 | ST0_FR); > + enable_fpu_hazard(); > + KSTK_STATUS(current) |= (ST0_CU1 | ST0_CU2); > + if (fr) > + KSTK_STATUS(current) |= ST0_FR; > + else > + KSTK_STATUS(current) &= ~ST0_FR; > + /* If FPU is owned, we needn't init or restore fp */ > + if(!fpu_owned) { > + set_thread_flag(TIF_USEDFPU); > + if (!used_math()) { > + _init_fpu(); > + set_used_math(); > + } else > + _restore_fp(current); > + } > + preempt_enable(); > + > + return NOTIFY_STOP; /* Don't call default notifier */ > + } > + > + return NOTIFY_OK; /* Let default notifier send signals */ > +} > + > +static int __init loongson_cu2_setup(void) > +{ > + return cu2_notifier(loongson_cu2_call, 0); > +} > +early_initcall(loongson_cu2_setup); > -- > 1.7.7.3 >