From c23dd2405fc2054345be33f8bb1d04b3b805202d Mon Sep 17 00:00:00 2001 From: Tobias Klauser Date: Wed, 10 Jun 2020 17:39:35 +0200 Subject: csky: remove unusued thread_saved_pc and *_segments functions/macros These are used nowhere in the tree (except for some architectures which define them for their own use) and were already removed for other architectures in: commit 6474924e2b5d ("arch: remove unused macro/function thread_saved_pc()") commit c17c02040bf0 ("arch: remove unused *_segments() macros/functions") Remove them from arch/csky as well. Signed-off-by: Tobias Klauser Signed-off-by: Guo Ren Cc: Arnd Bergmann --- arch/csky/include/asm/processor.h | 6 ------ 1 file changed, 6 deletions(-) (limited to 'arch/csky/include') diff --git a/arch/csky/include/asm/processor.h b/arch/csky/include/asm/processor.h index 24442d8e86f9..4800f6563abb 100644 --- a/arch/csky/include/asm/processor.h +++ b/arch/csky/include/asm/processor.h @@ -82,12 +82,6 @@ static inline void release_thread(struct task_struct *dead_task) extern int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags); -#define copy_segments(tsk, mm) do { } while (0) -#define release_segments(mm) do { } while (0) -#define forget_segments() do { } while (0) - -extern unsigned long thread_saved_pc(struct task_struct *tsk); - unsigned long get_wchan(struct task_struct *p); #define KSTK_EIP(tsk) (task_pt_regs(tsk)->pc) -- cgit v1.2.3 From e95a4f8cb985e759648b32ed0b721a472deb86a5 Mon Sep 17 00:00:00 2001 From: Guo Ren Date: Tue, 26 May 2020 08:11:52 +0000 Subject: csky: Add SECCOMP_FILTER supported secure_computing() is called first in syscall_trace_enter() so that a system call will be aborted quickly without doing succeeding syscall tracing if seccomp rules want to deny that system call. TODO: - Update https://github.com/seccomp/libseccomp csky support Signed-off-by: Guo Ren Cc: Arnd Bergmann --- arch/csky/Kconfig | 14 ++++++++++++++ arch/csky/include/asm/Kbuild | 1 + arch/csky/include/asm/thread_info.h | 2 +- arch/csky/kernel/entry.S | 3 +++ arch/csky/kernel/ptrace.c | 8 ++++++-- tools/testing/selftests/seccomp/seccomp_bpf.c | 13 ++++++++++++- 6 files changed, 37 insertions(+), 4 deletions(-) (limited to 'arch/csky/include') diff --git a/arch/csky/Kconfig b/arch/csky/Kconfig index bd31ab12f77d..822362d0598e 100644 --- a/arch/csky/Kconfig +++ b/arch/csky/Kconfig @@ -38,6 +38,7 @@ config CSKY select GX6605S_TIMER if CPU_CK610 select HAVE_ARCH_TRACEHOOK select HAVE_ARCH_AUDITSYSCALL + select HAVE_ARCH_SECCOMP_FILTER select HAVE_COPY_THREAD_TLS select HAVE_DEBUG_BUGVERBOSE select HAVE_DYNAMIC_FTRACE @@ -296,3 +297,16 @@ endmenu source "arch/csky/Kconfig.platforms" source "kernel/Kconfig.hz" + +config SECCOMP + bool "Enable seccomp to safely compute untrusted bytecode" + help + This kernel feature is useful for number crunching applications + that may need to compute untrusted bytecode during their + execution. By using pipes or other transports made available to + the process as file descriptors supporting the read/write + syscalls, it's possible to isolate those applications in + their own address space using seccomp. Once seccomp is + enabled via prctl(PR_SET_SECCOMP), it cannot be disabled + and the task is only allowed to execute a few safe syscalls + defined by each seccomp mode. diff --git a/arch/csky/include/asm/Kbuild b/arch/csky/include/asm/Kbuild index 93372255984d..64876e59e2ef 100644 --- a/arch/csky/include/asm/Kbuild +++ b/arch/csky/include/asm/Kbuild @@ -4,5 +4,6 @@ generic-y += gpio.h generic-y += kvm_para.h generic-y += local64.h generic-y += qrwlock.h +generic-y += seccomp.h generic-y += user.h generic-y += vmlinux.lds.h diff --git a/arch/csky/include/asm/thread_info.h b/arch/csky/include/asm/thread_info.h index 8980e4e64391..68e7a1227170 100644 --- a/arch/csky/include/asm/thread_info.h +++ b/arch/csky/include/asm/thread_info.h @@ -85,6 +85,6 @@ static inline struct thread_info *current_thread_info(void) _TIF_NOTIFY_RESUME | _TIF_UPROBE) #define _TIF_SYSCALL_WORK (_TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT | \ - _TIF_SYSCALL_TRACEPOINT) + _TIF_SYSCALL_TRACEPOINT | _TIF_SECCOMP) #endif /* _ASM_CSKY_THREAD_INFO_H */ diff --git a/arch/csky/kernel/entry.S b/arch/csky/kernel/entry.S index f13800383a19..efd2e696e3cd 100644 --- a/arch/csky/kernel/entry.S +++ b/arch/csky/kernel/entry.S @@ -168,6 +168,8 @@ ENTRY(csky_systemcall) csky_syscall_trace: mov a0, sp /* sp = pt_regs pointer */ jbsr syscall_trace_enter + cmpnei a0, 0 + bt 1f /* Prepare args before do system call */ ldw a0, (sp, LSAVE_A0) ldw a1, (sp, LSAVE_A1) @@ -188,6 +190,7 @@ csky_syscall_trace: #endif stw a0, (sp, LSAVE_A0) /* Save return value */ +1: #ifdef CONFIG_DEBUG_RSEQ mov a0, sp jbsr rseq_syscall diff --git a/arch/csky/kernel/ptrace.c b/arch/csky/kernel/ptrace.c index 944ca2fdcdd9..0de10f7beae6 100644 --- a/arch/csky/kernel/ptrace.c +++ b/arch/csky/kernel/ptrace.c @@ -320,16 +320,20 @@ long arch_ptrace(struct task_struct *child, long request, return ret; } -asmlinkage void syscall_trace_enter(struct pt_regs *regs) +asmlinkage int syscall_trace_enter(struct pt_regs *regs) { if (test_thread_flag(TIF_SYSCALL_TRACE)) if (tracehook_report_syscall_entry(regs)) - syscall_set_nr(current, regs, -1); + return -1; + + if (secure_computing() == -1) + return -1; if (test_thread_flag(TIF_SYSCALL_TRACEPOINT)) trace_sys_enter(regs, syscall_get_nr(current, regs)); audit_syscall_entry(regs_syscallid(regs), regs->a0, regs->a1, regs->a2, regs->a3); + return 0; } asmlinkage void syscall_trace_exit(struct pt_regs *regs) diff --git a/tools/testing/selftests/seccomp/seccomp_bpf.c b/tools/testing/selftests/seccomp/seccomp_bpf.c index 252140a52553..8d18a0ddafdd 100644 --- a/tools/testing/selftests/seccomp/seccomp_bpf.c +++ b/tools/testing/selftests/seccomp/seccomp_bpf.c @@ -116,6 +116,8 @@ struct seccomp_data { # define __NR_seccomp 277 # elif defined(__riscv) # define __NR_seccomp 277 +# elif defined(__csky__) +# define __NR_seccomp 277 # elif defined(__hppa__) # define __NR_seccomp 338 # elif defined(__powerpc__) @@ -1603,6 +1605,14 @@ TEST_F(TRACE_poke, getpid_runs_normally) # define ARCH_REGS struct user_regs_struct # define SYSCALL_NUM a7 # define SYSCALL_RET a0 +#elif defined(__csky__) +# define ARCH_REGS struct pt_regs +#if defined(__CSKYABIV2__) +# define SYSCALL_NUM regs[3] +#else +# define SYSCALL_NUM regs[9] +#endif +# define SYSCALL_RET a0 #elif defined(__hppa__) # define ARCH_REGS struct user_regs_struct # define SYSCALL_NUM gr[20] @@ -1693,7 +1703,8 @@ void change_syscall(struct __test_metadata *_metadata, EXPECT_EQ(0, ret) {} #if defined(__x86_64__) || defined(__i386__) || defined(__powerpc__) || \ - defined(__s390__) || defined(__hppa__) || defined(__riscv) + defined(__s390__) || defined(__hppa__) || defined(__riscv) || \ + defined(__csky__) { regs.SYSCALL_NUM = syscall; } -- cgit v1.2.3 From 71e193d7cbcfc988c3802e15261bd807171adb6b Mon Sep 17 00:00:00 2001 From: Guo Ren Date: Tue, 28 Jul 2020 16:30:46 +0000 Subject: csky: Add support for function error injection Inspired by the commit 42d038c4fb00 ("arm64: Add support for function error injection"), this patch supports function error injection for csky. This patch mainly support two functions: one is regs_set_return_value() which is used to overwrite the return value; the another function is override_function_with_return() which is to override the probed function returning and jump to its caller. Test log: cd /sys/kernel/debug/fail_function/ echo sys_clone > inject echo 100 > probability echo 1 > interval ls / [ 108.644163] FAULT_INJECTION: forcing a failure. [ 108.644163] name fail_function, interval 1, probability 100, space 0, times 1 [ 108.647799] CPU: 0 PID: 104 Comm: sh Not tainted 5.8.0-rc5+ #46 [ 108.648384] Call Trace: [ 108.649339] [<8005eed4>] walk_stackframe+0x0/0xf0 [ 108.649679] [<8005f16a>] show_stack+0x32/0x5c [ 108.649927] [<8040f9d2>] dump_stack+0x6e/0x9c [ 108.650271] [<80406f7e>] should_fail+0x15e/0x1ac [ 108.650720] [<80118ba8>] fei_kprobe_handler+0x28/0x5c [ 108.651519] [<80754110>] kprobe_breakpoint_handler+0x144/0x1cc [ 108.652289] [<8005d6da>] trap_c+0x8e/0x110 [ 108.652816] [<8005ce8c>] csky_trap+0x5c/0x70 -sh: can't fork: Invalid argument Signed-off-by: Guo Ren Cc: Arnd Bergmann --- arch/csky/Kconfig | 1 + arch/csky/include/asm/ptrace.h | 6 ++++++ arch/csky/lib/Makefile | 1 + arch/csky/lib/error-inject.c | 10 ++++++++++ 4 files changed, 18 insertions(+) create mode 100644 arch/csky/lib/error-inject.c (limited to 'arch/csky/include') diff --git a/arch/csky/Kconfig b/arch/csky/Kconfig index 822362d0598e..c51f64c14391 100644 --- a/arch/csky/Kconfig +++ b/arch/csky/Kconfig @@ -45,6 +45,7 @@ config CSKY select HAVE_DYNAMIC_FTRACE_WITH_REGS select HAVE_FUNCTION_TRACER select HAVE_FUNCTION_GRAPH_TRACER + select HAVE_FUNCTION_ERROR_INJECTION select HAVE_FTRACE_MCOUNT_RECORD select HAVE_KERNEL_GZIP select HAVE_KERNEL_LZO diff --git a/arch/csky/include/asm/ptrace.h b/arch/csky/include/asm/ptrace.h index bcfb7070e48d..82da5e08558d 100644 --- a/arch/csky/include/asm/ptrace.h +++ b/arch/csky/include/asm/ptrace.h @@ -52,6 +52,12 @@ static inline unsigned long regs_return_value(struct pt_regs *regs) return regs->a0; } +static inline void regs_set_return_value(struct pt_regs *regs, + unsigned long val) +{ + regs->a0 = val; +} + /* Valid only for Kernel mode traps. */ static inline unsigned long kernel_stack_pointer(struct pt_regs *regs) { diff --git a/arch/csky/lib/Makefile b/arch/csky/lib/Makefile index 078e2d5f32e1..7fbdbb2c4d12 100644 --- a/arch/csky/lib/Makefile +++ b/arch/csky/lib/Makefile @@ -1,2 +1,3 @@ # SPDX-License-Identifier: GPL-2.0-only lib-y := usercopy.o delay.o +obj-$(CONFIG_FUNCTION_ERROR_INJECTION) += error-inject.o diff --git a/arch/csky/lib/error-inject.c b/arch/csky/lib/error-inject.c new file mode 100644 index 000000000000..c15fb36fe067 --- /dev/null +++ b/arch/csky/lib/error-inject.c @@ -0,0 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include +#include + +void override_function_with_return(struct pt_regs *regs) +{ + instruction_pointer_set(regs, regs->lr); +} +NOKPROBE_SYMBOL(override_function_with_return); -- cgit v1.2.3 From 5bc46ce26cfc42fa066b2206621587f9dea9a8a8 Mon Sep 17 00:00:00 2001 From: Guo Ren Date: Thu, 30 Jul 2020 11:09:51 +0000 Subject: 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 Cc: Arnd Bergmann --- arch/csky/include/asm/bug.h | 3 +- arch/csky/include/asm/ptrace.h | 1 + arch/csky/kernel/ptrace.c | 29 +----- arch/csky/kernel/traps.c | 223 +++++++++++++++++++++++++++-------------- arch/csky/mm/fault.c | 10 +- 5 files changed, 157 insertions(+), 109 deletions(-) (limited to 'arch/csky/include') diff --git a/arch/csky/include/asm/bug.h b/arch/csky/include/asm/bug.h index bd7b3235bb84..33ebd16b9c78 100644 --- a/arch/csky/include/asm/bug.h +++ b/arch/csky/include/asm/bug.h @@ -20,7 +20,8 @@ do { \ struct pt_regs; -void die_if_kernel(char *str, struct pt_regs *regs, int nr); +void die(struct pt_regs *regs, const char *str); void show_regs(struct pt_regs *regs); +void show_code(struct pt_regs *regs); #endif /* __ASM_CSKY_BUG_H */ diff --git a/arch/csky/include/asm/ptrace.h b/arch/csky/include/asm/ptrace.h index 82da5e08558d..91ceb1b454c9 100644 --- a/arch/csky/include/asm/ptrace.h +++ b/arch/csky/include/asm/ptrace.h @@ -24,6 +24,7 @@ #define user_mode(regs) (!((regs)->sr & PS_S)) #define instruction_pointer(regs) ((regs)->pc) #define profile_pc(regs) instruction_pointer(regs) +#define trap_no(regs) ((regs->sr >> 16) & 0xff) static inline void instruction_pointer_set(struct pt_regs *regs, unsigned long val) diff --git a/arch/csky/kernel/ptrace.c b/arch/csky/kernel/ptrace.c index 0de10f7beae6..b06612c408c4 100644 --- a/arch/csky/kernel/ptrace.c +++ b/arch/csky/kernel/ptrace.c @@ -347,13 +347,8 @@ asmlinkage void syscall_trace_exit(struct pt_regs *regs) trace_sys_exit(regs, syscall_get_return_value(current, regs)); } -extern void show_stack(struct task_struct *task, unsigned long *stack, const char *loglvl); void show_regs(struct pt_regs *fp) { - unsigned long *sp; - unsigned char *tp; - int i; - pr_info("\nCURRENT PROCESS:\n\n"); pr_info("COMM=%s PID=%d\n", current->comm, current->pid); @@ -400,29 +395,9 @@ void show_regs(struct pt_regs *fp) fp->regs[0], fp->regs[1], fp->regs[2], fp->regs[3]); pr_info("r10: 0x%08lx r11: 0x%08lx r12: 0x%08lx r13: 0x%08lx\n", fp->regs[4], fp->regs[5], fp->regs[6], fp->regs[7]); - pr_info("r14: 0x%08lx r1: 0x%08lx r15: 0x%08lx\n", - fp->regs[8], fp->regs[9], fp->lr); + pr_info("r14: 0x%08lx r1: 0x%08lx\n", + fp->regs[8], fp->regs[9]); #endif - pr_info("\nCODE:"); - tp = ((unsigned char *) fp->pc) - 0x20; - tp += ((int)tp % 4) ? 2 : 0; - for (sp = (unsigned long *) tp, i = 0; (i < 0x40); i += 4) { - if ((i % 0x10) == 0) - pr_cont("\n%08x: ", (int) (tp + i)); - pr_cont("%08x ", (int) *sp++); - } - pr_cont("\n"); - - pr_info("\nKERNEL STACK:"); - tp = ((unsigned char *) fp) - 0x40; - for (sp = (unsigned long *) tp, i = 0; (i < 0xc0); i += 4) { - if ((i % 0x10) == 0) - pr_cont("\n%08x: ", (int) (tp + i)); - pr_cont("%08x ", (int) *sp++); - } - pr_cont("\n"); - - show_stack(NULL, (unsigned long *)fp->regs[4], KERN_INFO); return; } diff --git a/arch/csky/kernel/traps.c b/arch/csky/kernel/traps.c index fcc3a69831ad..959a917c989d 100644 --- a/arch/csky/kernel/traps.c +++ b/arch/csky/kernel/traps.c @@ -15,6 +15,8 @@ #include #include #include +#include +#include #include #include @@ -27,6 +29,8 @@ #include #endif +int show_unhandled_signals = 1; + /* Defined in entry.S */ asmlinkage void csky_trap(void); @@ -77,117 +81,184 @@ void __init trap_init(void) #endif } -void die_if_kernel(char *str, struct pt_regs *regs, int nr) +static DEFINE_SPINLOCK(die_lock); + +void die(struct pt_regs *regs, const char *str) { - if (user_mode(regs)) - return; + static int die_counter; + int ret; + oops_enter(); + + spin_lock_irq(&die_lock); console_verbose(); - pr_err("%s: %08x\n", str, nr); + bust_spinlocks(1); + + pr_emerg("%s [#%d]\n", str, ++die_counter); + print_modules(); show_regs(regs); + show_stack(current, (unsigned long *)regs->regs[4], KERN_INFO); + + ret = notify_die(DIE_OOPS, str, regs, 0, trap_no(regs), SIGSEGV); + + bust_spinlocks(0); add_taint(TAINT_DIE, LOCKDEP_NOW_UNRELIABLE); - do_exit(SIGSEGV); + spin_unlock_irq(&die_lock); + oops_exit(); + + if (in_interrupt()) + panic("Fatal exception in interrupt"); + if (panic_on_oops) + panic("Fatal exception"); + if (ret != NOTIFY_STOP) + do_exit(SIGSEGV); } -void buserr(struct pt_regs *regs) +void do_trap(struct pt_regs *regs, int signo, int code, unsigned long addr) { -#ifdef CONFIG_CPU_CK810 - static unsigned long prev_pc; + struct task_struct *tsk = current; - if ((regs->pc == prev_pc) && prev_pc != 0) { - prev_pc = 0; - } else { - prev_pc = regs->pc; - return; + if (show_unhandled_signals && unhandled_signal(tsk, signo) + && printk_ratelimit()) { + pr_info("%s[%d]: unhandled signal %d code 0x%x at 0x%08lx", + tsk->comm, task_pid_nr(tsk), signo, code, addr); + print_vma_addr(KERN_CONT " in ", instruction_pointer(regs)); + pr_cont("\n"); + show_regs(regs); } -#endif - die_if_kernel("Kernel mode BUS error", regs, 0); + force_sig_fault(signo, code, (void __user *)addr); +} - pr_err("User mode Bus Error\n"); - show_regs(regs); +static void do_trap_error(struct pt_regs *regs, int signo, int code, + unsigned long addr, const char *str) +{ + current->thread.trap_no = trap_no(regs); - force_sig_fault(SIGSEGV, 0, (void __user *)regs->pc); + if (user_mode(regs)) { + do_trap(regs, signo, code, addr); + } else { + if (!fixup_exception(regs)) + die(regs, str); + } } -asmlinkage void trap_c(struct pt_regs *regs) -{ - int sig; - unsigned long vector; - siginfo_t info; - struct task_struct *tsk = current; +#define DO_ERROR_INFO(name, signo, code, str) \ +asmlinkage __visible void name(struct pt_regs *regs) \ +{ \ + do_trap_error(regs, signo, code, regs->pc, "Oops - " str); \ +} - vector = (regs->sr >> 16) & 0xff; +DO_ERROR_INFO(do_trap_unknown, + SIGILL, ILL_ILLTRP, "unknown exception"); +DO_ERROR_INFO(do_trap_zdiv, + SIGFPE, FPE_INTDIV, "error zero div exception"); +DO_ERROR_INFO(do_trap_buserr, + SIGSEGV, ILL_ILLADR, "error bus error exception"); - switch (vector) { - case VEC_ZERODIV: - die_if_kernel("Kernel mode ZERO DIV", regs, vector); - sig = SIGFPE; - break; - /* ptrace */ - case VEC_TRACE: +asmlinkage void do_trap_misaligned(struct pt_regs *regs) +{ +#ifdef CONFIG_CPU_NEED_SOFTALIGN + csky_alignment(regs); +#else + current->thread.trap_no = trap_no(regs); + do_trap_error(regs, SIGBUS, BUS_ADRALN, regs->pc, + "Oops - load/store address misaligned"); +#endif +} + +asmlinkage void do_trap_bkpt(struct pt_regs *regs) +{ #ifdef CONFIG_KPROBES - if (kprobe_single_step_handler(regs)) - return; + if (kprobe_single_step_handler(regs)) + return; #endif #ifdef CONFIG_UPROBES - if (uprobe_single_step_handler(regs)) - return; + if (uprobe_single_step_handler(regs)) + return; #endif - info.si_code = TRAP_TRACE; - sig = SIGTRAP; - break; - case VEC_ILLEGAL: - tsk->thread.trap_no = vector; + if (user_mode(regs)) { + send_sig(SIGTRAP, current, 0); + return; + } + + do_trap_error(regs, SIGILL, ILL_ILLTRP, regs->pc, + "Oops - illegal trap exception"); +} + +asmlinkage void do_trap_illinsn(struct pt_regs *regs) +{ + current->thread.trap_no = trap_no(regs); + #ifdef CONFIG_KPROBES - if (kprobe_breakpoint_handler(regs)) - return; + if (kprobe_breakpoint_handler(regs)) + return; #endif #ifdef CONFIG_UPROBES - if (uprobe_breakpoint_handler(regs)) - return; + if (uprobe_breakpoint_handler(regs)) + return; #endif - die_if_kernel("Kernel mode ILLEGAL", regs, vector); #ifndef CONFIG_CPU_NO_USER_BKPT - if (*(uint16_t *)instruction_pointer(regs) != USR_BKPT) + if (*(uint16_t *)instruction_pointer(regs) != USR_BKPT) { + send_sig(SIGTRAP, current, 0); + return; + } #endif - { - sig = SIGILL; - break; - } - /* gdbserver breakpoint */ + + do_trap_error(regs, SIGILL, ILL_ILLOPC, regs->pc, + "Oops - illegal instruction exception"); +} + +asmlinkage void do_trap_fpe(struct pt_regs *regs) +{ +#ifdef CONFIG_CPU_HAS_FP + return fpu_fpe(regs); +#else + do_trap_error(regs, SIGILL, ILL_ILLOPC, regs->pc, + "Oops - fpu instruction exception"); +#endif +} + +asmlinkage void do_trap_priv(struct pt_regs *regs) +{ +#ifdef CONFIG_CPU_HAS_FP + if (user_mode(regs) && fpu_libc_helper(regs)) + return; +#endif + do_trap_error(regs, SIGILL, ILL_PRVOPC, regs->pc, + "Oops - illegal privileged exception"); +} + +asmlinkage void trap_c(struct pt_regs *regs) +{ + switch (trap_no(regs)) { + case VEC_ZERODIV: + do_trap_zdiv(regs); + break; + case VEC_TRACE: + do_trap_bkpt(regs); + break; + case VEC_ILLEGAL: + do_trap_illinsn(regs); + break; case VEC_TRAP1: - /* jtagserver breakpoint */ case VEC_BREAKPOINT: - die_if_kernel("Kernel mode BKPT", regs, vector); - info.si_code = TRAP_BRKPT; - sig = SIGTRAP; + do_trap_bkpt(regs); break; case VEC_ACCESS: - tsk->thread.trap_no = vector; - return buserr(regs); -#ifdef CONFIG_CPU_NEED_SOFTALIGN + do_trap_buserr(regs); + break; case VEC_ALIGN: - tsk->thread.trap_no = vector; - return csky_alignment(regs); -#endif -#ifdef CONFIG_CPU_HAS_FPU + do_trap_misaligned(regs); + break; case VEC_FPE: - tsk->thread.trap_no = vector; - die_if_kernel("Kernel mode FPE", regs, vector); - return fpu_fpe(regs); + do_trap_fpe(regs); + break; case VEC_PRIV: - tsk->thread.trap_no = vector; - die_if_kernel("Kernel mode PRIV", regs, vector); - if (fpu_libc_helper(regs)) - return; -#endif + do_trap_priv(regs); + break; default: - sig = SIGSEGV; + do_trap_unknown(regs); break; } - - tsk->thread.trap_no = vector; - - send_sig(sig, current, 0); } diff --git a/arch/csky/mm/fault.c b/arch/csky/mm/fault.c index 0b9cbf2cf6a9..b1dce9f2f04d 100644 --- a/arch/csky/mm/fault.c +++ b/arch/csky/mm/fault.c @@ -183,13 +183,13 @@ bad_area: bad_area_nosemaphore: /* User mode accesses just cause a SIGSEGV */ if (user_mode(regs)) { - tsk->thread.trap_no = (regs->sr >> 16) & 0xff; + tsk->thread.trap_no = trap_no(regs); force_sig_fault(SIGSEGV, si_code, (void __user *)address); return; } no_context: - tsk->thread.trap_no = (regs->sr >> 16) & 0xff; + tsk->thread.trap_no = trap_no(regs); /* Are we prepared to handle this kernel fault? */ if (fixup_exception(regs)) @@ -202,10 +202,10 @@ no_context: bust_spinlocks(1); pr_alert("Unable to handle kernel paging request at virtual " "address 0x%08lx, pc: 0x%08lx\n", address, regs->pc); - die_if_kernel("Oops", regs, write); + die(regs, "Oops"); out_of_memory: - tsk->thread.trap_no = (regs->sr >> 16) & 0xff; + tsk->thread.trap_no = trap_no(regs); /* * We ran out of memory, call the OOM killer, and return the userspace @@ -215,7 +215,7 @@ out_of_memory: return; do_sigbus: - tsk->thread.trap_no = (regs->sr >> 16) & 0xff; + tsk->thread.trap_no = trap_no(regs); mmap_read_unlock(mm); -- cgit v1.2.3 From 2c81b0768297fb2fb4d2f39eac49a55f3598375b Mon Sep 17 00:00:00 2001 From: Guo Ren Date: Thu, 30 Jul 2020 17:05:51 +0000 Subject: csky: Add irq_work support Running work in hardware interrupt context for csky. Implement: - arch_irq_work_raise() - arch_irq_work_has_interrupt() Signed-off-by: Guo Ren Cc: Arnd Bergmann --- arch/csky/include/asm/irq_work.h | 11 +++++++++++ arch/csky/kernel/smp.c | 12 ++++++++++++ 2 files changed, 23 insertions(+) create mode 100644 arch/csky/include/asm/irq_work.h (limited to 'arch/csky/include') diff --git a/arch/csky/include/asm/irq_work.h b/arch/csky/include/asm/irq_work.h new file mode 100644 index 000000000000..33aaf39d6f94 --- /dev/null +++ b/arch/csky/include/asm/irq_work.h @@ -0,0 +1,11 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +#ifndef __ASM_CSKY_IRQ_WORK_H +#define __ASM_CSKY_IRQ_WORK_H + +static inline bool arch_irq_work_has_interrupt(void) +{ + return true; +} +extern void arch_irq_work_raise(void); +#endif /* __ASM_CSKY_IRQ_WORK_H */ diff --git a/arch/csky/kernel/smp.c b/arch/csky/kernel/smp.c index 1945fb29007d..60f2ab1c5865 100644 --- a/arch/csky/kernel/smp.c +++ b/arch/csky/kernel/smp.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -35,6 +36,7 @@ enum ipi_message_type { IPI_EMPTY, IPI_RESCHEDULE, IPI_CALL_FUNC, + IPI_IRQ_WORK, IPI_MAX }; @@ -53,6 +55,9 @@ static irqreturn_t handle_ipi(int irq, void *dev) if (ops & (1 << IPI_CALL_FUNC)) generic_smp_call_function_interrupt(); + if (ops & (1 << IPI_IRQ_WORK)) + irq_work_run(); + BUG_ON((ops >> IPI_MAX) != 0); } @@ -108,6 +113,13 @@ void smp_send_reschedule(int cpu) send_ipi_message(cpumask_of(cpu), IPI_RESCHEDULE); } +#ifdef CONFIG_IRQ_WORK +void arch_irq_work_raise(void) +{ + send_ipi_message(cpumask_of(smp_processor_id()), IPI_IRQ_WORK); +} +#endif + void __init smp_prepare_boot_cpu(void) { } -- cgit v1.2.3