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

csky: Optimize the trap processing flow

- Seperate different trap functions
- Add trap_no()
- Remove panic code print
- Redesign die_if_kerenl to die with riscv's
- Print exact trap info for app segment fault

[ 17.389321] gzip[126]: unhandled signal 11 code 0x3 at 0x0007835a in busybox[8000+d4000]
[ 17.393882]
[ 17.393882] CURRENT PROCESS:
[ 17.393882]
[ 17.394309] COMM=gzip PID=126
[ 17.394513] TEXT=00008000-000db2e4 DATA=000dcf14-000dd1ad BSS=000dd1ad-000ff000
[ 17.395499] USER-STACK=7f888e50 KERNEL-STACK=bf130300
[ 17.395499]
[ 17.396801] PC: 0x0007835a (0x7835a)
[ 17.397048] LR: 0x000058b4 (0x58b4)
[ 17.397285] SP: 0xbe519f68
[ 17.397555] orig_a0: 0x00002852
[ 17.397886] PSR: 0x00020341
[ 17.398356] a0: 0x00002852 a1: 0x000f2f5a a2: 0x0000d7ae a3: 0x0000005d
[ 17.399289] r4: 0x000de150 r5: 0x00000002 r6: 0x00000102 r7: 0x00007efa
[ 17.399800] r8: 0x7f888bc4 r9: 0x00000001 r10: 0x000002eb r11: 0x0000aac1
[ 17.400166] r12: 0x00002ef2 r13: 0x00000007 r15: 0x000058b4
[ 17.400531] r16: 0x0000004c r17: 0x00000031 r18: 0x000f5816 r19: 0x000e8068
[ 17.401006] r20: 0x000f5818 r21: 0x000e8068 r22: 0x000f5918 r23: 0x90000000
[ 17.401721] r24: 0x00000031 r25: 0x000000c8 r26: 0x00000000 r27: 0x00000000
[ 17.402199] r28: 0x2ac2a000 r29: 0x00000000 r30: 0x00000000 tls: 0x2aadbaa8
[ 17.402686] hi: 0x00120340 lo: 0x7f888bec
/etc/init.ci/ntfs3g_run: line 61: 126 Segmentation fault gzip -c -9 /mnt/test.bin > /mnt/test_bin.gz

Signed-off-by: Guo Ren <guoren@linux.alibaba.com>
Cc: Arnd Bergmann <arnd@arndb.de>

Guo Ren 5bc46ce2 71e193d7

