Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 181060
b: refs/heads/master
c: 0ea820c
h: refs/heads/master
v: v3
  • Loading branch information
Paul Mundt committed Jan 13, 2010
1 parent a1ba46d commit e5eab2d
Show file tree
Hide file tree
Showing 14 changed files with 293 additions and 286 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: a3705799e2cc5fb69d88ad6a7f317a8f5597f18d
refs/heads/master: 0ea820cf9bf58f735ed40ec67947159c4f170012
35 changes: 12 additions & 23 deletions trunk/arch/sh/include/asm/fpu.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
#define __ASM_SH_FPU_H

#ifndef __ASSEMBLY__
#include <linux/preempt.h>
#include <asm/ptrace.h>

struct task_struct;

#ifdef CONFIG_SH_FPU
static inline void release_fpu(struct pt_regs *regs)
Expand All @@ -16,22 +16,23 @@ static inline void grab_fpu(struct pt_regs *regs)
regs->sr &= ~SR_FD;
}

struct task_struct;

extern void save_fpu(struct task_struct *__tsk);
void fpu_state_restore(struct pt_regs *regs);
extern void restore_fpu(struct task_struct *__tsk);
extern void fpu_state_restore(struct pt_regs *regs);
extern void __fpu_state_restore(void);
#else

#define save_fpu(tsk) do { } while (0)
#define release_fpu(regs) do { } while (0)
#define grab_fpu(regs) do { } while (0)
#define fpu_state_restore(regs) do { } while (0)

#define save_fpu(tsk) do { } while (0)
#define restore_fpu(tsk) do { } while (0)
#define release_fpu(regs) do { } while (0)
#define grab_fpu(regs) do { } while (0)
#define fpu_state_restore(regs) do { } while (0)
#define __fpu_state_restore(regs) do { } while (0)
#endif

struct user_regset;

extern int do_fpu_inst(unsigned short, struct pt_regs *);
extern int init_fpu(struct task_struct *);

extern int fpregs_get(struct task_struct *target,
const struct user_regset *regset,
Expand Down Expand Up @@ -65,18 +66,6 @@ static inline void clear_fpu(struct task_struct *tsk, struct pt_regs *regs)
preempt_enable();
}

static inline int init_fpu(struct task_struct *tsk)
{
if (tsk_used_math(tsk)) {
if ((boot_cpu_data.flags & CPU_HAS_FPU) && tsk == current)
unlazy_fpu(tsk, task_pt_regs(tsk));
return 0;
}

set_stopped_child_used_math(tsk);
return 0;
}

#endif /* __ASSEMBLY__ */

#endif /* __ASM_SH_FPU_H */
16 changes: 10 additions & 6 deletions trunk/arch/sh/include/asm/processor_32.h
Original file line number Diff line number Diff line change
Expand Up @@ -90,11 +90,15 @@ struct sh_fpu_soft_struct {
unsigned long entry_pc;
};

