diff options
Diffstat (limited to 'arch/openrisc')
-rw-r--r-- | arch/openrisc/Kconfig | 9 | ||||
-rw-r--r-- | arch/openrisc/include/asm/fpu.h | 22 | ||||
-rw-r--r-- | arch/openrisc/include/asm/processor.h | 1 | ||||
-rw-r--r-- | arch/openrisc/include/asm/ptrace.h | 3 | ||||
-rw-r--r-- | arch/openrisc/include/uapi/asm/elf.h | 75 | ||||
-rw-r--r-- | arch/openrisc/kernel/entry.S | 15 | ||||
-rw-r--r-- | arch/openrisc/kernel/module.c | 18 | ||||
-rw-r--r-- | arch/openrisc/kernel/process.c | 5 | ||||
-rw-r--r-- | arch/openrisc/kernel/ptrace.c | 18 | ||||
-rw-r--r-- | arch/openrisc/kernel/signal.c | 36 | ||||
-rw-r--r-- | arch/openrisc/kernel/traps.c | 102 |
11 files changed, 214 insertions, 90 deletions
diff --git a/arch/openrisc/Kconfig b/arch/openrisc/Kconfig index 3586cda55b..69c0258700 100644 --- a/arch/openrisc/Kconfig +++ b/arch/openrisc/Kconfig @@ -188,6 +188,15 @@ config SMP If you don't know what to do here, say N. +config FPU + bool "FPU support" + default y + help + Say N here if you want to disable all floating-point related procedures + in the kernel and reduce binary size. + + If you don't know what to do here, say Y. + source "kernel/Kconfig.hz" config OPENRISC_NO_SPR_SR_DSX diff --git a/arch/openrisc/include/asm/fpu.h b/arch/openrisc/include/asm/fpu.h new file mode 100644 index 0000000000..57bc44d80d --- /dev/null +++ b/arch/openrisc/include/asm/fpu.h @@ -0,0 +1,22 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef __ASM_OPENRISC_FPU_H +#define __ASM_OPENRISC_FPU_H + +struct task_struct; + +#ifdef CONFIG_FPU +static inline void save_fpu(struct task_struct *task) +{ + task->thread.fpcsr = mfspr(SPR_FPCSR); +} + +static inline void restore_fpu(struct task_struct *task) +{ + mtspr(SPR_FPCSR, task->thread.fpcsr); +} +#else +#define save_fpu(tsk) do { } while (0) +#define restore_fpu(tsk) do { } while (0) +#endif + +#endif /* __ASM_OPENRISC_FPU_H */ diff --git a/arch/openrisc/include/asm/processor.h b/arch/openrisc/include/asm/processor.h index 3b736e74e6..e05d1b59e2 100644 --- a/arch/openrisc/include/asm/processor.h +++ b/arch/openrisc/include/asm/processor.h @@ -44,6 +44,7 @@ struct task_struct; struct thread_struct { + long fpcsr; /* Floating point control status register. */ }; /* diff --git a/arch/openrisc/include/asm/ptrace.h b/arch/openrisc/include/asm/ptrace.h index 375147ff71..1da3e66292 100644 --- a/arch/openrisc/include/asm/ptrace.h +++ b/arch/openrisc/include/asm/ptrace.h @@ -59,7 +59,7 @@ struct pt_regs { * -1 for all other exceptions. */ long orig_gpr11; /* For restarting system calls */ - long fpcsr; /* Floating point control status register. */ + long dummy; /* Cheap alignment fix */ long dummy2; /* Cheap alignment fix */ }; @@ -115,6 +115,5 @@ static inline long regs_return_value(struct pt_regs *regs) #define PT_GPR31 124 #define PT_PC 128 #define PT_ORIG_GPR11 132 -#define PT_FPCSR 136 #endif /* __ASM_OPENRISC_PTRACE_H */ diff --git a/arch/openrisc/include/uapi/asm/elf.h b/arch/openrisc/include/uapi/asm/elf.h index 6868f81c28..441e343f82 100644 --- a/arch/openrisc/include/uapi/asm/elf.h +++ b/arch/openrisc/include/uapi/asm/elf.h @@ -34,15 +34,72 @@ #include <asm/ptrace.h> /* The OR1K relocation types... not all relevant for module loader */ -#define R_OR32_NONE 0 -#define R_OR32_32 1 -#define R_OR32_16 2 -#define R_OR32_8 3 -#define R_OR32_CONST 4 -#define R_OR32_CONSTH 5 -#define R_OR32_JUMPTARG 6 -#define R_OR32_VTINHERIT 7 -#define R_OR32_VTENTRY 8 +#define R_OR1K_NONE 0 +#define R_OR1K_32 1 +#define R_OR1K_16 2 +#define R_OR1K_8 3 +#define R_OR1K_LO_16_IN_INSN 4 +#define R_OR1K_HI_16_IN_INSN 5 +#define R_OR1K_INSN_REL_26 6 +#define R_OR1K_GNU_VTENTRY 7 +#define R_OR1K_GNU_VTINHERIT 8 +#define R_OR1K_32_PCREL 9 +#define R_OR1K_16_PCREL 10 +#define R_OR1K_8_PCREL 11 +#define R_OR1K_GOTPC_HI16 12 +#define R_OR1K_GOTPC_LO16 13 +#define R_OR1K_GOT16 14 +#define R_OR1K_PLT26 15 +#define R_OR1K_GOTOFF_HI16 16 +#define R_OR1K_GOTOFF_LO16 17 +#define R_OR1K_COPY 18 +#define R_OR1K_GLOB_DAT 19 +#define R_OR1K_JMP_SLOT 20 +#define R_OR1K_RELATIVE 21 +#define R_OR1K_TLS_GD_HI16 22 +#define R_OR1K_TLS_GD_LO16 23 +#define R_OR1K_TLS_LDM_HI16 24 +#define R_OR1K_TLS_LDM_LO16 25 +#define R_OR1K_TLS_LDO_HI16 26 +#define R_OR1K_TLS_LDO_LO16 27 +#define R_OR1K_TLS_IE_HI16 28 +#define R_OR1K_TLS_IE_LO16 29 +#define R_OR1K_TLS_LE_HI16 30 +#define R_OR1K_TLS_LE_LO16 31 +#define R_OR1K_TLS_TPOFF 32 +#define R_OR1K_TLS_DTPOFF 33 +#define R_OR1K_TLS_DTPMOD 34 +#define R_OR1K_AHI16 35 +#define R_OR1K_GOTOFF_AHI16 36 +#define R_OR1K_TLS_IE_AHI16 37 +#define R_OR1K_TLS_LE_AHI16 38 +#define R_OR1K_SLO16 39 +#define R_OR1K_GOTOFF_SLO16 40 +#define R_OR1K_TLS_LE_SLO16 41 +#define R_OR1K_PCREL_PG21 42 +#define R_OR1K_GOT_PG21 43 +#define R_OR1K_TLS_GD_PG21 44 +#define R_OR1K_TLS_LDM_PG21 45 +#define R_OR1K_TLS_IE_PG21 46 +#define R_OR1K_LO13 47 +#define R_OR1K_GOT_LO13 48 +#define R_OR1K_TLS_GD_LO13 49 +#define R_OR1K_TLS_LDM_LO13 50 +#define R_OR1K_TLS_IE_LO13 51 +#define R_OR1K_SLO13 52 +#define R_OR1K_PLTA26 53 +#define R_OR1K_GOT_AHI16 54 + +/* Old relocation names */ +#define R_OR32_NONE R_OR1K_NONE +#define R_OR32_32 R_OR1K_32 +#define R_OR32_16 R_OR1K_16 +#define R_OR32_8 R_OR1K_8 +#define R_OR32_CONST R_OR1K_LO_16_IN_INSN +#define R_OR32_CONSTH R_OR1K_HI_16_IN_INSN +#define R_OR32_JUMPTARG R_OR1K_INSN_REL_26 +#define R_OR32_VTENTRY R_OR1K_GNU_VTENTRY +#define R_OR32_VTINHERIT R_OR1K_GNU_VTINHERIT typedef unsigned long elf_greg_t; diff --git a/arch/openrisc/kernel/entry.S b/arch/openrisc/kernel/entry.S index c9f48e750b..440711d7bf 100644 --- a/arch/openrisc/kernel/entry.S +++ b/arch/openrisc/kernel/entry.S @@ -106,8 +106,6 @@ l.mtspr r0,r3,SPR_EPCR_BASE ;\ l.lwz r3,PT_SR(r1) ;\ l.mtspr r0,r3,SPR_ESR_BASE ;\ - l.lwz r3,PT_FPCSR(r1) ;\ - l.mtspr r0,r3,SPR_FPCSR ;\ l.lwz r2,PT_GPR2(r1) ;\ l.lwz r3,PT_GPR3(r1) ;\ l.lwz r4,PT_GPR4(r1) ;\ @@ -177,8 +175,6 @@ handler: ;\ /* r30 already save */ ;\ l.sw PT_GPR31(r1),r31 ;\ TRACE_IRQS_OFF_ENTRY ;\ - l.mfspr r30,r0,SPR_FPCSR ;\ - l.sw PT_FPCSR(r1),r30 ;\ /* Store -1 in orig_gpr11 for non-syscall exceptions */ ;\ l.addi r30,r0,-1 ;\ l.sw PT_ORIG_GPR11(r1),r30 @@ -219,8 +215,6 @@ handler: ;\ /* Store -1 in orig_gpr11 for non-syscall exceptions */ ;\ l.addi r30,r0,-1 ;\ l.sw PT_ORIG_GPR11(r1),r30 ;\ - l.mfspr r30,r0,SPR_FPCSR ;\ - l.sw PT_FPCSR(r1),r30 ;\ l.addi r3,r1,0 ;\ /* r4 is exception EA */ ;\ l.addi r5,r0,vector ;\ @@ -852,6 +846,7 @@ _syscall_badsys: EXCEPTION_ENTRY(_fpe_trap_handler) CLEAR_LWA_FLAG(r3) + /* r4: EA of fault (set by EXCEPTION_HANDLE) */ l.jal do_fpe_trap l.addi r3,r1,0 /* pt_regs */ @@ -1100,10 +1095,6 @@ ENTRY(_switch) l.sw PT_GPR28(r1),r28 l.sw PT_GPR30(r1),r30 - /* Store the old FPU state to new pt_regs */ - l.mfspr r29,r0,SPR_FPCSR - l.sw PT_FPCSR(r1),r29 - l.addi r11,r10,0 /* Save old 'current' to 'last' return value*/ /* We use thread_info->ksp for storing the address of the above @@ -1126,10 +1117,6 @@ ENTRY(_switch) l.lwz r29,PT_SP(r1) l.sw TI_KSP(r10),r29 - /* Restore the old value of FPCSR */ - l.lwz r29,PT_FPCSR(r1) - l.mtspr r0,r29,SPR_FPCSR - /* ...and restore the registers, except r11 because the return value * has already been set above. */ diff --git a/arch/openrisc/kernel/module.c b/arch/openrisc/kernel/module.c index 532013f523..c9ff4c4a0b 100644 --- a/arch/openrisc/kernel/module.c +++ b/arch/openrisc/kernel/module.c @@ -39,22 +39,32 @@ int apply_relocate_add(Elf32_Shdr *sechdrs, value = sym->st_value + rel[i].r_addend; switch (ELF32_R_TYPE(rel[i].r_info)) { - case R_OR32_32: + case R_OR1K_32: *location = value; break; - case R_OR32_CONST: + case R_OR1K_LO_16_IN_INSN: *((uint16_t *)location + 1) = value; break; - case R_OR32_CONSTH: + case R_OR1K_HI_16_IN_INSN: *((uint16_t *)location + 1) = value >> 16; break; - case R_OR32_JUMPTARG: + case R_OR1K_INSN_REL_26: value -= (uint32_t)location; value >>= 2; value &= 0x03ffffff; value |= *location & 0xfc000000; *location = value; break; + case R_OR1K_AHI16: + /* Adjust the operand to match with a signed LO16. */ + value += 0x8000; + *((uint16_t *)location + 1) = value >> 16; + break; + case R_OR1K_SLO16: + /* Split value lower 16-bits. */ + value = ((value & 0xf800) << 10) | (value & 0x7ff); + *location = (*location & ~0x3e007ff) | value; + break; default: pr_err("module %s: Unknown relocation: %u\n", me->name, ELF32_R_TYPE(rel[i].r_info)); diff --git a/arch/openrisc/kernel/process.c b/arch/openrisc/kernel/process.c index 3c27d1c727..eef99fee21 100644 --- a/arch/openrisc/kernel/process.c +++ b/arch/openrisc/kernel/process.c @@ -36,6 +36,7 @@ #include <linux/reboot.h> #include <linux/uaccess.h> +#include <asm/fpu.h> #include <asm/io.h> #include <asm/processor.h> #include <asm/spr_defs.h> @@ -244,6 +245,8 @@ struct task_struct *__switch_to(struct task_struct *old, local_irq_save(flags); + save_fpu(current); + /* current_set is an array of saved current pointers * (one for each cpu). we need them at user->kernel transition, * while we save them at kernel->user transition @@ -256,6 +259,8 @@ struct task_struct *__switch_to(struct task_struct *old, current_thread_info_set[smp_processor_id()] = new_ti; last = (_switch(old_ti, new_ti))->task; + restore_fpu(current); + local_irq_restore(flags); return last; diff --git a/arch/openrisc/kernel/ptrace.c b/arch/openrisc/kernel/ptrace.c index 1eeac3b62e..5091b18eab 100644 --- a/arch/openrisc/kernel/ptrace.c +++ b/arch/openrisc/kernel/ptrace.c @@ -88,6 +88,7 @@ static int genregs_set(struct task_struct *target, return ret; } +#ifdef CONFIG_FPU /* * As OpenRISC shares GPRs and floating point registers we don't need to export * the floating point registers again. So here we only export the fpcsr special @@ -97,9 +98,7 @@ static int fpregs_get(struct task_struct *target, const struct user_regset *regset, struct membuf to) { - const struct pt_regs *regs = task_pt_regs(target); - - return membuf_store(&to, regs->fpcsr); + return membuf_store(&to, target->thread.fpcsr); } static int fpregs_set(struct task_struct *target, @@ -107,21 +106,20 @@ static int fpregs_set(struct task_struct *target, unsigned int pos, unsigned int count, const void *kbuf, const void __user *ubuf) { - struct pt_regs *regs = task_pt_regs(target); - int ret; - /* FPCSR */ - ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, - ®s->fpcsr, 0, 4); - return ret; + return user_regset_copyin(&pos, &count, &kbuf, &ubuf, + &target->thread.fpcsr, 0, 4); } +#endif /* * Define the register sets available on OpenRISC under Linux */ enum or1k_regset { REGSET_GENERAL, +#ifdef CONFIG_FPU REGSET_FPU, +#endif }; static const struct user_regset or1k_regsets[] = { @@ -133,6 +131,7 @@ static const struct user_regset or1k_regsets[] = { .regset_get = genregs_get, .set = genregs_set, }, +#ifdef CONFIG_FPU [REGSET_FPU] = { .core_note_type = NT_PRFPREG, .n = sizeof(struct __or1k_fpu_state) / sizeof(long), @@ -141,6 +140,7 @@ static const struct user_regset or1k_regsets[] = { .regset_get = fpregs_get, .set = fpregs_set, }, +#endif }; static const struct user_regset_view user_or1k_native_view = { diff --git a/arch/openrisc/kernel/signal.c b/arch/openrisc/kernel/signal.c index e2f21a5d8a..c7ab42e2cb 100644 --- a/arch/openrisc/kernel/signal.c +++ b/arch/openrisc/kernel/signal.c @@ -23,6 +23,7 @@ #include <linux/stddef.h> #include <linux/resume_user_mode.h> +#include <asm/fpu.h> #include <asm/processor.h> #include <asm/syscall.h> #include <asm/ucontext.h> @@ -39,6 +40,37 @@ asmlinkage long _sys_rt_sigreturn(struct pt_regs *regs); asmlinkage int do_work_pending(struct pt_regs *regs, unsigned int thread_flags, int syscall); +#ifdef CONFIG_FPU +static long restore_fp_state(struct sigcontext __user *sc) +{ + long err; + + err = __copy_from_user(¤t->thread.fpcsr, &sc->fpcsr, sizeof(unsigned long)); + if (unlikely(err)) + return err; + + /* Restore the FPU state */ + restore_fpu(current); + + return 0; +} + +static long save_fp_state(struct sigcontext __user *sc) +{ + long err; + + /* Sync the user FPU state so we can copy to sigcontext */ + save_fpu(current); + + err = __copy_to_user(&sc->fpcsr, ¤t->thread.fpcsr, sizeof(unsigned long)); + + return err; +} +#else +#define save_fp_state(sc) (0) +#define restore_fp_state(sc) (0) +#endif + static int restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc) { @@ -55,7 +87,7 @@ static int restore_sigcontext(struct pt_regs *regs, err |= __copy_from_user(regs, sc->regs.gpr, 32 * sizeof(unsigned long)); err |= __copy_from_user(®s->pc, &sc->regs.pc, sizeof(unsigned long)); err |= __copy_from_user(®s->sr, &sc->regs.sr, sizeof(unsigned long)); - err |= __copy_from_user(®s->fpcsr, &sc->fpcsr, sizeof(unsigned long)); + err |= restore_fp_state(sc); /* make sure the SM-bit is cleared so user-mode cannot fool us */ regs->sr &= ~SPR_SR_SM; @@ -118,7 +150,7 @@ static int setup_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc) err |= __copy_to_user(sc->regs.gpr, regs, 32 * sizeof(unsigned long)); err |= __copy_to_user(&sc->regs.pc, ®s->pc, sizeof(unsigned long)); err |= __copy_to_user(&sc->regs.sr, ®s->sr, sizeof(unsigned long)); - err |= __copy_to_user(&sc->fpcsr, ®s->fpcsr, sizeof(unsigned long)); + err |= save_fp_state(sc); return err; } diff --git a/arch/openrisc/kernel/traps.c b/arch/openrisc/kernel/traps.c index 90554a5558..c195be9cc9 100644 --- a/arch/openrisc/kernel/traps.c +++ b/arch/openrisc/kernel/traps.c @@ -31,6 +31,7 @@ #include <linux/uaccess.h> #include <asm/bug.h> +#include <asm/fpu.h> #include <asm/io.h> #include <asm/processor.h> #include <asm/unwinder.h> @@ -51,16 +52,16 @@ static void print_trace(void *data, unsigned long addr, int reliable) { const char *loglvl = data; - printk("%s[<%p>] %s%pS\n", loglvl, (void *) addr, reliable ? "" : "? ", - (void *) addr); + pr_info("%s[<%p>] %s%pS\n", loglvl, (void *) addr, reliable ? "" : "? ", + (void *) addr); } static void print_data(unsigned long base_addr, unsigned long word, int i) { if (i == 0) - printk("(%08lx:)\t%08lx", base_addr + (i * 4), word); + pr_info("(%08lx:)\t%08lx", base_addr + (i * 4), word); else - printk(" %08lx:\t%08lx", base_addr + (i * 4), word); + pr_info(" %08lx:\t%08lx", base_addr + (i * 4), word); } /* displays a short stack trace */ @@ -69,7 +70,7 @@ void show_stack(struct task_struct *task, unsigned long *esp, const char *loglvl if (esp == NULL) esp = (unsigned long *)&esp; - printk("%sCall trace:\n", loglvl); + pr_info("%sCall trace:\n", loglvl); unwind_stack((void *)loglvl, esp, print_trace); } @@ -83,57 +84,56 @@ void show_registers(struct pt_regs *regs) if (user_mode(regs)) in_kernel = 0; - printk("CPU #: %d\n" - " PC: %08lx SR: %08lx SP: %08lx FPCSR: %08lx\n", - smp_processor_id(), regs->pc, regs->sr, regs->sp, - regs->fpcsr); - printk("GPR00: %08lx GPR01: %08lx GPR02: %08lx GPR03: %08lx\n", - 0L, regs->gpr[1], regs->gpr[2], regs->gpr[3]); - printk("GPR04: %08lx GPR05: %08lx GPR06: %08lx GPR07: %08lx\n", - regs->gpr[4], regs->gpr[5], regs->gpr[6], regs->gpr[7]); - printk("GPR08: %08lx GPR09: %08lx GPR10: %08lx GPR11: %08lx\n", - regs->gpr[8], regs->gpr[9], regs->gpr[10], regs->gpr[11]); - printk("GPR12: %08lx GPR13: %08lx GPR14: %08lx GPR15: %08lx\n", - regs->gpr[12], regs->gpr[13], regs->gpr[14], regs->gpr[15]); - printk("GPR16: %08lx GPR17: %08lx GPR18: %08lx GPR19: %08lx\n", - regs->gpr[16], regs->gpr[17], regs->gpr[18], regs->gpr[19]); - printk("GPR20: %08lx GPR21: %08lx GPR22: %08lx GPR23: %08lx\n", - regs->gpr[20], regs->gpr[21], regs->gpr[22], regs->gpr[23]); - printk("GPR24: %08lx GPR25: %08lx GPR26: %08lx GPR27: %08lx\n", - regs->gpr[24], regs->gpr[25], regs->gpr[26], regs->gpr[27]); - printk("GPR28: %08lx GPR29: %08lx GPR30: %08lx GPR31: %08lx\n", - regs->gpr[28], regs->gpr[29], regs->gpr[30], regs->gpr[31]); - printk(" RES: %08lx oGPR11: %08lx\n", - regs->gpr[11], regs->orig_gpr11); - - printk("Process %s (pid: %d, stackpage=%08lx)\n", - current->comm, current->pid, (unsigned long)current); + pr_info("CPU #: %d\n" + " PC: %08lx SR: %08lx SP: %08lx\n", + smp_processor_id(), regs->pc, regs->sr, regs->sp); + pr_info("GPR00: %08lx GPR01: %08lx GPR02: %08lx GPR03: %08lx\n", + 0L, regs->gpr[1], regs->gpr[2], regs->gpr[3]); + pr_info("GPR04: %08lx GPR05: %08lx GPR06: %08lx GPR07: %08lx\n", + regs->gpr[4], regs->gpr[5], regs->gpr[6], regs->gpr[7]); + pr_info("GPR08: %08lx GPR09: %08lx GPR10: %08lx GPR11: %08lx\n", + regs->gpr[8], regs->gpr[9], regs->gpr[10], regs->gpr[11]); + pr_info("GPR12: %08lx GPR13: %08lx GPR14: %08lx GPR15: %08lx\n", + regs->gpr[12], regs->gpr[13], regs->gpr[14], regs->gpr[15]); + pr_info("GPR16: %08lx GPR17: %08lx GPR18: %08lx GPR19: %08lx\n", + regs->gpr[16], regs->gpr[17], regs->gpr[18], regs->gpr[19]); + pr_info("GPR20: %08lx GPR21: %08lx GPR22: %08lx GPR23: %08lx\n", + regs->gpr[20], regs->gpr[21], regs->gpr[22], regs->gpr[23]); + pr_info("GPR24: %08lx GPR25: %08lx GPR26: %08lx GPR27: %08lx\n", + regs->gpr[24], regs->gpr[25], regs->gpr[26], regs->gpr[27]); + pr_info("GPR28: %08lx GPR29: %08lx GPR30: %08lx GPR31: %08lx\n", + regs->gpr[28], regs->gpr[29], regs->gpr[30], regs->gpr[31]); + pr_info(" RES: %08lx oGPR11: %08lx\n", + regs->gpr[11], regs->orig_gpr11); + + pr_info("Process %s (pid: %d, stackpage=%08lx)\n", + current->comm, current->pid, (unsigned long)current); /* * When in-kernel, we also print out the stack and code at the * time of the fault.. */ if (in_kernel) { - printk("\nStack: "); + pr_info("\nStack: "); show_stack(NULL, (unsigned long *)esp, KERN_EMERG); if (esp < PAGE_OFFSET) goto bad_stack; - printk("\n"); + pr_info("\n"); for (i = -8; i < 24; i += 1) { unsigned long word; if (__get_user(word, &((unsigned long *)esp)[i])) { bad_stack: - printk(" Bad Stack value."); + pr_info(" Bad Stack value."); break; } print_data(esp, word, i); } - printk("\nCode: "); + pr_info("\nCode: "); if (regs->pc < PAGE_OFFSET) goto bad; @@ -142,14 +142,14 @@ bad_stack: if (__get_user(word, &((unsigned long *)regs->pc)[i])) { bad: - printk(" Bad PC value."); + pr_info(" Bad PC value."); break; } print_data(regs->pc, word, i); } } - printk("\n"); + pr_info("\n"); } /* This is normally the 'Oops' routine */ @@ -157,10 +157,10 @@ void __noreturn die(const char *str, struct pt_regs *regs, long err) { console_verbose(); - printk("\n%s#: %04lx\n", str, err & 0xffff); + pr_emerg("\n%s#: %04lx\n", str, err & 0xffff); show_registers(regs); #ifdef CONFIG_JUMP_UPON_UNHANDLED_EXCEPTION - printk("\n\nUNHANDLED_EXCEPTION: entering infinite loop\n"); + pr_emerg("\n\nUNHANDLED_EXCEPTION: entering infinite loop\n"); /* shut down interrupts */ local_irq_disable(); @@ -173,8 +173,8 @@ void __noreturn die(const char *str, struct pt_regs *regs, long err) asmlinkage void unhandled_exception(struct pt_regs *regs, int ea, int vector) { - printk("Unable to handle exception at EA =0x%x, vector 0x%x", - ea, vector); + pr_emerg("Unable to handle exception at EA =0x%x, vector 0x%x", + ea, vector); die("Oops", regs, 9); } @@ -182,7 +182,11 @@ asmlinkage void do_fpe_trap(struct pt_regs *regs, unsigned long address) { if (user_mode(regs)) { int code = FPE_FLTUNK; - unsigned long fpcsr = regs->fpcsr; +#ifdef CONFIG_FPU + unsigned long fpcsr; + + save_fpu(current); + fpcsr = current->thread.fpcsr; if (fpcsr & SPR_FPCSR_IVF) code = FPE_FLTINV; @@ -196,8 +200,9 @@ asmlinkage void do_fpe_trap(struct pt_regs *regs, unsigned long address) code = FPE_FLTRES; /* Clear all flags */ - regs->fpcsr &= ~SPR_FPCSR_ALLF; - + current->thread.fpcsr &= ~SPR_FPCSR_ALLF; + restore_fpu(current); +#endif force_sig_fault(SIGFPE, code, (void __user *)regs->pc); } else { pr_emerg("KERNEL: Illegal fpe exception 0x%.8lx\n", regs->pc); @@ -221,8 +226,7 @@ asmlinkage void do_unaligned_access(struct pt_regs *regs, unsigned long address) /* Send a SIGBUS */ force_sig_fault(SIGBUS, BUS_ADRALN, (void __user *)address); } else { - printk("KERNEL: Unaligned Access 0x%.8lx\n", address); - show_registers(regs); + pr_emerg("KERNEL: Unaligned Access 0x%.8lx\n", address); die("Die:", regs, address); } @@ -234,8 +238,7 @@ asmlinkage void do_bus_fault(struct pt_regs *regs, unsigned long address) /* Send a SIGBUS */ force_sig_fault(SIGBUS, BUS_ADRERR, (void __user *)address); } else { /* Kernel mode */ - printk("KERNEL: Bus error (SIGBUS) 0x%.8lx\n", address); - show_registers(regs); + pr_emerg("KERNEL: Bus error (SIGBUS) 0x%.8lx\n", address); die("Die:", regs, address); } } @@ -429,9 +432,8 @@ asmlinkage void do_illegal_instruction(struct pt_regs *regs, /* Send a SIGILL */ force_sig_fault(SIGILL, ILL_ILLOPC, (void __user *)address); } else { /* Kernel mode */ - printk("KERNEL: Illegal instruction (SIGILL) 0x%.8lx\n", - address); - show_registers(regs); + pr_emerg("KERNEL: Illegal instruction (SIGILL) 0x%.8lx\n", + address); die("Die:", regs, address); } } |