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 ...@@ -9,6 +9,7 @@ config CSKY
select ARCH_USE_BUILTIN_BSWAP select ARCH_USE_BUILTIN_BSWAP
select ARCH_USE_QUEUED_RWLOCKS if NR_CPUS>2 select ARCH_USE_QUEUED_RWLOCKS if NR_CPUS>2
select ARCH_WANT_FRAME_POINTERS if !CPU_CK610 select ARCH_WANT_FRAME_POINTERS if !CPU_CK610
select ARCH_WANT_DEFAULT_TOPDOWN_MMAP_LAYOUT
select COMMON_CLK select COMMON_CLK
select CLKSRC_MMIO select CLKSRC_MMIO
select CSKY_MPINTC if CPU_CK860 select CSKY_MPINTC if CPU_CK860
...@@ -38,11 +39,16 @@ config CSKY ...@@ -38,11 +39,16 @@ config CSKY
select GX6605S_TIMER if CPU_CK610 select GX6605S_TIMER if CPU_CK610
select HAVE_ARCH_TRACEHOOK select HAVE_ARCH_TRACEHOOK
select HAVE_ARCH_AUDITSYSCALL 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_DEBUG_BUGVERBOSE
select HAVE_DYNAMIC_FTRACE select HAVE_DYNAMIC_FTRACE
select HAVE_DYNAMIC_FTRACE_WITH_REGS select HAVE_DYNAMIC_FTRACE_WITH_REGS
select HAVE_FUNCTION_TRACER select HAVE_FUNCTION_TRACER
select HAVE_FUNCTION_GRAPH_TRACER select HAVE_FUNCTION_GRAPH_TRACER
select HAVE_FUNCTION_ERROR_INJECTION
select HAVE_FTRACE_MCOUNT_RECORD select HAVE_FTRACE_MCOUNT_RECORD
select HAVE_KERNEL_GZIP select HAVE_KERNEL_GZIP
select HAVE_KERNEL_LZO select HAVE_KERNEL_LZO
...@@ -148,6 +154,14 @@ config L1_CACHE_SHIFT ...@@ -148,6 +154,14 @@ config L1_CACHE_SHIFT
default "5" if (CPU_CK807 || CPU_CK810) default "5" if (CPU_CK807 || CPU_CK810)
default "6" if (CPU_CK860) 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" menu "Processor type and features"
choice choice
...@@ -266,7 +280,7 @@ config NR_CPUS ...@@ -266,7 +280,7 @@ config NR_CPUS
int "Maximum number of CPUs (2-32)" int "Maximum number of CPUs (2-32)"
range 2 32 range 2 32
depends on SMP depends on SMP
default "2" default "4"
config HIGHMEM config HIGHMEM
bool "High Memory Support" bool "High Memory Support"
...@@ -295,3 +309,16 @@ endmenu ...@@ -295,3 +309,16 @@ endmenu
source "arch/csky/Kconfig.platforms" source "arch/csky/Kconfig.platforms"
source "kernel/Kconfig.hz" 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 @@ ...@@ -136,8 +136,6 @@
.macro RESTORE_REGS_FTRACE .macro RESTORE_REGS_FTRACE
ldw tls, (sp, 0) ldw tls, (sp, 0)
ldw a0, (sp, 16)
mtcr a0, ss0
#ifdef CONFIG_CPU_HAS_HILO #ifdef CONFIG_CPU_HAS_HILO
ldw a0, (sp, 140) ldw a0, (sp, 140)
...@@ -158,7 +156,6 @@ ...@@ -158,7 +156,6 @@
addi sp, 40 addi sp, 40
ldm r16-r30, (sp) ldm r16-r30, (sp)
addi sp, 72 addi sp, 72
mfcr sp, ss0
.endm .endm
.macro SAVE_SWITCH_STACK .macro SAVE_SWITCH_STACK
......
...@@ -55,7 +55,9 @@ ...@@ -55,7 +55,9 @@
.macro mcount_exit_regs .macro mcount_exit_regs
RESTORE_REGS_FTRACE RESTORE_REGS_FTRACE
ldw t1, (sp, 0) subi sp, 152
ldw t1, (sp, 4)
addi sp, 152
ldw r8, (sp, 4) ldw r8, (sp, 4)
ldw lr, (sp, 8) ldw lr, (sp, 8)
addi sp, 12 addi sp, 12
......
...@@ -4,5 +4,6 @@ generic-y += gpio.h ...@@ -4,5 +4,6 @@ generic-y += gpio.h
generic-y += kvm_para.h generic-y += kvm_para.h
generic-y += local64.h generic-y += local64.h
generic-y += qrwlock.h generic-y += qrwlock.h
generic-y += seccomp.h
generic-y += user.h generic-y += user.h
generic-y += vmlinux.lds.h generic-y += vmlinux.lds.h
...@@ -20,7 +20,8 @@ do { \ ...@@ -20,7 +20,8 @@ do { \
struct pt_regs; 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_regs(struct pt_regs *regs);
void show_code(struct pt_regs *regs);
#endif /* __ASM_CSKY_BUG_H */ #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) ...@@ -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); 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); unsigned long get_wchan(struct task_struct *p);
#define KSTK_EIP(tsk) (task_pt_regs(tsk)->pc) #define KSTK_EIP(tsk) (task_pt_regs(tsk)->pc)
......
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
#define user_mode(regs) (!((regs)->sr & PS_S)) #define user_mode(regs) (!((regs)->sr & PS_S))
#define instruction_pointer(regs) ((regs)->pc) #define instruction_pointer(regs) ((regs)->pc)
#define profile_pc(regs) instruction_pointer(regs) #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, static inline void instruction_pointer_set(struct pt_regs *regs,
unsigned long val) unsigned long val)
...@@ -52,6 +53,12 @@ static inline unsigned long regs_return_value(struct pt_regs *regs) ...@@ -52,6 +53,12 @@ static inline unsigned long regs_return_value(struct pt_regs *regs)
return regs->a0; 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. */ /* Valid only for Kernel mode traps. */
static inline unsigned long kernel_stack_pointer(struct pt_regs *regs) static inline unsigned long kernel_stack_pointer(struct pt_regs *regs)
{ {
......
...@@ -85,6 +85,6 @@ static inline struct thread_info *current_thread_info(void) ...@@ -85,6 +85,6 @@ static inline struct thread_info *current_thread_info(void)
_TIF_NOTIFY_RESUME | _TIF_UPROBE) _TIF_NOTIFY_RESUME | _TIF_UPROBE)
#define _TIF_SYSCALL_WORK (_TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT | \ #define _TIF_SYSCALL_WORK (_TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT | \
_TIF_SYSCALL_TRACEPOINT) _TIF_SYSCALL_TRACEPOINT | _TIF_SECCOMP)
#endif /* _ASM_CSKY_THREAD_INFO_H */ #endif /* _ASM_CSKY_THREAD_INFO_H */
...@@ -23,6 +23,24 @@ ...@@ -23,6 +23,24 @@
#endif #endif
.endm .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 .macro tlbop_begin name, val0, val1, val2
ENTRY(csky_\name) ENTRY(csky_\name)
mtcr a3, ss2 mtcr a3, ss2
...@@ -103,6 +121,7 @@ ENTRY(csky_\name) ...@@ -103,6 +121,7 @@ ENTRY(csky_\name)
.endm .endm
.macro tlbop_end is_write .macro tlbop_end is_write
zero_fp zero_fp
context_tracking
RD_MEH a2 RD_MEH a2
psrset ee, ie psrset ee, ie
mov a0, sp mov a0, sp
...@@ -128,6 +147,7 @@ tlbop_end 1 ...@@ -128,6 +147,7 @@ tlbop_end 1
ENTRY(csky_systemcall) ENTRY(csky_systemcall)
SAVE_ALL TRAP0_SIZE SAVE_ALL TRAP0_SIZE
zero_fp zero_fp
context_tracking
psrset ee, ie psrset ee, ie
lrw r9, __NR_syscalls lrw r9, __NR_syscalls
...@@ -168,6 +188,8 @@ ENTRY(csky_systemcall) ...@@ -168,6 +188,8 @@ ENTRY(csky_systemcall)
csky_syscall_trace: csky_syscall_trace:
mov a0, sp /* sp = pt_regs pointer */ mov a0, sp /* sp = pt_regs pointer */
jbsr syscall_trace_enter jbsr syscall_trace_enter
cmpnei a0, 0
bt 1f
/* Prepare args before do system call */ /* Prepare args before do system call */
ldw a0, (sp, LSAVE_A0) ldw a0, (sp, LSAVE_A0)
ldw a1, (sp, LSAVE_A1) ldw a1, (sp, LSAVE_A1)
...@@ -188,6 +210,7 @@ csky_syscall_trace: ...@@ -188,6 +210,7 @@ csky_syscall_trace:
#endif #endif
stw a0, (sp, LSAVE_A0) /* Save return value */ stw a0, (sp, LSAVE_A0) /* Save return value */
1:
#ifdef CONFIG_DEBUG_RSEQ #ifdef CONFIG_DEBUG_RSEQ
mov a0, sp mov a0, sp
jbsr rseq_syscall jbsr rseq_syscall
...@@ -234,6 +257,9 @@ ret_from_exception: ...@@ -234,6 +257,9 @@ ret_from_exception:
and r10, r9 and r10, r9
cmpnei r10, 0 cmpnei r10, 0
bt exit_work bt exit_work
#ifdef CONFIG_CONTEXT_TRACKING
jbsr context_tracking_user_enter
#endif
1: 1:
#ifdef CONFIG_PREEMPTION #ifdef CONFIG_PREEMPTION
mov r9, sp mov r9, sp
...@@ -274,6 +300,7 @@ work_resched: ...@@ -274,6 +300,7 @@ work_resched:
ENTRY(csky_trap) ENTRY(csky_trap)
SAVE_ALL 0 SAVE_ALL 0
zero_fp zero_fp
context_tracking
psrset ee psrset ee
mov a0, sp /* Push Stack pointer arg */ mov a0, sp /* Push Stack pointer arg */
jbsr trap_c /* Call C-level trap handler */ jbsr trap_c /* Call C-level trap handler */
...@@ -308,6 +335,7 @@ ENTRY(csky_get_tls) ...@@ -308,6 +335,7 @@ ENTRY(csky_get_tls)
ENTRY(csky_irq) ENTRY(csky_irq)
SAVE_ALL 0 SAVE_ALL 0
zero_fp zero_fp
context_tracking
psrset ee psrset ee
#ifdef CONFIG_TRACE_IRQFLAGS #ifdef CONFIG_TRACE_IRQFLAGS
......
...@@ -30,16 +30,6 @@ asmlinkage void ret_from_kernel_thread(void); ...@@ -30,16 +30,6 @@ asmlinkage void ret_from_kernel_thread(void);
*/ */
void flush_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, int copy_thread(unsigned long clone_flags,
unsigned long usp, unsigned long usp,
unsigned long kthread_arg, unsigned long kthread_arg,
......
...@@ -320,16 +320,20 @@ long arch_ptrace(struct task_struct *child, long request, ...@@ -320,16 +320,20 @@ long arch_ptrace(struct task_struct *child, long request,
return ret; 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 (test_thread_flag(TIF_SYSCALL_TRACE))
if (tracehook_report_syscall_entry(regs)) 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)) if (test_thread_flag(TIF_SYSCALL_TRACEPOINT))
trace_sys_enter(regs, syscall_get_nr(current, regs)); trace_sys_enter(regs, syscall_get_nr(current, regs));
audit_syscall_entry(regs_syscallid(regs), regs->a0, regs->a1, regs->a2, regs->a3); 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) asmlinkage void syscall_trace_exit(struct pt_regs *regs)
...@@ -343,13 +347,8 @@ 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)); 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) void show_regs(struct pt_regs *fp)
{ {
unsigned long *sp;
unsigned char *tp;
int i;
pr_info("\nCURRENT PROCESS:\n\n"); pr_info("\nCURRENT PROCESS:\n\n");
pr_info("COMM=%s PID=%d\n", current->comm, current->pid); pr_info("COMM=%s PID=%d\n", current->comm, current->pid);
...@@ -396,29 +395,9 @@ void show_regs(struct pt_regs *fp) ...@@ -396,29 +395,9 @@ void show_regs(struct pt_regs *fp)
fp->regs[0], fp->regs[1], fp->regs[2], fp->regs[3]); 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", 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]); fp->regs[4], fp->regs[5], fp->regs[6], fp->regs[7]);
pr_info("r14: 0x%08lx r1: 0x%08lx r15: 0x%08lx\n", pr_info("r14: 0x%08lx r1: 0x%08lx\n",
fp->regs[8], fp->regs[9], fp->lr); fp->regs[8], fp->regs[9]);
#endif #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; return;
} }
...@@ -12,8 +12,10 @@ ...@@ -12,8 +12,10 @@
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/err.h> #include <linux/err.h>
#include <linux/irq.h> #include <linux/irq.h>
#include <linux/irq_work.h>
#include <linux/irqdomain.h> #include <linux/irqdomain.h>
#include <linux/of.h> #include <linux/of.h>
#include <linux/seq_file.h>
#include <linux/sched/task_stack.h> #include <linux/sched/task_stack.h>
#include <linux/sched/mm.h> #include <linux/sched/mm.h>
#include <linux/sched/hotplug.h> #include <linux/sched/hotplug.h>
...@@ -26,20 +28,24 @@ ...@@ -26,20 +28,24 @@
#include <abi/fpu.h> #include <abi/fpu.h>
#endif #endif
struct ipi_data_struct {
unsigned long bits ____cacheline_aligned;
};
static DEFINE_PER_CPU(struct ipi_data_struct, ipi_data);
enum ipi_message_type { enum ipi_message_type {
IPI_EMPTY, IPI_EMPTY,
IPI_RESCHEDULE, IPI_RESCHEDULE,
IPI_CALL_FUNC, IPI_CALL_FUNC,
IPI_IRQ_WORK,
IPI_MAX 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) static irqreturn_t handle_ipi(int irq, void *dev)
{ {
unsigned long *stats = this_cpu_ptr(&ipi_data)->stats;
while (true) { while (true) {
unsigned long ops; unsigned long ops;
...@@ -47,11 +53,20 @@ static irqreturn_t handle_ipi(int irq, void *dev) ...@@ -47,11 +53,20 @@ static irqreturn_t handle_ipi(int irq, void *dev)
if (ops == 0) if (ops == 0)
return IRQ_HANDLED; return IRQ_HANDLED;
if (ops & (1 << IPI_RESCHEDULE)) if (ops & (1 << IPI_RESCHEDULE)) {
stats[IPI_RESCHEDULE]++;
scheduler_ipi(); scheduler_ipi();
}
if (ops & (1 << IPI_CALL_FUNC)) if (ops & (1 << IPI_CALL_FUNC)) {
stats[IPI_CALL_FUNC]++;
generic_smp_call_function_interrupt(); generic_smp_call_function_interrupt();
}
if (ops & (1 << IPI_IRQ_WORK)) {
stats[IPI_IRQ_WORK]++;
irq_work_run();
}
BUG_ON((ops >> IPI_MAX) != 0); BUG_ON((ops >> IPI_MAX) != 0);
} }
...@@ -83,6 +98,29 @@ send_ipi_message(const struct cpumask *to_whom, enum ipi_message_type operation) ...@@ -83,6 +98,29 @@ send_ipi_message(const struct cpumask *to_whom, enum ipi_message_type operation)
send_arch_ipi(to_whom); 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) void arch_send_call_function_ipi_mask(struct cpumask *mask)
{ {
send_ipi_message(mask, IPI_CALL_FUNC); send_ipi_message(mask, IPI_CALL_FUNC);
...@@ -108,6 +146,13 @@ void smp_send_reschedule(int cpu) ...@@ -108,6 +146,13 @@ void smp_send_reschedule(int cpu)
send_ipi_message(cpumask_of(cpu), IPI_RESCHEDULE); 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) void __init smp_prepare_boot_cpu(void)
{ {
} }
...@@ -156,6 +201,7 @@ void __init setup_smp(void) ...@@ -156,6 +201,7 @@ void __init setup_smp(void)
extern void _start_smp_secondary(void); extern void _start_smp_secondary(void);
volatile unsigned int secondary_hint; volatile unsigned int secondary_hint;
volatile unsigned int secondary_hint2;
volatile unsigned int secondary_ccr; volatile unsigned int secondary_ccr;
volatile unsigned int secondary_stack; volatile unsigned int secondary_stack;
...@@ -168,6 +214,7 @@ int __cpu_up(unsigned int cpu, struct task_struct *tidle) ...@@ -168,6 +214,7 @@ int __cpu_up(unsigned int cpu, struct task_struct *tidle)
secondary_stack = secondary_stack =
(unsigned int) task_stack_page(tidle) + THREAD_SIZE - 8; (unsigned int) task_stack_page(tidle) + THREAD_SIZE - 8;
secondary_hint = mfcr("cr31"); secondary_hint = mfcr("cr31");
secondary_hint2 = mfcr("cr<21, 1>");
secondary_ccr = mfcr("cr18"); secondary_ccr = mfcr("cr18");
secondary_msa1 = read_mmu_msa1(); secondary_msa1 = read_mmu_msa1();
...@@ -209,6 +256,7 @@ void csky_start_secondary(void) ...@@ -209,6 +256,7 @@ void csky_start_secondary(void)
unsigned int cpu = smp_processor_id(); unsigned int cpu = smp_processor_id();
mtcr("cr31", secondary_hint); mtcr("cr31", secondary_hint);
mtcr("cr<21, 1>", secondary_hint2);
mtcr("cr18", secondary_ccr); mtcr("cr18", secondary_ccr);
mtcr("vbr", vec_base); mtcr("vbr", vec_base);
......
...@@ -15,6 +15,8 @@ ...@@ -15,6 +15,8 @@
#include <linux/rtc.h> #include <linux/rtc.h>
#include <linux/uaccess.h> #include <linux/uaccess.h>
#include <linux/kprobes.h> #include <linux/kprobes.h>
#include <linux/kdebug.h>
#include <linux/sched/debug.h>
#include <asm/setup.h> #include <asm/setup.h>
#include <asm/traps.h> #include <asm/traps.h>
...@@ -27,6 +29,8 @@ ...@@ -27,6 +29,8 @@
#include <abi/fpu.h> #include <abi/fpu.h>
#endif #endif
int show_unhandled_signals = 1;
/* Defined in entry.S */ /* Defined in entry.S */
asmlinkage void csky_trap(void); asmlinkage void csky_trap(void);
...@@ -77,55 +81,94 @@ void __init trap_init(void) ...@@ -77,55 +81,94 @@ void __init trap_init(void)
#endif #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)) static int die_counter;
return; int ret;
oops_enter();
spin_lock_irq(&die_lock);
console_verbose(); 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_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); add_taint(TAINT_DIE, LOCKDEP_NOW_UNRELIABLE);
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); 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 struct task_struct *tsk = current;
static unsigned long prev_pc;
if ((regs->pc == prev_pc) && prev_pc != 0) { if (show_unhandled_signals && unhandled_signal(tsk, signo)
prev_pc = 0; && printk_ratelimit()) {
} else { pr_info("%s[%d]: unhandled signal %d code 0x%x at 0x%08lx",
prev_pc = regs->pc; tsk->comm, task_pid_nr(tsk), signo, code, addr);
return; 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"); static void do_trap_error(struct pt_regs *regs, int signo, int code,
show_regs(regs); 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) #define DO_ERROR_INFO(name, signo, code, str) \
{ asmlinkage __visible void name(struct pt_regs *regs) \
int sig; { \
unsigned long vector; do_trap_error(regs, signo, code, regs->pc, "Oops - " str); \
siginfo_t info; }
struct task_struct *tsk = current;
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) { asmlinkage void do_trap_misaligned(struct pt_regs *regs)
case VEC_ZERODIV: {
die_if_kernel("Kernel mode ZERO DIV", regs, vector); #ifdef CONFIG_CPU_NEED_SOFTALIGN
sig = SIGFPE; csky_alignment(regs);
break; #else
/* ptrace */ current->thread.trap_no = trap_no(regs);
case VEC_TRACE: 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 #ifdef CONFIG_KPROBES
if (kprobe_single_step_handler(regs)) if (kprobe_single_step_handler(regs))
return; return;
...@@ -134,11 +177,19 @@ asmlinkage void trap_c(struct pt_regs *regs) ...@@ -134,11 +177,19 @@ asmlinkage void trap_c(struct pt_regs *regs)
if (uprobe_single_step_handler(regs)) if (uprobe_single_step_handler(regs))
return; return;
#endif #endif
info.si_code = TRAP_TRACE; if (user_mode(regs)) {
sig = SIGTRAP; send_sig(SIGTRAP, current, 0);
break; return;
case VEC_ILLEGAL: }
tsk->thread.trap_no = vector;
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 #ifdef CONFIG_KPROBES
if (kprobe_breakpoint_handler(regs)) if (kprobe_breakpoint_handler(regs))
return; return;
...@@ -147,47 +198,67 @@ asmlinkage void trap_c(struct pt_regs *regs) ...@@ -147,47 +198,67 @@ asmlinkage void trap_c(struct pt_regs *regs)
if (uprobe_breakpoint_handler(regs)) if (uprobe_breakpoint_handler(regs))
return; return;
#endif #endif
die_if_kernel("Kernel mode ILLEGAL", regs, vector);
#ifndef CONFIG_CPU_NO_USER_BKPT #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
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 #endif
{ }
sig = SIGILL;
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; break;
}
/* gdbserver breakpoint */
case VEC_TRAP1: case VEC_TRAP1:
/* jtagserver breakpoint */
case VEC_BREAKPOINT: case VEC_BREAKPOINT:
die_if_kernel("Kernel mode BKPT", regs, vector); do_trap_bkpt(regs);
info.si_code = TRAP_BRKPT;
sig = SIGTRAP;
break; break;
case VEC_ACCESS: case VEC_ACCESS:
tsk->thread.trap_no = vector; do_trap_buserr(regs);
return buserr(regs); break;
#ifdef CONFIG_CPU_NEED_SOFTALIGN
case VEC_ALIGN: case VEC_ALIGN:
tsk->thread.trap_no = vector; do_trap_misaligned(regs);
return csky_alignment(regs); break;
#endif
#ifdef CONFIG_CPU_HAS_FPU
case VEC_FPE: case VEC_FPE:
tsk->thread.trap_no = vector; do_trap_fpe(regs);
die_if_kernel("Kernel mode FPE", regs, vector); break;
return fpu_fpe(regs);
case VEC_PRIV: case VEC_PRIV:
tsk->thread.trap_no = vector; do_trap_priv(regs);
die_if_kernel("Kernel mode PRIV", regs, vector); break;
if (fpu_libc_helper(regs))
return;
#endif
default: default:
sig = SIGSEGV; do_trap_unknown(regs);
break; break;
} }
tsk->thread.trap_no = vector;
send_sig(sig, current, 0);
} }
# SPDX-License-Identifier: GPL-2.0-only # SPDX-License-Identifier: GPL-2.0-only
lib-y := usercopy.o delay.o 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, ...@@ -183,13 +183,13 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long write,
bad_area_nosemaphore: bad_area_nosemaphore:
/* User mode accesses just cause a SIGSEGV */ /* User mode accesses just cause a SIGSEGV */
if (user_mode(regs)) { 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); force_sig_fault(SIGSEGV, si_code, (void __user *)address);
return; return;
} }
no_context: 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? */ /* Are we prepared to handle this kernel fault? */
if (fixup_exception(regs)) if (fixup_exception(regs))
...@@ -202,10 +202,10 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long write, ...@@ -202,10 +202,10 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long write,
bust_spinlocks(1); bust_spinlocks(1);
pr_alert("Unable to handle kernel paging request at virtual " pr_alert("Unable to handle kernel paging request at virtual "
"address 0x%08lx, pc: 0x%08lx\n", address, regs->pc); "address 0x%08lx, pc: 0x%08lx\n", address, regs->pc);
die_if_kernel("Oops", regs, write); die(regs, "Oops");
out_of_memory: 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 * 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, ...@@ -215,7 +215,7 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long write,
return; return;
do_sigbus: do_sigbus:
tsk->thread.trap_no = (regs->sr >> 16) & 0xff; tsk->thread.trap_no = trap_no(regs);
mmap_read_unlock(mm); mmap_read_unlock(mm);
......
...@@ -19,8 +19,6 @@ void kmap_flush_tlb(unsigned long addr) ...@@ -19,8 +19,6 @@ void kmap_flush_tlb(unsigned long addr)
} }
EXPORT_SYMBOL(kmap_flush_tlb); EXPORT_SYMBOL(kmap_flush_tlb);
EXPORT_SYMBOL(kmap);
void *kmap_atomic_high_prot(struct page *page, pgprot_t prot) void *kmap_atomic_high_prot(struct page *page, pgprot_t prot)
{ {
unsigned long vaddr; unsigned long vaddr;
......
...@@ -123,6 +123,8 @@ struct seccomp_data { ...@@ -123,6 +123,8 @@ struct seccomp_data {
# define __NR_seccomp 277 # define __NR_seccomp 277
# elif defined(__riscv) # elif defined(__riscv)
# define __NR_seccomp 277 # define __NR_seccomp 277
# elif defined(__csky__)
# define __NR_seccomp 277
# elif defined(__hppa__) # elif defined(__hppa__)
# define __NR_seccomp 338 # define __NR_seccomp 338
# elif defined(__powerpc__) # elif defined(__powerpc__)
...@@ -1682,6 +1684,14 @@ TEST_F(TRACE_poke, getpid_runs_normally) ...@@ -1682,6 +1684,14 @@ TEST_F(TRACE_poke, getpid_runs_normally)
# define ARCH_REGS struct user_regs_struct # define ARCH_REGS struct user_regs_struct
# define SYSCALL_NUM a7 # define SYSCALL_NUM a7
# define SYSCALL_RET a0 # 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__) #elif defined(__hppa__)
# define ARCH_REGS struct user_regs_struct # define ARCH_REGS struct user_regs_struct
# define SYSCALL_NUM gr[20] # define SYSCALL_NUM gr[20]
...@@ -1781,7 +1791,7 @@ void change_syscall(struct __test_metadata *_metadata, ...@@ -1781,7 +1791,7 @@ void change_syscall(struct __test_metadata *_metadata,
#if defined(__x86_64__) || defined(__i386__) || defined(__powerpc__) || \ #if defined(__x86_64__) || defined(__i386__) || defined(__powerpc__) || \
defined(__s390__) || defined(__hppa__) || defined(__riscv) || \ defined(__s390__) || defined(__hppa__) || defined(__riscv) || \
defined(__xtensa__) defined(__xtensa__) || defined(__csky__)
{ {
regs.SYSCALL_NUM = syscall; 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