union sh_fpu_union {
struct sh_fpu_hard_struct hard;
struct sh_fpu_soft_struct soft;
union thread_xstate {
struct sh_fpu_hard_struct hardfpu;
struct sh_fpu_soft_struct softfpu;
};

extern unsigned int xstate_size;
extern void free_thread_xstate(struct task_struct *);
extern struct kmem_cache *task_xstate_cachep;

struct thread_struct {
/* Saved registers when thread is descheduled */
unsigned long sp;
Expand All @@ -103,13 +107,13 @@ struct thread_struct {
/* Hardware debugging registers */
unsigned long ubc_pc;

/* floating point info */
union sh_fpu_union fpu;

#ifdef CONFIG_SH_DSP
/* Dsp status information */
struct sh_dsp_struct dsp_status;
#endif

/* Extended processor state */
union thread_xstate *xstate;
};

/* Count of active tasks with UBC settings */
Expand Down
4 changes: 4 additions & 0 deletions trunk/arch/sh/include/asm/thread_info.h
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,10 @@ static inline struct thread_info *current_thread_info(void)

extern struct thread_info *alloc_thread_info(struct task_struct *tsk);
extern void free_thread_info(struct thread_info *ti);
extern void arch_task_cache_init(void);
#define arch_task_cache_init arch_task_cache_init
extern int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src);
extern void init_thread_xstate(void);

#define __HAVE_ARCH_THREAD_INFO_ALLOCATOR

Expand Down
2 changes: 2 additions & 0 deletions trunk/arch/sh/kernel/cpu/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,7 @@ obj-$(CONFIG_ARCH_SHMOBILE) += shmobile/

obj-$(CONFIG_SH_ADC) += adc.o
obj-$(CONFIG_SH_CLK_CPG) += clock-cpg.o
obj-$(CONFIG_SH_FPU) += fpu.o
obj-$(CONFIG_SH_FPU_EMU) += fpu.o

obj-y += irq/ init.o clock.o hwblk.o
82 changes: 82 additions & 0 deletions trunk/arch/sh/kernel/cpu/fpu.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
#include <linux/sched.h>
#include <asm/processor.h>
#include <asm/fpu.h>

int init_fpu(struct task_struct *tsk)
{
if (tsk_used_math(tsk)) {
if ((boot_cpu_data.flags & CPU_HAS_FPU) && tsk == current)
unlazy_fpu(tsk, task_pt_regs(tsk));
return 0;
}

/*
* Memory allocation at the first usage of the FPU and other state.
*/
if (!tsk->thread.xstate) {
tsk->thread.xstate = kmem_cache_alloc(task_xstate_cachep,
GFP_KERNEL);
if (!tsk->thread.xstate)
return -ENOMEM;
}

if (boot_cpu_data.flags & CPU_HAS_FPU) {
struct sh_fpu_hard_struct *fp = &tsk->thread.xstate->hardfpu;
memset(fp, 0, xstate_size);
fp->fpscr = FPSCR_INIT;
} else {
struct sh_fpu_soft_struct *fp = &tsk->thread.xstate->softfpu;
memset(fp, 0, xstate_size);
fp->fpscr = FPSCR_INIT;
}

set_stopped_child_used_math(tsk);
return 0;
}

#ifdef CONFIG_SH_FPU
void __fpu_state_restore(void)
{
struct task_struct *tsk = current;

restore_fpu(tsk);

task_thread_info(tsk)->status |= TS_USEDFPU;
tsk->fpu_counter++;
}

void fpu_state_restore(struct pt_regs *regs)
{
struct task_struct *tsk = current;

if (unlikely(!user_mode(regs))) {
printk(KERN_ERR "BUG: FPU is used in kernel mode.\n");
BUG();
return;
}

if (!tsk_used_math(tsk)) {
/*
* does a slab alloc which can sleep
*/
if (init_fpu(tsk)) {
/*
* ran out of memory!
*/
do_group_exit(SIGKILL);
return;
}
}

grab_fpu(regs);

__fpu_state_restore();
}

BUILD_TRAP_HANDLER(fpu_state_restore)
{
TRAP_HANDLER_DECL;

fpu_state_restore(regs);
}
#endif /* CONFIG_SH_FPU */
80 changes: 48 additions & 32 deletions trunk/arch/sh/kernel/cpu/init.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,18 +28,30 @@
#include <asm/ubc.h>
#endif

#ifdef CONFIG_SH_FPU
#define cpu_has_fpu 1
#else
#define cpu_has_fpu 0
#endif

#ifdef CONFIG_SH_DSP
#define cpu_has_dsp 1
#else
#define cpu_has_dsp 0
#endif

/*
* Generic wrapper for command line arguments to disable on-chip
* peripherals (nofpu, nodsp, and so forth).
*/
#define onchip_setup(x) \
static int x##_disabled __initdata = 0; \
\
static int __init x##_setup(char *opts) \
{ \
x##_disabled = 1; \
return 1; \
} \
#define onchip_setup(x) \
static int x##_disabled __initdata = !cpu_has_##x; \
\
static int __init x##_setup(char *opts) \
{ \
x##_disabled = 1; \
return 1; \
} \
__setup("no" __stringify(x), x##_setup);

onchip_setup(fpu);
Expand Down Expand Up @@ -207,6 +219,18 @@ static void detect_cache_shape(void)
l2_cache_shape = -1; /* No S-cache */
}

static void __init fpu_init(void)
{
/* Disable the FPU */
if (fpu_disabled && (current_cpu_data.flags & CPU_HAS_FPU)) {
printk("FPU Disabled\n");
current_cpu_data.flags &= ~CPU_HAS_FPU;
}

disable_fpu();
clear_used_math();
}

#ifdef CONFIG_SH_DSP
static void __init release_dsp(void)
{
Expand Down Expand Up @@ -244,9 +268,17 @@ static void __init dsp_init(void)
if (sr & SR_DSP)
current_cpu_data.flags |= CPU_HAS_DSP;

/* Disable the DSP */
if (dsp_disabled && (current_cpu_data.flags & CPU_HAS_DSP)) {
printk("DSP Disabled\n");
current_cpu_data.flags &= ~CPU_HAS_DSP;
}

/* Now that we've determined the DSP status, clear the DSP bit. */
release_dsp();
}
#else
static inline void __init dsp_init(void) { }
#endif /* CONFIG_SH_DSP */

/**
Expand Down Expand Up @@ -302,37 +334,21 @@ asmlinkage void __init sh_cpu_init(void)
detect_cache_shape();
}

/* Disable the FPU */
if (fpu_disabled) {
printk("FPU Disabled\n");
current_cpu_data.flags &= ~CPU_HAS_FPU;
}

/* FPU initialization */
disable_fpu();
if ((current_cpu_data.flags & CPU_HAS_FPU)) {
current_thread_info()->status &= ~TS_USEDFPU;
clear_used_math();
}
fpu_init();
dsp_init();

/*
* Initialize the per-CPU ASID cache very early, since the
* TLB flushing routines depend on this being setup.
*/
current_cpu_data.asid_cache = NO_CONTEXT;

#ifdef CONFIG_SH_DSP
/* Probe for DSP */
dsp_init();

/* Disable the DSP */
if (dsp_disabled) {
printk("DSP Disabled\n");
current_cpu_data.flags &= ~CPU_HAS_DSP;
release_dsp();
}
#endif

speculative_execution_init();
expmask_init();

/*
* Boot processor to setup the FP and extended state context info.
*/
if (raw_smp_processor_id() == 0)
init_thread_xstate();
}
Loading

0 comments on commit e5eab2d

Please sign in to comment.