Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'for-linus' of https://github.com/openrisc/linux

Pull OpenRISC updates from Stafford Horne:
"Two things for OpenRISC this cycle:

- Small cleanup for device tree cpu iteration from Rob Herring

- Add support for storing, restoring and accessing user space FPU
state, to allow for libc to support the FPU on OpenRISC"

* tag 'for-linus' of https://github.com/openrisc/linux:
openrisc: Add floating point regset
openrisc: Support floating point user api
openrisc: Support storing and restoring fpu state
openrisc: Properly store r31 to pt_regs on unhandled exceptions
openrisc: Use common of_get_cpu_node() instead of open-coding

+101 -31
+2 -2
arch/openrisc/include/asm/ptrace.h
··· 59 59 * -1 for all other exceptions. 60 60 */ 61 61 long orig_gpr11; /* For restarting system calls */ 62 - long dummy; /* Cheap alignment fix */ 62 + long fpcsr; /* Floating point control status register. */ 63 63 long dummy2; /* Cheap alignment fix */ 64 64 }; 65 65 ··· 115 115 #define PT_GPR31 124 116 116 #define PT_PC 128 117 117 #define PT_ORIG_GPR11 132 118 - #define PT_SYSCALLNO 136 118 + #define PT_FPCSR 136 119 119 120 120 #endif /* __ASM_OPENRISC_PTRACE_H */
+1 -2
arch/openrisc/include/uapi/asm/elf.h
··· 53 53 #define ELF_NGREG (sizeof(struct user_regs_struct) / sizeof(elf_greg_t)) 54 54 typedef elf_greg_t elf_gregset_t[ELF_NGREG]; 55 55 56 - /* A placeholder; OR32 does not have fp support yes, so no fp regs for now. */ 57 - typedef unsigned long elf_fpregset_t; 56 + typedef struct __or1k_fpu_state elf_fpregset_t; 58 57 59 58 /* EM_OPENRISC is defined in linux/elf-em.h */ 60 59 #define EM_OR32 0x8472
+4
arch/openrisc/include/uapi/asm/ptrace.h
··· 30 30 unsigned long pc; 31 31 unsigned long sr; 32 32 }; 33 + 34 + struct __or1k_fpu_state { 35 + unsigned long fpcsr; 36 + }; 33 37 #endif 34 38 35 39
+1
arch/openrisc/include/uapi/asm/sigcontext.h
··· 28 28 29 29 struct sigcontext { 30 30 struct user_regs_struct regs; /* needs to be first */ 31 + struct __or1k_fpu_state fpu; 31 32 unsigned long oldmask; 32 33 }; 33 34
+25 -6
arch/openrisc/kernel/entry.S
··· 106 106 l.mtspr r0,r3,SPR_EPCR_BASE ;\ 107 107 l.lwz r3,PT_SR(r1) ;\ 108 108 l.mtspr r0,r3,SPR_ESR_BASE ;\ 109 + l.lwz r3,PT_FPCSR(r1) ;\ 110 + l.mtspr r0,r3,SPR_FPCSR ;\ 109 111 l.lwz r2,PT_GPR2(r1) ;\ 110 112 l.lwz r3,PT_GPR3(r1) ;\ 111 113 l.lwz r4,PT_GPR4(r1) ;\ ··· 175 173 l.sw PT_GPR28(r1),r28 ;\ 176 174 l.sw PT_GPR29(r1),r29 ;\ 177 175 /* r30 already save */ ;\ 178 - /* l.sw PT_GPR30(r1),r30*/ ;\ 179 176 l.sw PT_GPR31(r1),r31 ;\ 180 177 TRACE_IRQS_OFF_ENTRY ;\ 178 + l.mfspr r30,r0,SPR_FPCSR ;\ 179 + l.sw PT_FPCSR(r1),r30 ;\ 181 180 /* Store -1 in orig_gpr11 for non-syscall exceptions */ ;\ 182 181 l.addi r30,r0,-1 ;\ 183 182 l.sw PT_ORIG_GPR11(r1),r30 ··· 214 211 l.sw PT_GPR27(r1),r27 ;\ 215 212 l.sw PT_GPR28(r1),r28 ;\ 216 213 l.sw PT_GPR29(r1),r29 ;\ 217 - /* r31 already saved */ ;\ 218 - l.sw PT_GPR30(r1),r30 ;\ 219 - /* l.sw PT_GPR31(r1),r31 */ ;\ 214 + /* r30 already saved */ ;\ 215 + l.sw PT_GPR31(r1),r31 ;\ 220 216 /* Store -1 in orig_gpr11 for non-syscall exceptions */ ;\ 221 217 l.addi r30,r0,-1 ;\ 222 218 l.sw PT_ORIG_GPR11(r1),r30 ;\ 219 + l.mfspr r30,r0,SPR_FPCSR ;\ 220 + l.sw PT_FPCSR(r1),r30 ;\ 223 221 l.addi r3,r1,0 ;\ 224 222 /* r4 is exception EA */ ;\ 225 223 l.addi r5,r0,vector ;\ ··· 848 844 849 845 /******* END SYSCALL HANDLING *******/ 850 846 851 - /* ---[ 0xd00: Trap exception ]------------------------------------------ */ 847 + /* ---[ 0xd00: Floating Point exception ]-------------------------------- */ 852 848 853 - UNHANDLED_EXCEPTION(_vector_0xd00,0xd00) 849 + EXCEPTION_ENTRY(_fpe_trap_handler) 850 + CLEAR_LWA_FLAG(r3) 851 + /* r4: EA of fault (set by EXCEPTION_HANDLE) */ 852 + l.jal do_fpe_trap 853 + l.addi r3,r1,0 /* pt_regs */ 854 + 855 + l.j _ret_from_exception 856 + l.nop 854 857 855 858 /* ---[ 0xe00: Trap exception ]------------------------------------------ */ 856 859 ··· 1100 1089 l.sw PT_GPR28(r1),r28 1101 1090 l.sw PT_GPR30(r1),r30 1102 1091 1092 + /* Store the old FPU state to new pt_regs */ 1093 + l.mfspr r29,r0,SPR_FPCSR 1094 + l.sw PT_FPCSR(r1),r29 1095 + 1103 1096 l.addi r11,r10,0 /* Save old 'current' to 'last' return value*/ 1104 1097 1105 1098 /* We use thread_info->ksp for storing the address of the above ··· 1125 1110 /* Restore the old value of thread_info->ksp */ 1126 1111 l.lwz r29,PT_SP(r1) 1127 1112 l.sw TI_KSP(r10),r29 1113 + 1114 + /* Restore the old value of FPCSR */ 1115 + l.lwz r29,PT_FPCSR(r1) 1116 + l.mtspr r0,r29,SPR_FPCSR 1128 1117 1129 1118 /* ...and restore the registers, except r11 because the return value 1130 1119 * has already been set above.
+2 -2
arch/openrisc/kernel/head.S
··· 424 424 .org 0xc00 425 425 EXCEPTION_HANDLE(_sys_call_handler) 426 426 427 - /* ---[ 0xd00: Trap exception ]------------------------------------------ */ 427 + /* ---[ 0xd00: Floating point exception ]--------------------------------- */ 428 428 .org 0xd00 429 - UNHANDLED_EXCEPTION(_vector_0xd00) 429 + EXCEPTION_HANDLE(_fpe_trap_handler) 430 430 431 431 /* ---[ 0xe00: Trap exception ]------------------------------------------ */ 432 432 .org 0xe00
+37
arch/openrisc/kernel/ptrace.c
··· 85 85 } 86 86 87 87 /* 88 + * As OpenRISC shares GPRs and floating point registers we don't need to export 89 + * the floating point registers again. So here we only export the fpcsr special 90 + * purpose register. 91 + */ 92 + static int fpregs_get(struct task_struct *target, 93 + const struct user_regset *regset, 94 + struct membuf to) 95 + { 96 + const struct pt_regs *regs = task_pt_regs(target); 97 + 98 + return membuf_store(&to, regs->fpcsr); 99 + } 100 + 101 + static int fpregs_set(struct task_struct *target, 102 + const struct user_regset *regset, 103 + unsigned int pos, unsigned int count, 104 + const void *kbuf, const void __user *ubuf) 105 + { 106 + struct pt_regs *regs = task_pt_regs(target); 107 + int ret; 108 + 109 + /* FPCSR */ 110 + ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, 111 + &regs->fpcsr, 0, 4); 112 + return ret; 113 + } 114 + 115 + /* 88 116 * Define the register sets available on OpenRISC under Linux 89 117 */ 90 118 enum or1k_regset { 91 119 REGSET_GENERAL, 120 + REGSET_FPU, 92 121 }; 93 122 94 123 static const struct user_regset or1k_regsets[] = { ··· 128 99 .align = sizeof(long), 129 100 .regset_get = genregs_get, 130 101 .set = genregs_set, 102 + }, 103 + [REGSET_FPU] = { 104 + .core_note_type = NT_PRFPREG, 105 + .n = sizeof(struct __or1k_fpu_state) / sizeof(long), 106 + .size = sizeof(long), 107 + .align = sizeof(long), 108 + .regset_get = fpregs_get, 109 + .set = fpregs_set, 131 110 }, 132 111 }; 133 112
+2 -17
arch/openrisc/kernel/setup.c
··· 152 152 printk(KERN_INFO "-- custom unit(s)\n"); 153 153 } 154 154 155 - static struct device_node *setup_find_cpu_node(int cpu) 156 - { 157 - u32 hwid; 158 - struct device_node *cpun; 159 - 160 - for_each_of_cpu_node(cpun) { 161 - if (of_property_read_u32(cpun, "reg", &hwid)) 162 - continue; 163 - if (hwid == cpu) 164 - return cpun; 165 - } 166 - 167 - return NULL; 168 - } 169 - 170 155 void __init setup_cpuinfo(void) 171 156 { 172 157 struct device_node *cpu; ··· 160 175 int cpu_id = smp_processor_id(); 161 176 struct cpuinfo_or1k *cpuinfo = &cpuinfo_or1k[cpu_id]; 162 177 163 - cpu = setup_find_cpu_node(cpu_id); 178 + cpu = of_get_cpu_node(cpu_id, NULL); 164 179 if (!cpu) 165 180 panic("Couldn't find CPU%d in device tree...\n", cpu_id); 166 181 ··· 240 255 void calibrate_delay(void) 241 256 { 242 257 const int *val; 243 - struct device_node *cpu = setup_find_cpu_node(smp_processor_id()); 258 + struct device_node *cpu = of_get_cpu_node(smp_processor_id(), NULL); 244 259 245 260 val = of_get_property(cpu, "clock-frequency", NULL); 246 261 if (!val)
+2
arch/openrisc/kernel/signal.c
··· 50 50 err |= __copy_from_user(regs, sc->regs.gpr, 32 * sizeof(unsigned long)); 51 51 err |= __copy_from_user(&regs->pc, &sc->regs.pc, sizeof(unsigned long)); 52 52 err |= __copy_from_user(&regs->sr, &sc->regs.sr, sizeof(unsigned long)); 53 + err |= __copy_from_user(&regs->fpcsr, &sc->fpu.fpcsr, sizeof(unsigned long)); 53 54 54 55 /* make sure the SM-bit is cleared so user-mode cannot fool us */ 55 56 regs->sr &= ~SPR_SR_SM; ··· 113 112 err |= __copy_to_user(sc->regs.gpr, regs, 32 * sizeof(unsigned long)); 114 113 err |= __copy_to_user(&sc->regs.pc, &regs->pc, sizeof(unsigned long)); 115 114 err |= __copy_to_user(&sc->regs.sr, &regs->sr, sizeof(unsigned long)); 115 + err |= __copy_to_user(&sc->fpu.fpcsr, &regs->fpcsr, sizeof(unsigned long)); 116 116 117 117 return err; 118 118 }
+25 -2
arch/openrisc/kernel/traps.c
··· 75 75 in_kernel = 0; 76 76 77 77 printk("CPU #: %d\n" 78 - " PC: %08lx SR: %08lx SP: %08lx\n", 79 - smp_processor_id(), regs->pc, regs->sr, regs->sp); 78 + " PC: %08lx SR: %08lx SP: %08lx FPCSR: %08lx\n", 79 + smp_processor_id(), regs->pc, regs->sr, regs->sp, 80 + regs->fpcsr); 80 81 printk("GPR00: %08lx GPR01: %08lx GPR02: %08lx GPR03: %08lx\n", 81 82 0L, regs->gpr[1], regs->gpr[2], regs->gpr[3]); 82 83 printk("GPR04: %08lx GPR05: %08lx GPR06: %08lx GPR07: %08lx\n", ··· 241 240 printk("Unable to handle exception at EA =0x%x, vector 0x%x", 242 241 ea, vector); 243 242 die("Oops", regs, 9); 243 + } 244 + 245 + asmlinkage void do_fpe_trap(struct pt_regs *regs, unsigned long address) 246 + { 247 + int code = FPE_FLTUNK; 248 + unsigned long fpcsr = regs->fpcsr; 249 + 250 + if (fpcsr & SPR_FPCSR_IVF) 251 + code = FPE_FLTINV; 252 + else if (fpcsr & SPR_FPCSR_OVF) 253 + code = FPE_FLTOVF; 254 + else if (fpcsr & SPR_FPCSR_UNF) 255 + code = FPE_FLTUND; 256 + else if (fpcsr & SPR_FPCSR_DZF) 257 + code = FPE_FLTDIV; 258 + else if (fpcsr & SPR_FPCSR_IXF) 259 + code = FPE_FLTRES; 260 + 261 + /* Clear all flags */ 262 + regs->fpcsr &= ~SPR_FPCSR_ALLF; 263 + 264 + force_sig_fault(SIGFPE, code, (void __user *)regs->pc); 244 265 } 245 266 246 267 asmlinkage void do_trap(struct pt_regs *regs, unsigned long address)