+160 -112
+2 -1
arch/csky/include/asm/bug.h
··· 20 20 21 21 struct pt_regs; 22 22 23 - void die_if_kernel(char *str, struct pt_regs *regs, int nr); 23 + void die(struct pt_regs *regs, const char *str); 24 24 void show_regs(struct pt_regs *regs); 25 + void show_code(struct pt_regs *regs); 25 26 26 27 #endif /* __ASM_CSKY_BUG_H */
+1
arch/csky/include/asm/ptrace.h
··· 24 24 #define user_mode(regs) (!((regs)->sr & PS_S)) 25 25 #define instruction_pointer(regs) ((regs)->pc) 26 26 #define profile_pc(regs) instruction_pointer(regs) 27 + #define trap_no(regs) ((regs->sr >> 16) & 0xff) 27 28 28 29 static inline void instruction_pointer_set(struct pt_regs *regs, 29 30 unsigned long val)
+2 -27
arch/csky/kernel/ptrace.c
··· 347 347 trace_sys_exit(regs, syscall_get_return_value(current, regs)); 348 348 } 349 349 350 - extern void show_stack(struct task_struct *task, unsigned long *stack, const char *loglvl); 351 350 void show_regs(struct pt_regs *fp) 352 351 { 353 - unsigned long *sp; 354 - unsigned char *tp; 355 - int i; 356 - 357 352 pr_info("\nCURRENT PROCESS:\n\n"); 358 353 pr_info("COMM=%s PID=%d\n", current->comm, current->pid); 359 354 ··· 395 400 fp->regs[0], fp->regs[1], fp->regs[2], fp->regs[3]); 396 401 pr_info("r10: 0x%08lx r11: 0x%08lx r12: 0x%08lx r13: 0x%08lx\n", 397 402 fp->regs[4], fp->regs[5], fp->regs[6], fp->regs[7]); 398 - pr_info("r14: 0x%08lx r1: 0x%08lx r15: 0x%08lx\n", 399 - fp->regs[8], fp->regs[9], fp->lr); 403 + pr_info("r14: 0x%08lx r1: 0x%08lx\n", 404 + fp->regs[8], fp->regs[9]); 400 405 #endif 401 406 402 - pr_info("\nCODE:"); 403 - tp = ((unsigned char *) fp->pc) - 0x20; 404 - tp += ((int)tp % 4) ? 2 : 0; 405 - for (sp = (unsigned long *) tp, i = 0; (i < 0x40); i += 4) { 406 - if ((i % 0x10) == 0) 407 - pr_cont("\n%08x: ", (int) (tp + i)); 408 - pr_cont("%08x ", (int) *sp++); 409 - } 410 - pr_cont("\n"); 411 - 412 - pr_info("\nKERNEL STACK:"); 413 - tp = ((unsigned char *) fp) - 0x40; 414 - for (sp = (unsigned long *) tp, i = 0; (i < 0xc0); i += 4) { 415 - if ((i % 0x10) == 0) 416 - pr_cont("\n%08x: ", (int) (tp + i)); 417 - pr_cont("%08x ", (int) *sp++); 418 - } 419 - pr_cont("\n"); 420 - 421 - show_stack(NULL, (unsigned long *)fp->regs[4], KERN_INFO); 422 407 return; 423 408 }
+150 -79
arch/csky/kernel/traps.c
··· 15 15 #include <linux/rtc.h> 16 16 #include <linux/uaccess.h> 17 17 #include <linux/kprobes.h> 18 + #include <linux/kdebug.h> 19 + #include <linux/sched/debug.h> 18 20 19 21 #include <asm/setup.h> 20 22 #include <asm/traps.h> ··· 28 26 #ifdef CONFIG_CPU_HAS_FPU 29 27 #include <abi/fpu.h> 30 28 #endif 29 + 30 + int show_unhandled_signals = 1; 31 31 32 32 /* Defined in entry.S */ 33 33 asmlinkage void csky_trap(void); ··· 81 77 #endif 82 78 } 83 79 84 - void die_if_kernel(char *str, struct pt_regs *regs, int nr) 85 - { 86 - if (user_mode(regs)) 87 - return; 80 + static DEFINE_SPINLOCK(die_lock); 88 81 82 + void die(struct pt_regs *regs, const char *str) 83 + { 84 + static int die_counter; 85 + int ret; 86 + 87 + oops_enter(); 88 + 89 + spin_lock_irq(&die_lock); 89 90 console_verbose(); 90 - pr_err("%s: %08x\n", str, nr); 91 + bust_spinlocks(1); 92 + 93 + pr_emerg("%s [#%d]\n", str, ++die_counter); 94 + print_modules(); 91 95 show_regs(regs); 96 + show_stack(current, (unsigned long *)regs->regs[4], KERN_INFO); 97 + 98 + ret = notify_die(DIE_OOPS, str, regs, 0, trap_no(regs), SIGSEGV); 99 + 100 + bust_spinlocks(0); 92 101 add_taint(TAINT_DIE, LOCKDEP_NOW_UNRELIABLE); 93 - do_exit(SIGSEGV); 102 + spin_unlock_irq(&die_lock); 103 + oops_exit(); 104 + 105 + if (in_interrupt()) 106 + panic("Fatal exception in interrupt"); 107 + if (panic_on_oops) 108 + panic("Fatal exception"); 109 + if (ret != NOTIFY_STOP) 110 + do_exit(SIGSEGV); 94 111 } 95 112 96 - void buserr(struct pt_regs *regs) 113 + void do_trap(struct pt_regs *regs, int signo, int code, unsigned long addr) 97 114 { 98 - #ifdef CONFIG_CPU_CK810 99 - static unsigned long prev_pc; 115 + struct task_struct *tsk = current; 100 116 101 - if ((regs->pc == prev_pc) && prev_pc != 0) { 102 - prev_pc = 0; 117 + if (show_unhandled_signals && unhandled_signal(tsk, signo) 118 + && printk_ratelimit()) { 119 + pr_info("%s[%d]: unhandled signal %d code 0x%x at 0x%08lx", 120 + tsk->comm, task_pid_nr(tsk), signo, code, addr); 121 + print_vma_addr(KERN_CONT " in ", instruction_pointer(regs)); 122 + pr_cont("\n"); 123 + show_regs(regs); 124 + } 125 + 126 + force_sig_fault(signo, code, (void __user *)addr); 127 + } 128 + 129 + static void do_trap_error(struct pt_regs *regs, int signo, int code, 130 + unsigned long addr, const char *str) 131 + { 132 + current->thread.trap_no = trap_no(regs); 133 + 134 + if (user_mode(regs)) { 135 + do_trap(regs, signo, code, addr); 103 136 } else { 104 - prev_pc = regs->pc; 137 + if (!fixup_exception(regs)) 138 + die(regs, str); 139 + } 140 + } 141 + 142 + #define DO_ERROR_INFO(name, signo, code, str) \ 143 + asmlinkage __visible void name(struct pt_regs *regs) \ 144 + { \ 145 + do_trap_error(regs, signo, code, regs->pc, "Oops - " str); \ 146 + } 147 + 148 + DO_ERROR_INFO(do_trap_unknown, 149 + SIGILL, ILL_ILLTRP, "unknown exception"); 150 + DO_ERROR_INFO(do_trap_zdiv, 151 + SIGFPE, FPE_INTDIV, "error zero div exception"); 152 + DO_ERROR_INFO(do_trap_buserr, 153 + SIGSEGV, ILL_ILLADR, "error bus error exception"); 154 + 155 + asmlinkage void do_trap_misaligned(struct pt_regs *regs) 156 + { 157 + #ifdef CONFIG_CPU_NEED_SOFTALIGN 158 + csky_alignment(regs); 159 + #else 160 + current->thread.trap_no = trap_no(regs); 161 + do_trap_error(regs, SIGBUS, BUS_ADRALN, regs->pc, 162 + "Oops - load/store address misaligned"); 163 + #endif 164 + } 165 + 166 + asmlinkage void do_trap_bkpt(struct pt_regs *regs) 167 + { 168 + #ifdef CONFIG_KPROBES 169 + if (kprobe_single_step_handler(regs)) 170 + return; 171 + #endif 172 + #ifdef CONFIG_UPROBES 173 + if (uprobe_single_step_handler(regs)) 174 + return; 175 + #endif 176 + if (user_mode(regs)) { 177 + send_sig(SIGTRAP, current, 0); 178 + return; 179 + } 180 + 181 + do_trap_error(regs, SIGILL, ILL_ILLTRP, regs->pc, 182 + "Oops - illegal trap exception"); 183 + } 184 + 185 + asmlinkage void do_trap_illinsn(struct pt_regs *regs) 186 + { 187 + current->thread.trap_no = trap_no(regs); 188 + 189 + #ifdef CONFIG_KPROBES 190 + if (kprobe_breakpoint_handler(regs)) 191 + return; 192 + #endif 193 + #ifdef CONFIG_UPROBES 194 + if (uprobe_breakpoint_handler(regs)) 195 + return; 196 + #endif 197 + #ifndef CONFIG_CPU_NO_USER_BKPT 198 + if (*(uint16_t *)instruction_pointer(regs) != USR_BKPT) { 199 + send_sig(SIGTRAP, current, 0); 105 200 return; 106 201 } 107 202 #endif 108 203 109 - die_if_kernel("Kernel mode BUS error", regs, 0); 204 + do_trap_error(regs, SIGILL, ILL_ILLOPC, regs->pc, 205 + "Oops - illegal instruction exception"); 206 + } 110 207 111 - pr_err("User mode Bus Error\n"); 112 - show_regs(regs); 208 + asmlinkage void do_trap_fpe(struct pt_regs *regs) 209 + { 210 + #ifdef CONFIG_CPU_HAS_FP 211 + return fpu_fpe(regs); 212 + #else 213 + do_trap_error(regs, SIGILL, ILL_ILLOPC, regs->pc, 214 + "Oops - fpu instruction exception"); 215 + #endif 216 + } 113 217 114 - force_sig_fault(SIGSEGV, 0, (void __user *)regs->pc); 218 + asmlinkage void do_trap_priv(struct pt_regs *regs) 219 + { 220 + #ifdef CONFIG_CPU_HAS_FP 221 + if (user_mode(regs) && fpu_libc_helper(regs)) 222 + return; 223 + #endif 224 + do_trap_error(regs, SIGILL, ILL_PRVOPC, regs->pc, 225 + "Oops - illegal privileged exception"); 115 226 } 116 227 117 228 asmlinkage void trap_c(struct pt_regs *regs) 118 229 { 119 - int sig; 120 - unsigned long vector; 121 - siginfo_t info; 122 - struct task_struct *tsk = current; 123 - 124 - vector = (regs->sr >> 16) & 0xff; 125 - 126 - switch (vector) { 230 + switch (trap_no(regs)) { 127 231 case VEC_ZERODIV: 128 - die_if_kernel("Kernel mode ZERO DIV", regs, vector); 129 - sig = SIGFPE; 232 + do_trap_zdiv(regs); 130 233 break; 131 - /* ptrace */ 132 234 case VEC_TRACE: 133 - #ifdef CONFIG_KPROBES 134 - if (kprobe_single_step_handler(regs)) 135 - return; 136 - #endif 137 - #ifdef CONFIG_UPROBES 138 - if (uprobe_single_step_handler(regs)) 139 - return; 140 - #endif 141 - info.si_code = TRAP_TRACE; 142 - sig = SIGTRAP; 235 + do_trap_bkpt(regs); 143 236 break; 144 237 case VEC_ILLEGAL: 145 - tsk->thread.trap_no = vector; 146 - #ifdef CONFIG_KPROBES 147 - if (kprobe_breakpoint_handler(regs)) 148 - return; 149 - #endif 150 - #ifdef CONFIG_UPROBES 151 - if (uprobe_breakpoint_handler(regs)) 152 - return; 153 - #endif 154 - die_if_kernel("Kernel mode ILLEGAL", regs, vector); 155 - #ifndef CONFIG_CPU_NO_USER_BKPT 156 - if (*(uint16_t *)instruction_pointer(regs) != USR_BKPT) 157 - #endif 158 - { 159 - sig = SIGILL; 160 - break; 161 - } 162 - /* gdbserver breakpoint */ 238 + do_trap_illinsn(regs); 239 + break; 163 240 case VEC_TRAP1: 164 - /* jtagserver breakpoint */ 165 241 case VEC_BREAKPOINT: 166 - die_if_kernel("Kernel mode BKPT", regs, vector); 167 - info.si_code = TRAP_BRKPT; 168 - sig = SIGTRAP; 242 + do_trap_bkpt(regs); 169 243 break; 170 244 case VEC_ACCESS: 171 - tsk->thread.trap_no = vector; 172 - return buserr(regs); 173 - #ifdef CONFIG_CPU_NEED_SOFTALIGN 245 + do_trap_buserr(regs); 246 + break; 174 247 case VEC_ALIGN: 175 - tsk->thread.trap_no = vector; 176 - return csky_alignment(regs); 177 - #endif 178 - #ifdef CONFIG_CPU_HAS_FPU 248 + do_trap_misaligned(regs); 249 + break; 179 250 case VEC_FPE: 180 - tsk->thread.trap_no = vector; 181 - die_if_kernel("Kernel mode FPE", regs, vector); 182 - return fpu_fpe(regs); 251 + do_trap_fpe(regs); 252 + break; 183 253 case VEC_PRIV: 184 - tsk->thread.trap_no = vector; 185 - die_if_kernel("Kernel mode PRIV", regs, vector); 186 - if (fpu_libc_helper(regs)) 187 - return; 188 - #endif 254 + do_trap_priv(regs); 255 + break; 189 256 default: 190 - sig = SIGSEGV; 257 + do_trap_unknown(regs); 191 258 break; 192 259 } 193 - 194 - tsk->thread.trap_no = vector; 195 - 196 - send_sig(sig, current, 0); 197 260 }
+5 -5
arch/csky/mm/fault.c
··· 183 183 bad_area_nosemaphore: 184 184 /* User mode accesses just cause a SIGSEGV */ 185 185 if (user_mode(regs)) { 186 - tsk->thread.trap_no = (regs->sr >> 16) & 0xff; 186 + tsk->thread.trap_no = trap_no(regs); 187 187 force_sig_fault(SIGSEGV, si_code, (void __user *)address); 188 188 return; 189 189 } 190 190 191 191 no_context: 192 - tsk->thread.trap_no = (regs->sr >> 16) & 0xff; 192 + tsk->thread.trap_no = trap_no(regs); 193 193 194 194 /* Are we prepared to handle this kernel fault? */ 195 195 if (fixup_exception(regs)) ··· 202 202 bust_spinlocks(1); 203 203 pr_alert("Unable to handle kernel paging request at virtual " 204 204 "address 0x%08lx, pc: 0x%08lx\n", address, regs->pc); 205 - die_if_kernel("Oops", regs, write); 205 + die(regs, "Oops"); 206 206 207 207 out_of_memory: 208 - tsk->thread.trap_no = (regs->sr >> 16) & 0xff; 208 + tsk->thread.trap_no = trap_no(regs); 209 209 210 210 /* 211 211 * We ran out of memory, call the OOM killer, and return the userspace ··· 215 215 return; 216 216 217 217 do_sigbus: 218 - tsk->thread.trap_no = (regs->sr >> 16) & 0xff; 218 + tsk->thread.trap_no = trap_no(regs); 219 219 220 220 mmap_read_unlock(mm); 221 221