MN10300: Make the FPU operate in non-lazy mode under SMP
Make the FPU operate in non-lazy mode under SMP so that when the process that is currently using the FPU migrates to a different CPU, we don't have to ping its previous CPU to flush the FPU context. Signed-off-by: Akira Takeuchi <takeuchi.akr@jp.panasonic.com> Signed-off-by: Kiyoshi Owada <owada.kiyoshi@jp.panasonic.com> Signed-off-by: David Howells <dhowells@redhat.com>
This commit is contained in:
committed by
David Howells
parent
965ea4bbb9
commit
278d91c460
@@ -140,6 +140,21 @@ config FPU
|
|||||||
default y
|
default y
|
||||||
depends on MN10300_PROC_MN103E010
|
depends on MN10300_PROC_MN103E010
|
||||||
|
|
||||||
|
config LAZY_SAVE_FPU
|
||||||
|
bool "Save FPU state lazily"
|
||||||
|
default y
|
||||||
|
depends on FPU && !SMP
|
||||||
|
help
|
||||||
|
Enable this to be lazy in the saving of the FPU state to the owning
|
||||||
|
task's thread struct. This is useful if most tasks on the system
|
||||||
|
don't use the FPU as only those tasks that use it will pass it
|
||||||
|
between them, and the state needn't be saved for a task that isn't
|
||||||
|
using it.
|
||||||
|
|
||||||
|
This can't be so easily used on SMP as the process that owns the FPU
|
||||||
|
state on a CPU may be currently running on another CPU, so for the
|
||||||
|
moment, it is disabled.
|
||||||
|
|
||||||
source "arch/mn10300/mm/Kconfig.cache"
|
source "arch/mn10300/mm/Kconfig.cache"
|
||||||
|
|
||||||
config MN10300_TLB_USE_PIDR
|
config MN10300_TLB_USE_PIDR
|
||||||
|
@@ -47,8 +47,6 @@ typedef struct {
|
|||||||
u_int32_t fpcr;
|
u_int32_t fpcr;
|
||||||
} elf_fpregset_t;
|
} elf_fpregset_t;
|
||||||
|
|
||||||
extern int dump_fpu(struct pt_regs *, elf_fpregset_t *);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This is used to ensure we don't load something for the wrong architecture
|
* This is used to ensure we don't load something for the wrong architecture
|
||||||
*/
|
*/
|
||||||
|
@@ -101,7 +101,6 @@ extern asmlinkage void dtlb_aerror(void);
|
|||||||
extern asmlinkage void raw_bus_error(void);
|
extern asmlinkage void raw_bus_error(void);
|
||||||
extern asmlinkage void double_fault(void);
|
extern asmlinkage void double_fault(void);
|
||||||
extern asmlinkage int system_call(struct pt_regs *);
|
extern asmlinkage int system_call(struct pt_regs *);
|
||||||
extern asmlinkage void fpu_exception(struct pt_regs *, enum exception_code);
|
|
||||||
extern asmlinkage void nmi(struct pt_regs *, enum exception_code);
|
extern asmlinkage void nmi(struct pt_regs *, enum exception_code);
|
||||||
extern asmlinkage void uninitialised_exception(struct pt_regs *,
|
extern asmlinkage void uninitialised_exception(struct pt_regs *,
|
||||||
enum exception_code);
|
enum exception_code);
|
||||||
|
@@ -12,74 +12,125 @@
|
|||||||
#ifndef _ASM_FPU_H
|
#ifndef _ASM_FPU_H
|
||||||
#define _ASM_FPU_H
|
#define _ASM_FPU_H
|
||||||
|
|
||||||
#include <asm/processor.h>
|
#ifndef __ASSEMBLY__
|
||||||
|
|
||||||
|
#include <linux/sched.h>
|
||||||
|
#include <asm/exceptions.h>
|
||||||
#include <asm/sigcontext.h>
|
#include <asm/sigcontext.h>
|
||||||
#include <asm/user.h>
|
|
||||||
|
|
||||||
#ifdef __KERNEL__
|
#ifdef __KERNEL__
|
||||||
|
|
||||||
/* the task that owns the FPU state */
|
extern asmlinkage void fpu_disabled(void);
|
||||||
|
|
||||||
|
#ifdef CONFIG_FPU
|
||||||
|
|
||||||
|
#ifdef CONFIG_LAZY_SAVE_FPU
|
||||||
|
/* the task that currently owns the FPU state */
|
||||||
extern struct task_struct *fpu_state_owner;
|
extern struct task_struct *fpu_state_owner;
|
||||||
|
#endif
|
||||||
|
|
||||||
#define set_using_fpu(tsk) \
|
#if (THREAD_USING_FPU & ~0xff)
|
||||||
do { \
|
#error THREAD_USING_FPU must be smaller than 0x100.
|
||||||
(tsk)->thread.fpu_flags |= THREAD_USING_FPU; \
|
#endif
|
||||||
} while (0)
|
|
||||||
|
|
||||||
#define clear_using_fpu(tsk) \
|
static inline void set_using_fpu(struct task_struct *tsk)
|
||||||
do { \
|
{
|
||||||
(tsk)->thread.fpu_flags &= ~THREAD_USING_FPU; \
|
asm volatile(
|
||||||
} while (0)
|
"bset %0,(0,%1)"
|
||||||
|
:
|
||||||
|
: "i"(THREAD_USING_FPU), "a"(&tsk->thread.fpu_flags)
|
||||||
|
: "memory", "cc");
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void clear_using_fpu(struct task_struct *tsk)
|
||||||
|
{
|
||||||
|
asm volatile(
|
||||||
|
"bclr %0,(0,%1)"
|
||||||
|
:
|
||||||
|
: "i"(THREAD_USING_FPU), "a"(&tsk->thread.fpu_flags)
|
||||||
|
: "memory", "cc");
|
||||||
|
}
|
||||||
|
|
||||||
#define is_using_fpu(tsk) ((tsk)->thread.fpu_flags & THREAD_USING_FPU)
|
#define is_using_fpu(tsk) ((tsk)->thread.fpu_flags & THREAD_USING_FPU)
|
||||||
|
|
||||||
#define unlazy_fpu(tsk) \
|
|
||||||
do { \
|
|
||||||
preempt_disable(); \
|
|
||||||
if (fpu_state_owner == (tsk)) \
|
|
||||||
fpu_save(&tsk->thread.fpu_state); \
|
|
||||||
preempt_enable(); \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
#define exit_fpu() \
|
|
||||||
do { \
|
|
||||||
struct task_struct *__tsk = current; \
|
|
||||||
preempt_disable(); \
|
|
||||||
if (fpu_state_owner == __tsk) \
|
|
||||||
fpu_state_owner = NULL; \
|
|
||||||
preempt_enable(); \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
#define flush_fpu() \
|
|
||||||
do { \
|
|
||||||
struct task_struct *__tsk = current; \
|
|
||||||
preempt_disable(); \
|
|
||||||
if (fpu_state_owner == __tsk) { \
|
|
||||||
fpu_state_owner = NULL; \
|
|
||||||
__tsk->thread.uregs->epsw &= ~EPSW_FE; \
|
|
||||||
} \
|
|
||||||
preempt_enable(); \
|
|
||||||
clear_using_fpu(__tsk); \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
extern asmlinkage void fpu_init_state(void);
|
|
||||||
extern asmlinkage void fpu_kill_state(struct task_struct *);
|
extern asmlinkage void fpu_kill_state(struct task_struct *);
|
||||||
extern asmlinkage void fpu_disabled(struct pt_regs *, enum exception_code);
|
|
||||||
extern asmlinkage void fpu_exception(struct pt_regs *, enum exception_code);
|
extern asmlinkage void fpu_exception(struct pt_regs *, enum exception_code);
|
||||||
|
extern asmlinkage void fpu_invalid_op(struct pt_regs *, enum exception_code);
|
||||||
#ifdef CONFIG_FPU
|
extern asmlinkage void fpu_init_state(void);
|
||||||
extern asmlinkage void fpu_save(struct fpu_state_struct *);
|
extern asmlinkage void fpu_save(struct fpu_state_struct *);
|
||||||
extern asmlinkage void fpu_restore(struct fpu_state_struct *);
|
|
||||||
#else
|
|
||||||
#define fpu_save(a)
|
|
||||||
#define fpu_restore(a)
|
|
||||||
#endif /* CONFIG_FPU */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* signal frame handlers
|
|
||||||
*/
|
|
||||||
extern int fpu_setup_sigcontext(struct fpucontext *buf);
|
extern int fpu_setup_sigcontext(struct fpucontext *buf);
|
||||||
extern int fpu_restore_sigcontext(struct fpucontext *buf);
|
extern int fpu_restore_sigcontext(struct fpucontext *buf);
|
||||||
|
|
||||||
|
static inline void unlazy_fpu(struct task_struct *tsk)
|
||||||
|
{
|
||||||
|
preempt_disable();
|
||||||
|
#ifndef CONFIG_LAZY_SAVE_FPU
|
||||||
|
if (tsk->thread.fpu_flags & THREAD_HAS_FPU) {
|
||||||
|
fpu_save(&tsk->thread.fpu_state);
|
||||||
|
tsk->thread.fpu_flags &= ~THREAD_HAS_FPU;
|
||||||
|
tsk->thread.uregs->epsw &= ~EPSW_FE;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
if (fpu_state_owner == tsk)
|
||||||
|
fpu_save(&tsk->thread.fpu_state);
|
||||||
|
#endif
|
||||||
|
preempt_enable();
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void exit_fpu(void)
|
||||||
|
{
|
||||||
|
#ifdef CONFIG_LAZY_SAVE_FPU
|
||||||
|
struct task_struct *tsk = current;
|
||||||
|
|
||||||
|
preempt_disable();
|
||||||
|
if (fpu_state_owner == tsk)
|
||||||
|
fpu_state_owner = NULL;
|
||||||
|
preempt_enable();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void flush_fpu(void)
|
||||||
|
{
|
||||||
|
struct task_struct *tsk = current;
|
||||||
|
|
||||||
|
preempt_disable();
|
||||||
|
#ifndef CONFIG_LAZY_SAVE_FPU
|
||||||
|
if (tsk->thread.fpu_flags & THREAD_HAS_FPU) {
|
||||||
|
tsk->thread.fpu_flags &= ~THREAD_HAS_FPU;
|
||||||
|
tsk->thread.uregs->epsw &= ~EPSW_FE;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
if (fpu_state_owner == tsk) {
|
||||||
|
fpu_state_owner = NULL;
|
||||||
|
tsk->thread.uregs->epsw &= ~EPSW_FE;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
preempt_enable();
|
||||||
|
clear_using_fpu(tsk);
|
||||||
|
}
|
||||||
|
|
||||||
|
#else /* CONFIG_FPU */
|
||||||
|
|
||||||
|
extern asmlinkage
|
||||||
|
void unexpected_fpu_exception(struct pt_regs *, enum exception_code);
|
||||||
|
#define fpu_invalid_op unexpected_fpu_exception
|
||||||
|
#define fpu_exception unexpected_fpu_exception
|
||||||
|
|
||||||
|
struct task_struct;
|
||||||
|
struct fpu_state_struct;
|
||||||
|
static inline bool is_using_fpu(struct task_struct *tsk) { return false; }
|
||||||
|
static inline void set_using_fpu(struct task_struct *tsk) {}
|
||||||
|
static inline void clear_using_fpu(struct task_struct *tsk) {}
|
||||||
|
static inline void fpu_init_state(void) {}
|
||||||
|
static inline void fpu_save(struct fpu_state_struct *s) {}
|
||||||
|
static inline void fpu_kill_state(struct task_struct *tsk) {}
|
||||||
|
static inline void unlazy_fpu(struct task_struct *tsk) {}
|
||||||
|
static inline void exit_fpu(void) {}
|
||||||
|
static inline void flush_fpu(void) {}
|
||||||
|
static inline int fpu_setup_sigcontext(struct fpucontext *buf) { return 0; }
|
||||||
|
static inline int fpu_restore_sigcontext(struct fpucontext *buf) { return 0; }
|
||||||
|
#endif /* CONFIG_FPU */
|
||||||
|
|
||||||
#endif /* __KERNEL__ */
|
#endif /* __KERNEL__ */
|
||||||
|
#endif /* !__ASSEMBLY__ */
|
||||||
#endif /* _ASM_FPU_H */
|
#endif /* _ASM_FPU_H */
|
||||||
|
@@ -95,6 +95,7 @@ struct thread_struct {
|
|||||||
struct pt_regs *__frame;
|
struct pt_regs *__frame;
|
||||||
unsigned long fpu_flags;
|
unsigned long fpu_flags;
|
||||||
#define THREAD_USING_FPU 0x00000001 /* T if this task is using the FPU */
|
#define THREAD_USING_FPU 0x00000001 /* T if this task is using the FPU */
|
||||||
|
#define THREAD_HAS_FPU 0x00000002 /* T if this task owns the FPU right now */
|
||||||
struct fpu_state_struct fpu_state;
|
struct fpu_state_struct fpu_state;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -19,6 +19,21 @@
|
|||||||
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
||||||
#include <linux/irqflags.h>
|
#include <linux/irqflags.h>
|
||||||
|
|
||||||
|
#if !defined(CONFIG_LAZY_SAVE_FPU)
|
||||||
|
struct fpu_state_struct;
|
||||||
|
extern asmlinkage void fpu_save(struct fpu_state_struct *);
|
||||||
|
#define switch_fpu(prev, next) \
|
||||||
|
do { \
|
||||||
|
if ((prev)->thread.fpu_flags & THREAD_HAS_FPU) { \
|
||||||
|
(prev)->thread.fpu_flags &= ~THREAD_HAS_FPU; \
|
||||||
|
(prev)->thread.uregs->epsw &= ~EPSW_FE; \
|
||||||
|
fpu_save(&(prev)->thread.fpu_state); \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
#else
|
||||||
|
#define switch_fpu(prev, next) do {} while (0)
|
||||||
|
#endif
|
||||||
|
|
||||||
struct task_struct;
|
struct task_struct;
|
||||||
struct thread_struct;
|
struct thread_struct;
|
||||||
|
|
||||||
@@ -30,6 +45,7 @@ struct task_struct *__switch_to(struct thread_struct *prev,
|
|||||||
/* context switching is now performed out-of-line in switch_to.S */
|
/* context switching is now performed out-of-line in switch_to.S */
|
||||||
#define switch_to(prev, next, last) \
|
#define switch_to(prev, next, last) \
|
||||||
do { \
|
do { \
|
||||||
|
switch_fpu(prev, next); \
|
||||||
current->thread.wchan = (u_long) __builtin_return_address(0); \
|
current->thread.wchan = (u_long) __builtin_return_address(0); \
|
||||||
(last) = __switch_to(&(prev)->thread, &(next)->thread, (prev)); \
|
(last) = __switch_to(&(prev)->thread, &(next)->thread, (prev)); \
|
||||||
mb(); \
|
mb(); \
|
||||||
|
@@ -3,13 +3,15 @@
|
|||||||
#
|
#
|
||||||
extra-y := head.o init_task.o vmlinux.lds
|
extra-y := head.o init_task.o vmlinux.lds
|
||||||
|
|
||||||
obj-y := process.o signal.o entry.o fpu.o traps.o irq.o \
|
fpu-obj-y := fpu-nofpu.o fpu-nofpu-low.o
|
||||||
|
fpu-obj-$(CONFIG_FPU) := fpu.o fpu-low.o
|
||||||
|
|
||||||
|
obj-y := process.o signal.o entry.o traps.o irq.o \
|
||||||
ptrace.o setup.o time.o sys_mn10300.o io.o kthread.o \
|
ptrace.o setup.o time.o sys_mn10300.o io.o kthread.o \
|
||||||
switch_to.o mn10300_ksyms.o kernel_execve.o
|
switch_to.o mn10300_ksyms.o kernel_execve.o $(fpu-obj-y)
|
||||||
|
|
||||||
obj-$(CONFIG_MN10300_WD_TIMER) += mn10300-watchdog.o mn10300-watchdog-low.o
|
obj-$(CONFIG_MN10300_WD_TIMER) += mn10300-watchdog.o mn10300-watchdog-low.o
|
||||||
|
|
||||||
obj-$(CONFIG_FPU) += fpu-low.o
|
|
||||||
|
|
||||||
obj-$(CONFIG_MN10300_TTYSM) += mn10300-serial.o mn10300-serial-low.o \
|
obj-$(CONFIG_MN10300_TTYSM) += mn10300-serial.o mn10300-serial-low.o \
|
||||||
mn10300-debug.o
|
mn10300-debug.o
|
||||||
|
@@ -67,6 +67,15 @@ void foo(void)
|
|||||||
OFFSET(THREAD_A3, thread_struct, a3);
|
OFFSET(THREAD_A3, thread_struct, a3);
|
||||||
OFFSET(THREAD_USP, thread_struct, usp);
|
OFFSET(THREAD_USP, thread_struct, usp);
|
||||||
OFFSET(THREAD_FRAME, thread_struct, __frame);
|
OFFSET(THREAD_FRAME, thread_struct, __frame);
|
||||||
|
#ifdef CONFIG_FPU
|
||||||
|
OFFSET(THREAD_FPU_FLAGS, thread_struct, fpu_flags);
|
||||||
|
OFFSET(THREAD_FPU_STATE, thread_struct, fpu_state);
|
||||||
|
DEFINE(__THREAD_USING_FPU, THREAD_USING_FPU);
|
||||||
|
DEFINE(__THREAD_HAS_FPU, THREAD_HAS_FPU);
|
||||||
|
#endif /* CONFIG_FPU */
|
||||||
|
BLANK();
|
||||||
|
|
||||||
|
OFFSET(TASK_THREAD, task_struct, thread);
|
||||||
BLANK();
|
BLANK();
|
||||||
|
|
||||||
DEFINE(CLONE_VM_asm, CLONE_VM);
|
DEFINE(CLONE_VM_asm, CLONE_VM);
|
||||||
|
@@ -8,25 +8,14 @@
|
|||||||
* as published by the Free Software Foundation; either version
|
* as published by the Free Software Foundation; either version
|
||||||
* 2 of the Licence, or (at your option) any later version.
|
* 2 of the Licence, or (at your option) any later version.
|
||||||
*/
|
*/
|
||||||
|
#include <linux/linkage.h>
|
||||||
#include <asm/cpu-regs.h>
|
#include <asm/cpu-regs.h>
|
||||||
|
#include <asm/smp.h>
|
||||||
|
#include <asm/thread_info.h>
|
||||||
|
#include <asm/asm-offsets.h>
|
||||||
|
#include <asm/frame.inc>
|
||||||
|
|
||||||
###############################################################################
|
.macro FPU_INIT_STATE_ALL
|
||||||
#
|
|
||||||
# void fpu_init_state(void)
|
|
||||||
# - initialise the FPU
|
|
||||||
#
|
|
||||||
###############################################################################
|
|
||||||
.globl fpu_init_state
|
|
||||||
.type fpu_init_state,@function
|
|
||||||
fpu_init_state:
|
|
||||||
mov epsw,d0
|
|
||||||
or EPSW_FE,epsw
|
|
||||||
|
|
||||||
#ifdef CONFIG_MN10300_PROC_MN103E010
|
|
||||||
nop
|
|
||||||
nop
|
|
||||||
nop
|
|
||||||
#endif
|
|
||||||
fmov 0,fs0
|
fmov 0,fs0
|
||||||
fmov fs0,fs1
|
fmov fs0,fs1
|
||||||
fmov fs0,fs2
|
fmov fs0,fs2
|
||||||
@@ -60,7 +49,100 @@ fpu_init_state:
|
|||||||
fmov fs0,fs30
|
fmov fs0,fs30
|
||||||
fmov fs0,fs31
|
fmov fs0,fs31
|
||||||
fmov FPCR_INIT,fpcr
|
fmov FPCR_INIT,fpcr
|
||||||
|
.endm
|
||||||
|
|
||||||
|
.macro FPU_SAVE_ALL areg,dreg
|
||||||
|
fmov fs0,(\areg+)
|
||||||
|
fmov fs1,(\areg+)
|
||||||
|
fmov fs2,(\areg+)
|
||||||
|
fmov fs3,(\areg+)
|
||||||
|
fmov fs4,(\areg+)
|
||||||
|
fmov fs5,(\areg+)
|
||||||
|
fmov fs6,(\areg+)
|
||||||
|
fmov fs7,(\areg+)
|
||||||
|
fmov fs8,(\areg+)
|
||||||
|
fmov fs9,(\areg+)
|
||||||
|
fmov fs10,(\areg+)
|
||||||
|
fmov fs11,(\areg+)
|
||||||
|
fmov fs12,(\areg+)
|
||||||
|
fmov fs13,(\areg+)
|
||||||
|
fmov fs14,(\areg+)
|
||||||
|
fmov fs15,(\areg+)
|
||||||
|
fmov fs16,(\areg+)
|
||||||
|
fmov fs17,(\areg+)
|
||||||
|
fmov fs18,(\areg+)
|
||||||
|
fmov fs19,(\areg+)
|
||||||
|
fmov fs20,(\areg+)
|
||||||
|
fmov fs21,(\areg+)
|
||||||
|
fmov fs22,(\areg+)
|
||||||
|
fmov fs23,(\areg+)
|
||||||
|
fmov fs24,(\areg+)
|
||||||
|
fmov fs25,(\areg+)
|
||||||
|
fmov fs26,(\areg+)
|
||||||
|
fmov fs27,(\areg+)
|
||||||
|
fmov fs28,(\areg+)
|
||||||
|
fmov fs29,(\areg+)
|
||||||
|
fmov fs30,(\areg+)
|
||||||
|
fmov fs31,(\areg+)
|
||||||
|
fmov fpcr,\dreg
|
||||||
|
mov \dreg,(\areg)
|
||||||
|
.endm
|
||||||
|
|
||||||
|
.macro FPU_RESTORE_ALL areg,dreg
|
||||||
|
fmov (\areg+),fs0
|
||||||
|
fmov (\areg+),fs1
|
||||||
|
fmov (\areg+),fs2
|
||||||
|
fmov (\areg+),fs3
|
||||||
|
fmov (\areg+),fs4
|
||||||
|
fmov (\areg+),fs5
|
||||||
|
fmov (\areg+),fs6
|
||||||
|
fmov (\areg+),fs7
|
||||||
|
fmov (\areg+),fs8
|
||||||
|
fmov (\areg+),fs9
|
||||||
|
fmov (\areg+),fs10
|
||||||
|
fmov (\areg+),fs11
|
||||||
|
fmov (\areg+),fs12
|
||||||
|
fmov (\areg+),fs13
|
||||||
|
fmov (\areg+),fs14
|
||||||
|
fmov (\areg+),fs15
|
||||||
|
fmov (\areg+),fs16
|
||||||
|
fmov (\areg+),fs17
|
||||||
|
fmov (\areg+),fs18
|
||||||
|
fmov (\areg+),fs19
|
||||||
|
fmov (\areg+),fs20
|
||||||
|
fmov (\areg+),fs21
|
||||||
|
fmov (\areg+),fs22
|
||||||
|
fmov (\areg+),fs23
|
||||||
|
fmov (\areg+),fs24
|
||||||
|
fmov (\areg+),fs25
|
||||||
|
fmov (\areg+),fs26
|
||||||
|
fmov (\areg+),fs27
|
||||||
|
fmov (\areg+),fs28
|
||||||
|
fmov (\areg+),fs29
|
||||||
|
fmov (\areg+),fs30
|
||||||
|
fmov (\areg+),fs31
|
||||||
|
mov (\areg),\dreg
|
||||||
|
fmov \dreg,fpcr
|
||||||
|
.endm
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
#
|
||||||
|
# void fpu_init_state(void)
|
||||||
|
# - initialise the FPU
|
||||||
|
#
|
||||||
|
###############################################################################
|
||||||
|
.globl fpu_init_state
|
||||||
|
.type fpu_init_state,@function
|
||||||
|
fpu_init_state:
|
||||||
|
mov epsw,d0
|
||||||
|
or EPSW_FE,epsw
|
||||||
|
|
||||||
|
#ifdef CONFIG_MN10300_PROC_MN103E010
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
#endif
|
||||||
|
FPU_INIT_STATE_ALL
|
||||||
#ifdef CONFIG_MN10300_PROC_MN103E010
|
#ifdef CONFIG_MN10300_PROC_MN103E010
|
||||||
nop
|
nop
|
||||||
nop
|
nop
|
||||||
@@ -89,40 +171,7 @@ fpu_save:
|
|||||||
nop
|
nop
|
||||||
#endif
|
#endif
|
||||||
mov d0,a0
|
mov d0,a0
|
||||||
fmov fs0,(a0+)
|
FPU_SAVE_ALL a0,d0
|
||||||
fmov fs1,(a0+)
|
|
||||||
fmov fs2,(a0+)
|
|
||||||
fmov fs3,(a0+)
|
|
||||||
fmov fs4,(a0+)
|
|
||||||
fmov fs5,(a0+)
|
|
||||||
fmov fs6,(a0+)
|
|
||||||
fmov fs7,(a0+)
|
|
||||||
fmov fs8,(a0+)
|
|
||||||
fmov fs9,(a0+)
|
|
||||||
fmov fs10,(a0+)
|
|
||||||
fmov fs11,(a0+)
|
|
||||||
fmov fs12,(a0+)
|
|
||||||
fmov fs13,(a0+)
|
|
||||||
fmov fs14,(a0+)
|
|
||||||
fmov fs15,(a0+)
|
|
||||||
fmov fs16,(a0+)
|
|
||||||
fmov fs17,(a0+)
|
|
||||||
fmov fs18,(a0+)
|
|
||||||
fmov fs19,(a0+)
|
|
||||||
fmov fs20,(a0+)
|
|
||||||
fmov fs21,(a0+)
|
|
||||||
fmov fs22,(a0+)
|
|
||||||
fmov fs23,(a0+)
|
|
||||||
fmov fs24,(a0+)
|
|
||||||
fmov fs25,(a0+)
|
|
||||||
fmov fs26,(a0+)
|
|
||||||
fmov fs27,(a0+)
|
|
||||||
fmov fs28,(a0+)
|
|
||||||
fmov fs29,(a0+)
|
|
||||||
fmov fs30,(a0+)
|
|
||||||
fmov fs31,(a0+)
|
|
||||||
fmov fpcr,d0
|
|
||||||
mov d0,(a0)
|
|
||||||
#ifdef CONFIG_MN10300_PROC_MN103E010
|
#ifdef CONFIG_MN10300_PROC_MN103E010
|
||||||
nop
|
nop
|
||||||
nop
|
nop
|
||||||
@@ -135,63 +184,75 @@ fpu_save:
|
|||||||
|
|
||||||
###############################################################################
|
###############################################################################
|
||||||
#
|
#
|
||||||
# void fpu_restore(struct fpu_state_struct *)
|
# void fpu_disabled(void)
|
||||||
# - restore the fpu state
|
# - handle an exception due to the FPU being disabled
|
||||||
# - note that an FPU Operational exception might occur during this process
|
# when CONFIG_FPU is enabled
|
||||||
#
|
#
|
||||||
###############################################################################
|
###############################################################################
|
||||||
.globl fpu_restore
|
.type fpu_disabled,@function
|
||||||
.type fpu_restore,@function
|
.globl fpu_disabled
|
||||||
fpu_restore:
|
fpu_disabled:
|
||||||
mov epsw,d1
|
or EPSW_nAR|EPSW_FE,epsw
|
||||||
or EPSW_FE,epsw /* enable the FPU so we can access it */
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
|
||||||
#ifdef CONFIG_MN10300_PROC_MN103E010
|
mov sp,a1
|
||||||
nop
|
mov (a1),d1 /* get epsw of user context */
|
||||||
nop
|
and ~(THREAD_SIZE-1),a1 /* a1: (thread_info *ti) */
|
||||||
#endif
|
mov (TI_task,a1),a2 /* a2: (task_struct *tsk) */
|
||||||
mov d0,a0
|
btst EPSW_nSL,d1
|
||||||
fmov (a0+),fs0
|
beq fpu_used_in_kernel
|
||||||
fmov (a0+),fs1
|
|
||||||
fmov (a0+),fs2
|
|
||||||
fmov (a0+),fs3
|
|
||||||
fmov (a0+),fs4
|
|
||||||
fmov (a0+),fs5
|
|
||||||
fmov (a0+),fs6
|
|
||||||
fmov (a0+),fs7
|
|
||||||
fmov (a0+),fs8
|
|
||||||
fmov (a0+),fs9
|
|
||||||
fmov (a0+),fs10
|
|
||||||
fmov (a0+),fs11
|
|
||||||
fmov (a0+),fs12
|
|
||||||
fmov (a0+),fs13
|
|
||||||
fmov (a0+),fs14
|
|
||||||
fmov (a0+),fs15
|
|
||||||
fmov (a0+),fs16
|
|
||||||
fmov (a0+),fs17
|
|
||||||
fmov (a0+),fs18
|
|
||||||
fmov (a0+),fs19
|
|
||||||
fmov (a0+),fs20
|
|
||||||
fmov (a0+),fs21
|
|
||||||
fmov (a0+),fs22
|
|
||||||
fmov (a0+),fs23
|
|
||||||
fmov (a0+),fs24
|
|
||||||
fmov (a0+),fs25
|
|
||||||
fmov (a0+),fs26
|
|
||||||
fmov (a0+),fs27
|
|
||||||
fmov (a0+),fs28
|
|
||||||
fmov (a0+),fs29
|
|
||||||
fmov (a0+),fs30
|
|
||||||
fmov (a0+),fs31
|
|
||||||
mov (a0),d0
|
|
||||||
fmov d0,fpcr
|
|
||||||
#ifdef CONFIG_MN10300_PROC_MN103E010
|
|
||||||
nop
|
|
||||||
nop
|
|
||||||
nop
|
|
||||||
#endif
|
|
||||||
|
|
||||||
mov d1,epsw
|
or EPSW_FE,d1
|
||||||
ret [],0
|
mov d1,(sp)
|
||||||
|
mov (TASK_THREAD+THREAD_FPU_FLAGS,a2),d1
|
||||||
|
#ifndef CONFIG_LAZY_SAVE_FPU
|
||||||
|
or __THREAD_HAS_FPU,d1
|
||||||
|
mov d1,(TASK_THREAD+THREAD_FPU_FLAGS,a2)
|
||||||
|
#else /* !CONFIG_LAZY_SAVE_FPU */
|
||||||
|
mov (fpu_state_owner),a0
|
||||||
|
cmp 0,a0
|
||||||
|
beq fpu_regs_save_end
|
||||||
|
|
||||||
.size fpu_restore,.-fpu_restore
|
mov (TASK_THREAD+THREAD_UREGS,a0),a1
|
||||||
|
add TASK_THREAD+THREAD_FPU_STATE,a0
|
||||||
|
FPU_SAVE_ALL a0,d0
|
||||||
|
|
||||||
|
mov (REG_EPSW,a1),d0
|
||||||
|
and ~EPSW_FE,d0
|
||||||
|
mov d0,(REG_EPSW,a1)
|
||||||
|
|
||||||
|
fpu_regs_save_end:
|
||||||
|
mov a2,(fpu_state_owner)
|
||||||
|
#endif /* !CONFIG_LAZY_SAVE_FPU */
|
||||||
|
|
||||||
|
btst __THREAD_USING_FPU,d1
|
||||||
|
beq fpu_regs_init
|
||||||
|
add TASK_THREAD+THREAD_FPU_STATE,a2
|
||||||
|
FPU_RESTORE_ALL a2,d0
|
||||||
|
rti
|
||||||
|
|
||||||
|
fpu_regs_init:
|
||||||
|
FPU_INIT_STATE_ALL
|
||||||
|
add TASK_THREAD+THREAD_FPU_FLAGS,a2
|
||||||
|
bset __THREAD_USING_FPU,(0,a2)
|
||||||
|
rti
|
||||||
|
|
||||||
|
fpu_used_in_kernel:
|
||||||
|
and ~(EPSW_nAR|EPSW_FE),epsw
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
|
||||||
|
add -4,sp
|
||||||
|
SAVE_ALL
|
||||||
|
mov -1,d0
|
||||||
|
mov d0,(REG_ORIG_D0,fp)
|
||||||
|
|
||||||
|
and ~EPSW_NMID,epsw
|
||||||
|
|
||||||
|
mov fp,d0
|
||||||
|
call fpu_disabled_in_kernel[],0
|
||||||
|
jmp ret_from_exception
|
||||||
|
|
||||||
|
.size fpu_disabled,.-fpu_disabled
|
||||||
|
39
arch/mn10300/kernel/fpu-nofpu-low.S
Normal file
39
arch/mn10300/kernel/fpu-nofpu-low.S
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
/* MN10300 Low level FPU management operations
|
||||||
|
*
|
||||||
|
* Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
|
||||||
|
* Written by David Howells (dhowells@redhat.com)
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public Licence
|
||||||
|
* as published by the Free Software Foundation; either version
|
||||||
|
* 2 of the Licence, or (at your option) any later version.
|
||||||
|
*/
|
||||||
|
#include <linux/linkage.h>
|
||||||
|
#include <asm/cpu-regs.h>
|
||||||
|
#include <asm/smp.h>
|
||||||
|
#include <asm/thread_info.h>
|
||||||
|
#include <asm/asm-offsets.h>
|
||||||
|
#include <asm/frame.inc>
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
#
|
||||||
|
# void fpu_disabled(void)
|
||||||
|
# - handle an exception due to the FPU being disabled
|
||||||
|
# when CONFIG_FPU is disabled
|
||||||
|
#
|
||||||
|
###############################################################################
|
||||||
|
.type fpu_disabled,@function
|
||||||
|
.globl fpu_disabled
|
||||||
|
fpu_disabled:
|
||||||
|
add -4,sp
|
||||||
|
SAVE_ALL
|
||||||
|
mov -1,d0
|
||||||
|
mov d0,(REG_ORIG_D0,fp)
|
||||||
|
|
||||||
|
and ~EPSW_NMID,epsw
|
||||||
|
|
||||||
|
mov fp,d0
|
||||||
|
call unexpected_fpu_exception[],0
|
||||||
|
jmp ret_from_exception
|
||||||
|
|
||||||
|
.size fpu_disabled,.-fpu_disabled
|
30
arch/mn10300/kernel/fpu-nofpu.c
Normal file
30
arch/mn10300/kernel/fpu-nofpu.c
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
/* MN10300 FPU management
|
||||||
|
*
|
||||||
|
* Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
|
||||||
|
* Written by David Howells (dhowells@redhat.com)
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public Licence
|
||||||
|
* as published by the Free Software Foundation; either version
|
||||||
|
* 2 of the Licence, or (at your option) any later version.
|
||||||
|
*/
|
||||||
|
#include <asm/fpu.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* handle an FPU operational exception
|
||||||
|
* - there's a possibility that if the FPU is asynchronous, the signal might
|
||||||
|
* be meant for a process other than the current one
|
||||||
|
*/
|
||||||
|
asmlinkage
|
||||||
|
void unexpected_fpu_exception(struct pt_regs *regs, enum exception_code code)
|
||||||
|
{
|
||||||
|
panic("An FPU exception was received, but there's no FPU enabled.");
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* fill in the FPU structure for a core dump
|
||||||
|
*/
|
||||||
|
int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpreg)
|
||||||
|
{
|
||||||
|
return 0; /* not valid */
|
||||||
|
}
|
@@ -12,56 +12,19 @@
|
|||||||
#include <asm/fpu.h>
|
#include <asm/fpu.h>
|
||||||
#include <asm/elf.h>
|
#include <asm/elf.h>
|
||||||
#include <asm/exceptions.h>
|
#include <asm/exceptions.h>
|
||||||
|
#include <asm/system.h>
|
||||||
|
|
||||||
|
#ifdef CONFIG_LAZY_SAVE_FPU
|
||||||
struct task_struct *fpu_state_owner;
|
struct task_struct *fpu_state_owner;
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* handle an exception due to the FPU being disabled
|
* error functions in FPU disabled exception
|
||||||
*/
|
*/
|
||||||
asmlinkage void fpu_disabled(struct pt_regs *regs, enum exception_code code)
|
asmlinkage void fpu_disabled_in_kernel(struct pt_regs *regs)
|
||||||
{
|
{
|
||||||
struct task_struct *tsk = current;
|
die_if_no_fixup("An FPU Disabled exception happened in kernel space\n",
|
||||||
|
regs, EXCEP_FPU_DISABLED);
|
||||||
if (!user_mode(regs))
|
|
||||||
die_if_no_fixup("An FPU Disabled exception happened in"
|
|
||||||
" kernel space\n",
|
|
||||||
regs, code);
|
|
||||||
|
|
||||||
#ifdef CONFIG_FPU
|
|
||||||
preempt_disable();
|
|
||||||
|
|
||||||
/* transfer the last process's FPU state to memory */
|
|
||||||
if (fpu_state_owner) {
|
|
||||||
fpu_save(&fpu_state_owner->thread.fpu_state);
|
|
||||||
fpu_state_owner->thread.uregs->epsw &= ~EPSW_FE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* the current process now owns the FPU state */
|
|
||||||
fpu_state_owner = tsk;
|
|
||||||
regs->epsw |= EPSW_FE;
|
|
||||||
|
|
||||||
/* load the FPU with the current process's FPU state or invent a new
|
|
||||||
* clean one if the process doesn't have one */
|
|
||||||
if (is_using_fpu(tsk)) {
|
|
||||||
fpu_restore(&tsk->thread.fpu_state);
|
|
||||||
} else {
|
|
||||||
fpu_init_state();
|
|
||||||
set_using_fpu(tsk);
|
|
||||||
}
|
|
||||||
|
|
||||||
preempt_enable();
|
|
||||||
#else
|
|
||||||
{
|
|
||||||
siginfo_t info;
|
|
||||||
|
|
||||||
info.si_signo = SIGFPE;
|
|
||||||
info.si_errno = 0;
|
|
||||||
info.si_addr = (void *) tsk->thread.uregs->pc;
|
|
||||||
info.si_code = FPE_FLTINV;
|
|
||||||
|
|
||||||
force_sig_info(SIGFPE, &info, tsk);
|
|
||||||
}
|
|
||||||
#endif /* CONFIG_FPU */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -71,15 +34,16 @@ asmlinkage void fpu_disabled(struct pt_regs *regs, enum exception_code code)
|
|||||||
*/
|
*/
|
||||||
asmlinkage void fpu_exception(struct pt_regs *regs, enum exception_code code)
|
asmlinkage void fpu_exception(struct pt_regs *regs, enum exception_code code)
|
||||||
{
|
{
|
||||||
struct task_struct *tsk = fpu_state_owner;
|
struct task_struct *tsk = current;
|
||||||
siginfo_t info;
|
siginfo_t info;
|
||||||
|
u32 fpcr;
|
||||||
|
|
||||||
if (!user_mode(regs))
|
if (!user_mode(regs))
|
||||||
die_if_no_fixup("An FPU Operation exception happened in"
|
die_if_no_fixup("An FPU Operation exception happened in"
|
||||||
" kernel space\n",
|
" kernel space\n",
|
||||||
regs, code);
|
regs, code);
|
||||||
|
|
||||||
if (!tsk)
|
if (!is_using_fpu(tsk))
|
||||||
die_if_no_fixup("An FPU Operation exception happened,"
|
die_if_no_fixup("An FPU Operation exception happened,"
|
||||||
" but the FPU is not in use",
|
" but the FPU is not in use",
|
||||||
regs, code);
|
regs, code);
|
||||||
@@ -89,27 +53,9 @@ asmlinkage void fpu_exception(struct pt_regs *regs, enum exception_code code)
|
|||||||
info.si_addr = (void *) tsk->thread.uregs->pc;
|
info.si_addr = (void *) tsk->thread.uregs->pc;
|
||||||
info.si_code = FPE_FLTINV;
|
info.si_code = FPE_FLTINV;
|
||||||
|
|
||||||
#ifdef CONFIG_FPU
|
unlazy_fpu(tsk);
|
||||||
{
|
|
||||||
u32 fpcr;
|
|
||||||
|
|
||||||
/* get FPCR (we need to enable the FPU whilst we do this) */
|
fpcr = tsk->thread.fpu_state.fpcr;
|
||||||
asm volatile(" or %1,epsw \n"
|
|
||||||
#ifdef CONFIG_MN10300_PROC_MN103E010
|
|
||||||
" nop \n"
|
|
||||||
" nop \n"
|
|
||||||
" nop \n"
|
|
||||||
#endif
|
|
||||||
" fmov fpcr,%0 \n"
|
|
||||||
#ifdef CONFIG_MN10300_PROC_MN103E010
|
|
||||||
" nop \n"
|
|
||||||
" nop \n"
|
|
||||||
" nop \n"
|
|
||||||
#endif
|
|
||||||
" and %2,epsw \n"
|
|
||||||
: "=&d"(fpcr)
|
|
||||||
: "i"(EPSW_FE), "i"(~EPSW_FE)
|
|
||||||
);
|
|
||||||
|
|
||||||
if (fpcr & FPCR_EC_Z)
|
if (fpcr & FPCR_EC_Z)
|
||||||
info.si_code = FPE_FLTDIV;
|
info.si_code = FPE_FLTDIV;
|
||||||
@@ -119,18 +65,33 @@ asmlinkage void fpu_exception(struct pt_regs *regs, enum exception_code code)
|
|||||||
info.si_code = FPE_FLTUND;
|
info.si_code = FPE_FLTUND;
|
||||||
else if (fpcr & FPCR_EC_I)
|
else if (fpcr & FPCR_EC_I)
|
||||||
info.si_code = FPE_FLTRES;
|
info.si_code = FPE_FLTRES;
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
force_sig_info(SIGFPE, &info, tsk);
|
force_sig_info(SIGFPE, &info, tsk);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* handle an FPU invalid_op exception
|
||||||
|
* - Derived from DO_EINFO() macro in arch/mn10300/kernel/traps.c
|
||||||
|
*/
|
||||||
|
asmlinkage void fpu_invalid_op(struct pt_regs *regs, enum exception_code code)
|
||||||
|
{
|
||||||
|
siginfo_t info;
|
||||||
|
|
||||||
|
if (!user_mode(regs))
|
||||||
|
die_if_no_fixup("FPU invalid opcode", regs, code);
|
||||||
|
|
||||||
|
info.si_signo = SIGILL;
|
||||||
|
info.si_errno = 0;
|
||||||
|
info.si_code = ILL_COPROC;
|
||||||
|
info.si_addr = (void *) regs->pc;
|
||||||
|
force_sig_info(info.si_signo, &info, current);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* save the FPU state to a signal context
|
* save the FPU state to a signal context
|
||||||
*/
|
*/
|
||||||
int fpu_setup_sigcontext(struct fpucontext *fpucontext)
|
int fpu_setup_sigcontext(struct fpucontext *fpucontext)
|
||||||
{
|
{
|
||||||
#ifdef CONFIG_FPU
|
|
||||||
struct task_struct *tsk = current;
|
struct task_struct *tsk = current;
|
||||||
|
|
||||||
if (!is_using_fpu(tsk))
|
if (!is_using_fpu(tsk))
|
||||||
@@ -142,11 +103,19 @@ int fpu_setup_sigcontext(struct fpucontext *fpucontext)
|
|||||||
*/
|
*/
|
||||||
preempt_disable();
|
preempt_disable();
|
||||||
|
|
||||||
|
#ifndef CONFIG_LAZY_SAVE_FPU
|
||||||
|
if (tsk->thread.fpu_flags & THREAD_HAS_FPU) {
|
||||||
|
fpu_save(&tsk->thread.fpu_state);
|
||||||
|
tsk->thread.uregs->epsw &= ~EPSW_FE;
|
||||||
|
tsk->thread.fpu_flags &= ~THREAD_HAS_FPU;
|
||||||
|
}
|
||||||
|
#else /* !CONFIG_LAZY_SAVE_FPU */
|
||||||
if (fpu_state_owner == tsk) {
|
if (fpu_state_owner == tsk) {
|
||||||
fpu_save(&tsk->thread.fpu_state);
|
fpu_save(&tsk->thread.fpu_state);
|
||||||
fpu_state_owner->thread.uregs->epsw &= ~EPSW_FE;
|
fpu_state_owner->thread.uregs->epsw &= ~EPSW_FE;
|
||||||
fpu_state_owner = NULL;
|
fpu_state_owner = NULL;
|
||||||
}
|
}
|
||||||
|
#endif /* !CONFIG_LAZY_SAVE_FPU */
|
||||||
|
|
||||||
preempt_enable();
|
preempt_enable();
|
||||||
|
|
||||||
@@ -161,9 +130,6 @@ int fpu_setup_sigcontext(struct fpucontext *fpucontext)
|
|||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
#else
|
|
||||||
return 0;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -171,17 +137,23 @@ int fpu_setup_sigcontext(struct fpucontext *fpucontext)
|
|||||||
*/
|
*/
|
||||||
void fpu_kill_state(struct task_struct *tsk)
|
void fpu_kill_state(struct task_struct *tsk)
|
||||||
{
|
{
|
||||||
#ifdef CONFIG_FPU
|
|
||||||
/* disown anything left in the FPU */
|
/* disown anything left in the FPU */
|
||||||
preempt_disable();
|
preempt_disable();
|
||||||
|
|
||||||
|
#ifndef CONFIG_LAZY_SAVE_FPU
|
||||||
|
if (tsk->thread.fpu_flags & THREAD_HAS_FPU) {
|
||||||
|
tsk->thread.uregs->epsw &= ~EPSW_FE;
|
||||||
|
tsk->thread.fpu_flags &= ~THREAD_HAS_FPU;
|
||||||
|
}
|
||||||
|
#else /* !CONFIG_LAZY_SAVE_FPU */
|
||||||
if (fpu_state_owner == tsk) {
|
if (fpu_state_owner == tsk) {
|
||||||
fpu_state_owner->thread.uregs->epsw &= ~EPSW_FE;
|
fpu_state_owner->thread.uregs->epsw &= ~EPSW_FE;
|
||||||
fpu_state_owner = NULL;
|
fpu_state_owner = NULL;
|
||||||
}
|
}
|
||||||
|
#endif /* !CONFIG_LAZY_SAVE_FPU */
|
||||||
|
|
||||||
preempt_enable();
|
preempt_enable();
|
||||||
#endif
|
|
||||||
/* we no longer have a valid current FPU state */
|
/* we no longer have a valid current FPU state */
|
||||||
clear_using_fpu(tsk);
|
clear_using_fpu(tsk);
|
||||||
}
|
}
|
||||||
@@ -195,8 +167,7 @@ int fpu_restore_sigcontext(struct fpucontext *fpucontext)
|
|||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
/* load up the old FPU state */
|
/* load up the old FPU state */
|
||||||
ret = copy_from_user(&tsk->thread.fpu_state,
|
ret = copy_from_user(&tsk->thread.fpu_state, fpucontext,
|
||||||
fpucontext,
|
|
||||||
min(sizeof(struct fpu_state_struct),
|
min(sizeof(struct fpu_state_struct),
|
||||||
sizeof(struct fpucontext)));
|
sizeof(struct fpucontext)));
|
||||||
if (!ret)
|
if (!ret)
|
||||||
|
@@ -101,7 +101,6 @@ DO_EINFO(SIGILL, {}, "invalid opcode", invalid_op, ILL_ILLOPC);
|
|||||||
DO_EINFO(SIGILL, {}, "invalid ex opcode", invalid_exop, ILL_ILLOPC);
|
DO_EINFO(SIGILL, {}, "invalid ex opcode", invalid_exop, ILL_ILLOPC);
|
||||||
DO_EINFO(SIGBUS, {}, "invalid address", mem_error, BUS_ADRERR);
|
DO_EINFO(SIGBUS, {}, "invalid address", mem_error, BUS_ADRERR);
|
||||||
DO_EINFO(SIGBUS, {}, "bus error", bus_error, BUS_ADRERR);
|
DO_EINFO(SIGBUS, {}, "bus error", bus_error, BUS_ADRERR);
|
||||||
DO_EINFO(SIGILL, {}, "FPU invalid opcode", fpu_invalid_op, ILL_COPROC);
|
|
||||||
|
|
||||||
DO_ERROR(SIGTRAP,
|
DO_ERROR(SIGTRAP,
|
||||||
#ifndef CONFIG_MN10300_USING_JTAG
|
#ifndef CONFIG_MN10300_USING_JTAG
|
||||||
@@ -561,7 +560,6 @@ void __init trap_init(void)
|
|||||||
set_excp_vector(EXCEP_PRIVINSACC, insn_acc_error);
|
set_excp_vector(EXCEP_PRIVINSACC, insn_acc_error);
|
||||||
set_excp_vector(EXCEP_PRIVDATACC, data_acc_error);
|
set_excp_vector(EXCEP_PRIVDATACC, data_acc_error);
|
||||||
set_excp_vector(EXCEP_DATINSACC, insn_acc_error);
|
set_excp_vector(EXCEP_DATINSACC, insn_acc_error);
|
||||||
set_excp_vector(EXCEP_FPU_DISABLED, fpu_disabled);
|
|
||||||
set_excp_vector(EXCEP_FPU_UNIMPINS, fpu_invalid_op);
|
set_excp_vector(EXCEP_FPU_UNIMPINS, fpu_invalid_op);
|
||||||
set_excp_vector(EXCEP_FPU_OPERATION, fpu_exception);
|
set_excp_vector(EXCEP_FPU_OPERATION, fpu_exception);
|
||||||
|
|
||||||
|
@@ -9,6 +9,7 @@
|
|||||||
* 2 of the Licence, or (at your option) any later version.
|
* 2 of the Licence, or (at your option) any later version.
|
||||||
*/
|
*/
|
||||||
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
||||||
|
#include <asm/fpu.h>
|
||||||
#include <asm/rtc.h>
|
#include <asm/rtc.h>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -28,6 +29,7 @@ asmlinkage void __init processor_init(void)
|
|||||||
__set_intr_stub(EXCEP_DAERROR, dtlb_aerror);
|
__set_intr_stub(EXCEP_DAERROR, dtlb_aerror);
|
||||||
__set_intr_stub(EXCEP_BUSERROR, raw_bus_error);
|
__set_intr_stub(EXCEP_BUSERROR, raw_bus_error);
|
||||||
__set_intr_stub(EXCEP_DOUBLE_FAULT, double_fault);
|
__set_intr_stub(EXCEP_DOUBLE_FAULT, double_fault);
|
||||||
|
__set_intr_stub(EXCEP_FPU_DISABLED, fpu_disabled);
|
||||||
__set_intr_stub(EXCEP_SYSCALL0, system_call);
|
__set_intr_stub(EXCEP_SYSCALL0, system_call);
|
||||||
|
|
||||||
__set_intr_stub(EXCEP_NMI, nmi_handler);
|
__set_intr_stub(EXCEP_NMI, nmi_handler);
|
||||||
|
Reference in New Issue
Block a user