Loading arch/sh/Kconfig +1 −1 Original line number Diff line number Diff line Loading @@ -23,7 +23,7 @@ config SUPERH32 def_bool !SUPERH64 select HAVE_KPROBES select HAVE_KRETPROBES select HAVE_ARCH_TRACEHOOK if !SH_FPU select HAVE_ARCH_TRACEHOOK select HAVE_FTRACE config SUPERH64 Loading arch/sh/include/asm/elf.h +3 −3 Original line number Diff line number Diff line Loading @@ -108,10 +108,10 @@ typedef struct user_fpu_struct elf_fpregset_t; #define elf_check_fdpic(x) ((x)->e_flags & EF_SH_FDPIC) #define elf_check_const_displacement(x) ((x)->e_flags & EF_SH_PIC) #if defined(CONFIG_SUPERH32) && !defined(CONFIG_SH_FPU) #ifdef CONFIG_SUPERH32 /* * Enable dump using regset for general purpose registers, use this as * the default once the FPU registers are moved over also. * Enable dump using regset. * This covers all of general/DSP/FPU regs. */ #define CORE_DUMP_USE_REGSET #endif Loading arch/sh/include/asm/fpu.h +19 −0 Original line number Diff line number Diff line Loading @@ -30,8 +30,15 @@ static inline void save_fpu(struct task_struct *tsk, struct pt_regs *regs) } #endif struct user_regset; extern int do_fpu_inst(unsigned short, struct pt_regs *); extern int fpregs_get(struct task_struct *target, const struct user_regset *regset, unsigned int pos, unsigned int count, void *kbuf, void __user *ubuf); static inline void unlazy_fpu(struct task_struct *tsk, struct pt_regs *regs) { preempt_disable(); Loading @@ -50,6 +57,18 @@ 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 */ arch/sh/kernel/process_32.c +9 −5 Original line number Diff line number Diff line Loading @@ -7,7 +7,11 @@ * * SuperH version: Copyright (C) 1999, 2000 Niibe Yutaka & Kaz Kojima * Copyright (C) 2006 Lineo Solutions Inc. support SH4A UBC * Copyright (C) 2002 - 2007 Paul Mundt * Copyright (C) 2002 - 2008 Paul Mundt * * 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. */ #include <linux/module.h> #include <linux/mm.h> Loading Loading @@ -222,10 +226,10 @@ int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpu) struct task_struct *tsk = current; fpvalid = !!tsk_used_math(tsk); if (fpvalid) { unlazy_fpu(tsk, regs); memcpy(fpu, &tsk->thread.fpu.hard, sizeof(*fpu)); } if (fpvalid) fpvalid = !fpregs_get(tsk, NULL, 0, sizeof(struct user_fpu_struct), fpu, NULL); #endif return fpvalid; Loading arch/sh/kernel/ptrace_32.c +76 −0 Original line number Diff line number Diff line Loading @@ -32,6 +32,7 @@ #include <asm/processor.h> #include <asm/mmu_context.h> #include <asm/syscalls.h> #include <asm/fpu.h> /* * This routine will get a word off of the process kernel stack. Loading Loading @@ -145,6 +146,54 @@ static int genregs_set(struct task_struct *target, return ret; } #ifdef CONFIG_SH_FPU int fpregs_get(struct task_struct *target, const struct user_regset *regset, unsigned int pos, unsigned int count, void *kbuf, void __user *ubuf) { int ret; ret = init_fpu(target); if (ret) return ret; if ((boot_cpu_data.flags & CPU_HAS_FPU)) return user_regset_copyout(&pos, &count, &kbuf, &ubuf, &target->thread.fpu.hard, 0, -1); return user_regset_copyout(&pos, &count, &kbuf, &ubuf, &target->thread.fpu.soft, 0, -1); } static int fpregs_set(struct task_struct *target, const struct user_regset *regset, unsigned int pos, unsigned int count, const void *kbuf, const void __user *ubuf) { int ret; ret = init_fpu(target); if (ret) return ret; set_stopped_child_used_math(target); if ((boot_cpu_data.flags & CPU_HAS_FPU)) return user_regset_copyin(&pos, &count, &kbuf, &ubuf, &target->thread.fpu.hard, 0, -1); return user_regset_copyin(&pos, &count, &kbuf, &ubuf, &target->thread.fpu.soft, 0, -1); } static int fpregs_active(struct task_struct *target, const struct user_regset *regset) { return tsk_used_math(target) ? regset->n : 0; } #endif #ifdef CONFIG_SH_DSP static int dspregs_get(struct task_struct *target, const struct user_regset *regset, Loading Loading @@ -194,6 +243,9 @@ static int dspregs_active(struct task_struct *target, */ enum sh_regset { REGSET_GENERAL, #ifdef CONFIG_SH_FPU REGSET_FPU, #endif #ifdef CONFIG_SH_DSP REGSET_DSP, #endif Loading @@ -214,6 +266,18 @@ static const struct user_regset sh_regsets[] = { .set = genregs_set, }, #ifdef CONFIG_SH_FPU [REGSET_FPU] = { .core_note_type = NT_PRFPREG, .n = sizeof(struct user_fpu_struct) / sizeof(long), .size = sizeof(long), .align = sizeof(long), .get = fpregs_get, .set = fpregs_set, .active = fpregs_active, }, #endif #ifdef CONFIG_SH_DSP [REGSET_DSP] = { .n = sizeof(struct pt_dspregs) / sizeof(long), Loading Loading @@ -304,6 +368,18 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) REGSET_GENERAL, 0, sizeof(struct pt_regs), (const void __user *)data); #ifdef CONFIG_SH_FPU case PTRACE_GETFPREGS: return copy_regset_to_user(child, &user_sh_native_view, REGSET_FPU, 0, sizeof(struct user_fpu_struct), (void __user *)data); case PTRACE_SETFPREGS: return copy_regset_from_user(child, &user_sh_native_view, REGSET_FPU, 0, sizeof(struct user_fpu_struct), (const void __user *)data); #endif #ifdef CONFIG_SH_DSP case PTRACE_GETDSPREGS: return copy_regset_to_user(child, &user_sh_native_view, Loading Loading
arch/sh/Kconfig +1 −1 Original line number Diff line number Diff line Loading @@ -23,7 +23,7 @@ config SUPERH32 def_bool !SUPERH64 select HAVE_KPROBES select HAVE_KRETPROBES select HAVE_ARCH_TRACEHOOK if !SH_FPU select HAVE_ARCH_TRACEHOOK select HAVE_FTRACE config SUPERH64 Loading
arch/sh/include/asm/elf.h +3 −3 Original line number Diff line number Diff line Loading @@ -108,10 +108,10 @@ typedef struct user_fpu_struct elf_fpregset_t; #define elf_check_fdpic(x) ((x)->e_flags & EF_SH_FDPIC) #define elf_check_const_displacement(x) ((x)->e_flags & EF_SH_PIC) #if defined(CONFIG_SUPERH32) && !defined(CONFIG_SH_FPU) #ifdef CONFIG_SUPERH32 /* * Enable dump using regset for general purpose registers, use this as * the default once the FPU registers are moved over also. * Enable dump using regset. * This covers all of general/DSP/FPU regs. */ #define CORE_DUMP_USE_REGSET #endif Loading
arch/sh/include/asm/fpu.h +19 −0 Original line number Diff line number Diff line Loading @@ -30,8 +30,15 @@ static inline void save_fpu(struct task_struct *tsk, struct pt_regs *regs) } #endif struct user_regset; extern int do_fpu_inst(unsigned short, struct pt_regs *); extern int fpregs_get(struct task_struct *target, const struct user_regset *regset, unsigned int pos, unsigned int count, void *kbuf, void __user *ubuf); static inline void unlazy_fpu(struct task_struct *tsk, struct pt_regs *regs) { preempt_disable(); Loading @@ -50,6 +57,18 @@ 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 */
arch/sh/kernel/process_32.c +9 −5 Original line number Diff line number Diff line Loading @@ -7,7 +7,11 @@ * * SuperH version: Copyright (C) 1999, 2000 Niibe Yutaka & Kaz Kojima * Copyright (C) 2006 Lineo Solutions Inc. support SH4A UBC * Copyright (C) 2002 - 2007 Paul Mundt * Copyright (C) 2002 - 2008 Paul Mundt * * 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. */ #include <linux/module.h> #include <linux/mm.h> Loading Loading @@ -222,10 +226,10 @@ int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpu) struct task_struct *tsk = current; fpvalid = !!tsk_used_math(tsk); if (fpvalid) { unlazy_fpu(tsk, regs); memcpy(fpu, &tsk->thread.fpu.hard, sizeof(*fpu)); } if (fpvalid) fpvalid = !fpregs_get(tsk, NULL, 0, sizeof(struct user_fpu_struct), fpu, NULL); #endif return fpvalid; Loading
arch/sh/kernel/ptrace_32.c +76 −0 Original line number Diff line number Diff line Loading @@ -32,6 +32,7 @@ #include <asm/processor.h> #include <asm/mmu_context.h> #include <asm/syscalls.h> #include <asm/fpu.h> /* * This routine will get a word off of the process kernel stack. Loading Loading @@ -145,6 +146,54 @@ static int genregs_set(struct task_struct *target, return ret; } #ifdef CONFIG_SH_FPU int fpregs_get(struct task_struct *target, const struct user_regset *regset, unsigned int pos, unsigned int count, void *kbuf, void __user *ubuf) { int ret; ret = init_fpu(target); if (ret) return ret; if ((boot_cpu_data.flags & CPU_HAS_FPU)) return user_regset_copyout(&pos, &count, &kbuf, &ubuf, &target->thread.fpu.hard, 0, -1); return user_regset_copyout(&pos, &count, &kbuf, &ubuf, &target->thread.fpu.soft, 0, -1); } static int fpregs_set(struct task_struct *target, const struct user_regset *regset, unsigned int pos, unsigned int count, const void *kbuf, const void __user *ubuf) { int ret; ret = init_fpu(target); if (ret) return ret; set_stopped_child_used_math(target); if ((boot_cpu_data.flags & CPU_HAS_FPU)) return user_regset_copyin(&pos, &count, &kbuf, &ubuf, &target->thread.fpu.hard, 0, -1); return user_regset_copyin(&pos, &count, &kbuf, &ubuf, &target->thread.fpu.soft, 0, -1); } static int fpregs_active(struct task_struct *target, const struct user_regset *regset) { return tsk_used_math(target) ? regset->n : 0; } #endif #ifdef CONFIG_SH_DSP static int dspregs_get(struct task_struct *target, const struct user_regset *regset, Loading Loading @@ -194,6 +243,9 @@ static int dspregs_active(struct task_struct *target, */ enum sh_regset { REGSET_GENERAL, #ifdef CONFIG_SH_FPU REGSET_FPU, #endif #ifdef CONFIG_SH_DSP REGSET_DSP, #endif Loading @@ -214,6 +266,18 @@ static const struct user_regset sh_regsets[] = { .set = genregs_set, }, #ifdef CONFIG_SH_FPU [REGSET_FPU] = { .core_note_type = NT_PRFPREG, .n = sizeof(struct user_fpu_struct) / sizeof(long), .size = sizeof(long), .align = sizeof(long), .get = fpregs_get, .set = fpregs_set, .active = fpregs_active, }, #endif #ifdef CONFIG_SH_DSP [REGSET_DSP] = { .n = sizeof(struct pt_dspregs) / sizeof(long), Loading Loading @@ -304,6 +368,18 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) REGSET_GENERAL, 0, sizeof(struct pt_regs), (const void __user *)data); #ifdef CONFIG_SH_FPU case PTRACE_GETFPREGS: return copy_regset_to_user(child, &user_sh_native_view, REGSET_FPU, 0, sizeof(struct user_fpu_struct), (void __user *)data); case PTRACE_SETFPREGS: return copy_regset_from_user(child, &user_sh_native_view, REGSET_FPU, 0, sizeof(struct user_fpu_struct), (const void __user *)data); #endif #ifdef CONFIG_SH_DSP case PTRACE_GETDSPREGS: return copy_regset_to_user(child, &user_sh_native_view, Loading