Loading arch/arc/Kconfig +5 −10 Original line number Diff line number Diff line Loading @@ -351,9 +351,8 @@ config NODES_SHIFT Accessing memory beyond 1GB (with or w/o PAE) requires 2 memory zones. if ISA_ARCOMPACT config ARC_COMPACT_IRQ_LEVELS depends on ISA_ARCOMPACT bool "Setup Timer IRQ as high Priority" # if SMP, LV2 enabled ONLY if ARC implementation has LV2 re-entrancy depends on !SMP Loading @@ -361,14 +360,10 @@ config ARC_COMPACT_IRQ_LEVELS config ARC_FPU_SAVE_RESTORE bool "Enable FPU state persistence across context switch" help Double Precision Floating Point unit had dedicated regs which need to be saved/restored across context-switch. Note that ARC FPU is overly simplistic, unlike say x86, which has hardware pieces to allow software to conditionally save/restore, based on actual usage of FPU by a task. Thus our implemn does this for all tasks in system. endif #ISA_ARCOMPACT ARCompact FPU has internal registers to assist with Double precision Floating Point operations. There are control and stauts registers for floating point exceptions and rounding modes. These are preserved across task context switch when enabled. config ARC_CANT_LLSC def_bool n Loading arch/arc/include/asm/arcregs.h +2 −0 Original line number Diff line number Diff line Loading @@ -39,6 +39,8 @@ #define ARC_REG_CLUSTER_BCR 0xcf #define ARC_REG_AUX_ICCM 0x208 /* ICCM Base Addr (ARCv2) */ #define ARC_REG_LPB_CTRL 0x488 /* ARCv2 Loop Buffer control */ #define ARC_REG_FPU_CTRL 0x300 #define ARC_REG_FPU_STATUS 0x301 /* Common for ARCompact and ARCv2 status register */ #define ARC_REG_STATUS32 0x0A Loading arch/arc/include/asm/fpu.h +27 −1 Original line number Diff line number Diff line Loading @@ -11,6 +11,8 @@ #include <asm/ptrace.h> #ifdef CONFIG_ISA_ARCOMPACT /* These DPFP regs need to be saved/restored across ctx-sw */ struct arc_fpu { struct { Loading @@ -18,11 +20,35 @@ struct arc_fpu { } aux_dpfp[2]; }; extern void fpu_save_restore(struct task_struct *p, struct task_struct *n); #define fpu_init_task(regs) #else /* * ARCv2 FPU Control aux register * - bits to enable Traps on Exceptions * - Rounding mode * * ARCv2 FPU Status aux register * - FPU exceptions flags (Inv, Div-by-Zero, overflow, underflow, inexact) * - Flag Write Enable to clear flags explicitly (vs. by fpu instructions * only */ struct arc_fpu { unsigned int ctrl, status; }; extern void fpu_init_task(struct pt_regs *regs); #endif /* !CONFIG_ISA_ARCOMPACT */ extern void fpu_save_restore(struct task_struct *p, struct task_struct *n); #else /* !CONFIG_ARC_FPU_SAVE_RESTORE */ #define fpu_save_restore(p, n) #define fpu_init_task(regs) #endif /* CONFIG_ARC_FPU_SAVE_RESTORE */ Loading arch/arc/kernel/Makefile +2 −0 Original line number Diff line number Diff line Loading @@ -23,7 +23,9 @@ obj-$(CONFIG_PERF_EVENTS) += perf_event.o obj-$(CONFIG_JUMP_LABEL) += jump_label.o obj-$(CONFIG_ARC_FPU_SAVE_RESTORE) += fpu.o ifdef CONFIG_ISA_ARCOMPACT CFLAGS_fpu.o += -mdpfp endif ifdef CONFIG_ARC_DW2_UNWIND CFLAGS_ctx_sw.o += -fno-omit-frame-pointer Loading arch/arc/kernel/fpu.c +27 −0 Original line number Diff line number Diff line Loading @@ -8,6 +8,8 @@ #include <linux/sched.h> #include <asm/fpu.h> #ifdef CONFIG_ISA_ARCOMPACT /* * To save/restore FPU regs, simplest scheme would use LR/SR insns. * However since SR serializes the pipeline, an alternate "hack" can be used Loading Loading @@ -50,3 +52,28 @@ void fpu_save_restore(struct task_struct *prev, struct task_struct *next) : "r" (zero), "r" (*(readfrom + 3)), "r" (*(readfrom + 2)) ); } #else void fpu_init_task(struct pt_regs *regs) { /* default rounding mode */ write_aux_reg(ARC_REG_FPU_CTRL, 0x100); /* set "Write enable" to allow explicit write to exception flags */ write_aux_reg(ARC_REG_FPU_STATUS, 0x80000000); } void fpu_save_restore(struct task_struct *prev, struct task_struct *next) { struct arc_fpu *save = &prev->thread.fpu; struct arc_fpu *restore = &next->thread.fpu; save->ctrl = read_aux_reg(ARC_REG_FPU_CTRL); save->status = read_aux_reg(ARC_REG_FPU_STATUS); write_aux_reg(ARC_REG_FPU_CTRL, restore->ctrl); write_aux_reg(ARC_REG_FPU_STATUS, restore->status); } #endif Loading
arch/arc/Kconfig +5 −10 Original line number Diff line number Diff line Loading @@ -351,9 +351,8 @@ config NODES_SHIFT Accessing memory beyond 1GB (with or w/o PAE) requires 2 memory zones. if ISA_ARCOMPACT config ARC_COMPACT_IRQ_LEVELS depends on ISA_ARCOMPACT bool "Setup Timer IRQ as high Priority" # if SMP, LV2 enabled ONLY if ARC implementation has LV2 re-entrancy depends on !SMP Loading @@ -361,14 +360,10 @@ config ARC_COMPACT_IRQ_LEVELS config ARC_FPU_SAVE_RESTORE bool "Enable FPU state persistence across context switch" help Double Precision Floating Point unit had dedicated regs which need to be saved/restored across context-switch. Note that ARC FPU is overly simplistic, unlike say x86, which has hardware pieces to allow software to conditionally save/restore, based on actual usage of FPU by a task. Thus our implemn does this for all tasks in system. endif #ISA_ARCOMPACT ARCompact FPU has internal registers to assist with Double precision Floating Point operations. There are control and stauts registers for floating point exceptions and rounding modes. These are preserved across task context switch when enabled. config ARC_CANT_LLSC def_bool n Loading
arch/arc/include/asm/arcregs.h +2 −0 Original line number Diff line number Diff line Loading @@ -39,6 +39,8 @@ #define ARC_REG_CLUSTER_BCR 0xcf #define ARC_REG_AUX_ICCM 0x208 /* ICCM Base Addr (ARCv2) */ #define ARC_REG_LPB_CTRL 0x488 /* ARCv2 Loop Buffer control */ #define ARC_REG_FPU_CTRL 0x300 #define ARC_REG_FPU_STATUS 0x301 /* Common for ARCompact and ARCv2 status register */ #define ARC_REG_STATUS32 0x0A Loading
arch/arc/include/asm/fpu.h +27 −1 Original line number Diff line number Diff line Loading @@ -11,6 +11,8 @@ #include <asm/ptrace.h> #ifdef CONFIG_ISA_ARCOMPACT /* These DPFP regs need to be saved/restored across ctx-sw */ struct arc_fpu { struct { Loading @@ -18,11 +20,35 @@ struct arc_fpu { } aux_dpfp[2]; }; extern void fpu_save_restore(struct task_struct *p, struct task_struct *n); #define fpu_init_task(regs) #else /* * ARCv2 FPU Control aux register * - bits to enable Traps on Exceptions * - Rounding mode * * ARCv2 FPU Status aux register * - FPU exceptions flags (Inv, Div-by-Zero, overflow, underflow, inexact) * - Flag Write Enable to clear flags explicitly (vs. by fpu instructions * only */ struct arc_fpu { unsigned int ctrl, status; }; extern void fpu_init_task(struct pt_regs *regs); #endif /* !CONFIG_ISA_ARCOMPACT */ extern void fpu_save_restore(struct task_struct *p, struct task_struct *n); #else /* !CONFIG_ARC_FPU_SAVE_RESTORE */ #define fpu_save_restore(p, n) #define fpu_init_task(regs) #endif /* CONFIG_ARC_FPU_SAVE_RESTORE */ Loading
arch/arc/kernel/Makefile +2 −0 Original line number Diff line number Diff line Loading @@ -23,7 +23,9 @@ obj-$(CONFIG_PERF_EVENTS) += perf_event.o obj-$(CONFIG_JUMP_LABEL) += jump_label.o obj-$(CONFIG_ARC_FPU_SAVE_RESTORE) += fpu.o ifdef CONFIG_ISA_ARCOMPACT CFLAGS_fpu.o += -mdpfp endif ifdef CONFIG_ARC_DW2_UNWIND CFLAGS_ctx_sw.o += -fno-omit-frame-pointer Loading
arch/arc/kernel/fpu.c +27 −0 Original line number Diff line number Diff line Loading @@ -8,6 +8,8 @@ #include <linux/sched.h> #include <asm/fpu.h> #ifdef CONFIG_ISA_ARCOMPACT /* * To save/restore FPU regs, simplest scheme would use LR/SR insns. * However since SR serializes the pipeline, an alternate "hack" can be used Loading Loading @@ -50,3 +52,28 @@ void fpu_save_restore(struct task_struct *prev, struct task_struct *next) : "r" (zero), "r" (*(readfrom + 3)), "r" (*(readfrom + 2)) ); } #else void fpu_init_task(struct pt_regs *regs) { /* default rounding mode */ write_aux_reg(ARC_REG_FPU_CTRL, 0x100); /* set "Write enable" to allow explicit write to exception flags */ write_aux_reg(ARC_REG_FPU_STATUS, 0x80000000); } void fpu_save_restore(struct task_struct *prev, struct task_struct *next) { struct arc_fpu *save = &prev->thread.fpu; struct arc_fpu *restore = &next->thread.fpu; save->ctrl = read_aux_reg(ARC_REG_FPU_CTRL); save->status = read_aux_reg(ARC_REG_FPU_STATUS); write_aux_reg(ARC_REG_FPU_CTRL, restore->ctrl); write_aux_reg(ARC_REG_FPU_STATUS, restore->status); } #endif