Commit 2044513f authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'csky-for-linus-5.9-rc1' of https://github.com/c-sky/csky-linux

Pull arch/csky updates from Guo Ren:
 "New features:
   - seccomp-filter
   - err-injection
   - top-down&random mmap-layout
   - irq_work
   - show_ipi
   - context-tracking

  Fixes & Optimizations:
   - kprobe_on_ftrace
   - optimize panic print"

* tag 'csky-for-linus-5.9-rc1' of https://github.com/c-sky/csky-linux:
  csky: Add context tracking support
  csky: Add arch_show_interrupts for IPI interrupts
  csky: Add irq_work support
  csky: Fixup warning by EXPORT_SYMBOL(kmap)
  csky: Set CONFIG_NR_CPU 4 as default
  csky: Use top-down mmap layout
  csky: Optimize the trap processing flow
  csky: Add support for function error injection
  csky: Fixup kprobes handler couldn't change pc
  csky: Fixup duplicated restore sp in RESTORE_REGS_FTRACE
  csky: Add cpu feature register hint for smp
  csky: Add SECCOMP_FILTER supported
  csky: remove unusued thread_saved_pc and *_segments functions/macros
parents bbcf9cd1 bdcd93ef
......@@ -9,6 +9,7 @@ config CSKY
select ARCH_USE_BUILTIN_BSWAP
select ARCH_USE_QUEUED_RWLOCKS if NR_CPUS>2
select ARCH_WANT_FRAME_POINTERS if !CPU_CK610
select ARCH_WANT_DEFAULT_TOPDOWN_MMAP_LAYOUT
select COMMON_CLK
select CLKSRC_MMIO
select CSKY_MPINTC if CPU_CK860
......@@ -38,11 +39,16 @@ config CSKY
select GX6605S_TIMER if CPU_CK610
select HAVE_ARCH_TRACEHOOK
select HAVE_ARCH_AUDITSYSCALL
select HAVE_ARCH_MMAP_RND_BITS
select HAVE_ARCH_SECCOMP_FILTER
select HAVE_CONTEXT_TRACKING
select HAVE_VIRT_CPU_ACCOUNTING_GEN
select HAVE_DEBUG_BUGVERBOSE
select HAVE_DYNAMIC_FTRACE
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
......@@ -148,6 +154,14 @@ config L1_CACHE_SHIFT
default "5" if (CPU_CK807 || CPU_CK810)
default "6" if (CPU_CK860)
config ARCH_MMAP_RND_BITS_MIN
default 8
# max bits determined by the following formula:
# VA_BITS - PAGE_SHIFT - 3
config ARCH_MMAP_RND_BITS_MAX
default 17
menu "Processor type and features"
choice
......@@ -266,7 +280,7 @@ config NR_CPUS
int "Maximum number of CPUs (2-32)"
range 2 32
depends on SMP
default "2"
default "4"
config HIGHMEM
bool "High Memory Support"
......@@ -295,3 +309,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.
......@@ -136,8 +136,6 @@
.macro RESTORE_REGS_FTRACE
ldw tls, (sp, 0)
ldw a0, (sp, 16)
mtcr a0, ss0
#ifdef CONFIG_CPU_HAS_HILO
ldw a0, (sp, 140)
......@@ -158,7 +156,6 @@
addi sp, 40
ldm r16-r30, (sp)
addi sp, 72
mfcr sp, ss0
.endm
.macro SAVE_SWITCH_STACK
......
......@@ -55,7 +55,9 @@
.macro mcount_exit_regs
RESTORE_REGS_FTRACE
ldw t1, (sp, 0)
subi sp, 152
ldw t1, (sp, 4)
addi sp, 152
ldw r8, (sp, 4)
ldw lr, (sp, 8)
addi sp, 12
......
......@@ -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
......@@ -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 */
/* 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 */
......@@ -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)
......
......@@ -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)
......@@ -52,6 +53,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)
{
......
......@@ -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 */
......@@ -23,6 +23,24 @@
#endif
.endm
.macro context_tracking
#ifdef CONFIG_CONTEXT_TRACKING
mfcr a0, epsr
btsti a0, 31
bt 1f
jbsr context_tracking_user_exit
ldw a0, (sp, LSAVE_A0)
ldw a1, (sp, LSAVE_A1)
ldw a2, (sp, LSAVE_A2)
ldw a3, (sp, LSAVE_A3)
#if defined(__CSKYABIV1__)
ldw r6, (sp, LSAVE_A4)
ldw r7, (sp, LSAVE_A5)
#endif
1:
#endif
.endm
.macro tlbop_begin name, val0, val1, val2
ENTRY(csky_\name)
mtcr a3, ss2
......@@ -103,6 +121,7 @@ ENTRY(csky_\name)
.endm
.macro tlbop_end is_write
zero_fp
context_tracking
RD_MEH a2
psrset ee, ie
mov a0, sp
......@@ -128,6 +147,7 @@ tlbop_end 1
ENTRY(csky_systemcall)
SAVE_ALL TRAP0_SIZE
zero_fp
context_tracking
psrset ee, ie
lrw r9, __NR_syscalls
......@@ -168,6 +188,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 +210,7 @@ csky_syscall_trace:
#endif
stw a0, (sp, LSAVE_A0) /* Save return value */
1:
#ifdef CONFIG_DEBUG_RSEQ
mov a0, sp
jbsr rseq_syscall
......@@ -234,6 +257,9 @@ ret_from_exception:
and r10, r9
cmpnei r10, 0
bt exit_work
#ifdef CONFIG_CONTEXT_TRACKING
jbsr context_tracking_user_enter
#endif
1:
#ifdef CONFIG_PREEMPTION
mov r9, sp
......@@ -274,6 +300,7 @@ work_resched:
ENTRY(csky_trap)
SAVE_ALL 0
zero_fp
context_tracking
psrset ee
mov a0, sp /* Push Stack pointer arg */
jbsr trap_c /* Call C-level trap handler */
......@@ -308,6 +335,7 @@ ENTRY(csky_get_tls)
ENTRY(csky_irq)
SAVE_ALL 0
zero_fp
context_tracking
psrset ee
#ifdef CONFIG_TRACE_IRQFLAGS
......
......@@ -30,16 +30,6 @@ asmlinkage void ret_from_kernel_thread(void);
*/
void flush_thread(void){}
/*
* Return saved PC from a blocked thread
*/
unsigned long thread_saved_pc(struct task_struct *tsk)
{
struct switch_stack *sw = (struct switch_stack *)tsk->thread.sp;
return sw->r15;
}
int copy_thread(unsigned long clone_flags,
unsigned long usp,
unsigned long kthread_arg,
......
......@@ -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)
......@@ -343,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);
......@@ -396,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;
}
......@@ -12,8 +12,10 @@
#include <linux/delay.h>
#include <linux/err.h>
#include <linux/irq.h>
#include <linux/irq_work.h>
#include <linux/irqdomain.h>
#include <linux/of.h>
#include <linux/seq_file.h>
#include <linux/sched/task_stack.h>
#include <linux/sched/mm.h>
#include <linux/sched/hotplug.h>
......@@ -26,20 +28,24 @@
#include <abi/fpu.h>
#endif
struct ipi_data_struct {
unsigned long bits ____cacheline_aligned;
};
static DEFINE_PER_CPU(struct ipi_data_struct, ipi_data);
enum ipi_message_type {
IPI_EMPTY,
IPI_RESCHEDULE,
IPI_CALL_FUNC,
IPI_IRQ_WORK,
IPI_MAX
};
struct ipi_data_struct {
unsigned long bits ____cacheline_aligned;
unsigned long stats[IPI_MAX] ____cacheline_aligned;
};
static DEFINE_PER_CPU(struct ipi_data_struct, ipi_data);
static irqreturn_t handle_ipi(int irq, void *dev)
{
unsigned long *stats = this_cpu_ptr(&ipi_data)->stats;
while (true) {
unsigned long ops;
......@@ -47,11 +53,20 @@ static irqreturn_t handle_ipi(int irq, void *dev)
if (ops == 0)
return IRQ_HANDLED;
if (ops & (1 << IPI_RESCHEDULE))
if (ops & (1 << IPI_RESCHEDULE)) {
stats[IPI_RESCHEDULE]++;
scheduler_ipi();
}
if (ops & (1 << IPI_CALL_FUNC))
if (ops & (1 << IPI_CALL_FUNC)) {
stats[IPI_CALL_FUNC]++;
generic_smp_call_function_interrupt();
}
if (ops & (1 << IPI_IRQ_WORK)) {
stats[IPI_IRQ_WORK]++;
irq_work_run();
}
BUG_ON((ops >> IPI_MAX) != 0);
}
......@@ -83,6 +98,29 @@ send_ipi_message(const struct cpumask *to_whom, enum ipi_message_type operation)
send_arch_ipi(to_whom);
}
static const char * const ipi_names[] = {
[IPI_EMPTY] = "Empty interrupts",
[IPI_RESCHEDULE] = "Rescheduling interrupts",
[IPI_CALL_FUNC] = "Function call interrupts",
[IPI_IRQ_WORK] = "Irq work interrupts",
};
int arch_show_interrupts(struct seq_file *p, int prec)
{
unsigned int cpu, i;
for (i = 0; i < IPI_MAX; i++) {
seq_printf(p, "%*s%u:%s", prec - 1, "IPI", i,
prec >= 4 ? " " : "");
for_each_online_cpu(cpu)
seq_printf(p, "%10lu ",
per_cpu_ptr(&ipi_data, cpu)->stats[i]);
seq_printf(p, " %s\n", ipi_names[i]);
}
return 0;
}
void arch_send_call_function_ipi_mask(struct cpumask *mask)
{
send_ipi_message(mask, IPI_CALL_FUNC);
......@@ -108,6 +146,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)
{
}
......@@ -156,6 +201,7 @@ void __init setup_smp(void)
extern void _start_smp_secondary(void);
volatile unsigned int secondary_hint;
volatile unsigned int secondary_hint2;
volatile unsigned int secondary_ccr;
volatile unsigned int secondary_stack;
......@@ -168,6 +214,7 @@ int __cpu_up(unsigned int cpu, struct task_struct *tidle)
secondary_stack =
(unsigned int) task_stack_page(tidle) + THREAD_SIZE - 8;
secondary_hint = mfcr("cr31");
secondary_hint2 = mfcr("cr<21, 1>");
secondary_ccr = mfcr("cr18");
secondary_msa1 = read_mmu_msa1();
......@@ -209,6 +256,7 @@ void csky_start_secondary(void)
unsigned int cpu = smp_processor_id();
mtcr("cr31", secondary_hint);
mtcr("cr<21, 1>", secondary_hint2);
mtcr("cr18", secondary_ccr);
mtcr("vbr", vec_base);
......
......@@ -15,6 +15,8 @@
#include <linux/rtc.h>
#include <linux/uaccess.h>
#include <linux/kprobes.h>
#include <linux/kdebug.h>
#include <linux/sched/debug.h>
#include <asm/setup.h>
#include <asm/traps.h>
......@@ -27,6 +29,8 @@
#include <abi/fpu.h>
#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);
}
# SPDX-License-Identifier: GPL-2.0-only
lib-y := usercopy.o delay.o
obj-$(CONFIG_FUNCTION_ERROR_INJECTION) += error-inject.o
// SPDX-License-Identifier: GPL-2.0
#include <linux/error-injection.h>
#include <linux/kprobes.h>
void override_function_with_return(struct pt_regs *regs)
{
instruction_pointer_set(regs, regs->lr);
}
NOKPROBE_SYMBOL(override_function_with_return);
......@@ -183,13 +183,13 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long write,
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 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long write,
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 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long write,
return;
do_sigbus:
tsk->thread.trap_no = (regs->sr >> 16) & 0xff;
tsk->thread.trap_no = trap_no(regs);
mmap_read_unlock(mm);
......
......@@ -19,8 +19,6 @@ void kmap_flush_tlb(unsigned long addr)
}
EXPORT_SYMBOL(kmap_flush_tlb);
EXPORT_SYMBOL(kmap);
void *kmap_atomic_high_prot(struct page *page, pgprot_t prot)
{
unsigned long vaddr;
......
......@@ -123,6 +123,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__)
......@@ -1682,6 +1684,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]
......@@ -1781,7 +1791,7 @@ void change_syscall(struct __test_metadata *_metadata,
#if defined(__x86_64__) || defined(__i386__) || defined(__powerpc__) || \
defined(__s390__) || defined(__hppa__) || defined(__riscv) || \
defined(__xtensa__)
defined(__xtensa__) || defined(__csky__)
{
regs.SYSCALL_NUM = syscall;
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment