Skip to content

Commit

Permalink
Merge tag 'csky-for-linus-5.7-rc1' of git://github.com/c-sky/csky-linux
Browse files Browse the repository at this point in the history
Pull csky updates from Guo Ren:

 - Add kproobes/uprobes support

 - Add lockdep, rseq, gcov support

 - Fixup init_fpu

 - Fixup ftrace_modify deadlock

 - Fixup speculative execution on IO area

* tag 'csky-for-linus-5.7-rc1' of git://github.com/c-sky/csky-linux:
  csky: Fixup cpu speculative execution to IO area
  csky: Add uprobes support
  csky: Add kprobes supported
  csky: Enable LOCKDEP_SUPPORT
  csky: Enable the gcov function
  csky: Fixup get wrong psr value from phyical reg
  csky/ftrace: Fixup ftrace_modify_code deadlock without CPU_HAS_ICACHE_INS
  csky: Implement ftrace with regs
  csky: Add support for restartable sequence
  csky: Implement ptrace regs and stack API
  csky: Fixup init_fpu compile warning with __init
  • Loading branch information
Linus Torvalds committed Apr 6, 2020
2 parents b6ff107 + aefd946 commit f183d26
Show file tree
Hide file tree
Showing 34 changed files with 1,807 additions and 74 deletions.
13 changes: 13 additions & 0 deletions arch/csky/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ config CSKY
def_bool y
select ARCH_32BIT_OFF_T
select ARCH_HAS_DMA_PREP_COHERENT
select ARCH_HAS_GCOV_PROFILE_ALL
select ARCH_HAS_SYNC_DMA_FOR_CPU
select ARCH_HAS_SYNC_DMA_FOR_DEVICE
select ARCH_USE_BUILTIN_BSWAP
Expand Down Expand Up @@ -38,16 +39,22 @@ config CSKY
select HAVE_ARCH_AUDITSYSCALL
select HAVE_COPY_THREAD_TLS
select HAVE_DYNAMIC_FTRACE
select HAVE_DYNAMIC_FTRACE_WITH_REGS
select HAVE_FUNCTION_TRACER
select HAVE_FUNCTION_GRAPH_TRACER
select HAVE_FTRACE_MCOUNT_RECORD
select HAVE_KERNEL_GZIP
select HAVE_KERNEL_LZO
select HAVE_KERNEL_LZMA
select HAVE_KPROBES if !CPU_CK610
select HAVE_KPROBES_ON_FTRACE if !CPU_CK610
select HAVE_KRETPROBES if !CPU_CK610
select HAVE_PERF_EVENTS
select HAVE_PERF_REGS
select HAVE_PERF_USER_STACK_DUMP
select HAVE_DMA_CONTIGUOUS
select HAVE_REGS_AND_STACK_ACCESS_API
select HAVE_RSEQ
select HAVE_STACKPROTECTOR
select HAVE_SYSCALL_TRACEPOINTS
select MAY_HAVE_SPARSE_IRQ
Expand All @@ -65,6 +72,12 @@ config CSKY
select PCI_SYSCALL if PCI
select PCI_MSI if PCI

config LOCKDEP_SUPPORT
def_bool y

config ARCH_SUPPORTS_UPROBES
def_bool y if !CPU_CK610

config CPU_HAS_CACHEV2
bool

Expand Down
5 changes: 1 addition & 4 deletions arch/csky/abiv1/inc/abi/entry.h
Original file line number Diff line number Diff line change
Expand Up @@ -172,10 +172,7 @@
addi r6, 0xe
cpwcr r6, cpcr30

lsri r6, 28
addi r6, 2
lsli r6, 28
addi r6, 0xe
movi r6, 0
cpwcr r6, cpcr31
.endm

Expand Down
5 changes: 0 additions & 5 deletions arch/csky/abiv2/fpu.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,6 @@
#define MTCR_DIST 0xC0006420
#define MFCR_DIST 0xC0006020

void __init init_fpu(void)
{
mtcr("cr<1, 2>", 0);
}

/*
* fpu_libc_helper() is to help libc to excute:
* - mfcr %a, cr<1, 2>
Expand Down
67 changes: 62 additions & 5 deletions arch/csky/abiv2/inc/abi/entry.h
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,66 @@
rte
.endm

.macro SAVE_REGS_FTRACE
subi sp, 152
stw tls, (sp, 0)
stw lr, (sp, 4)

mfcr lr, psr
stw lr, (sp, 12)

addi lr, sp, 152
stw lr, (sp, 16)

stw a0, (sp, 20)
stw a0, (sp, 24)
stw a1, (sp, 28)
stw a2, (sp, 32)
stw a3, (sp, 36)

addi sp, 40
stm r4-r13, (sp)

addi sp, 40
stm r16-r30, (sp)
#ifdef CONFIG_CPU_HAS_HILO
mfhi lr
stw lr, (sp, 60)
mflo lr
stw lr, (sp, 64)
mfcr lr, cr14
stw lr, (sp, 68)
#endif
subi sp, 80
.endm

.macro RESTORE_REGS_FTRACE
ldw tls, (sp, 0)
ldw a0, (sp, 16)
mtcr a0, ss0

#ifdef CONFIG_CPU_HAS_HILO
ldw a0, (sp, 140)
mthi a0
ldw a0, (sp, 144)
mtlo a0
ldw a0, (sp, 148)
mtcr a0, cr14
#endif

ldw a0, (sp, 24)
ldw a1, (sp, 28)
ldw a2, (sp, 32)
ldw a3, (sp, 36)

addi sp, 40
ldm r4-r13, (sp)
addi sp, 40
ldm r16-r30, (sp)
addi sp, 72
mfcr sp, ss0
.endm

.macro SAVE_SWITCH_STACK
subi sp, 64
stm r4-r11, (sp)
Expand Down Expand Up @@ -230,11 +290,8 @@
addi r6, 0x1ce
mtcr r6, cr<30, 15> /* Set MSA0 */

lsri r6, 28
addi r6, 2
lsli r6, 28
addi r6, 0x1ce
mtcr r6, cr<31, 15> /* Set MSA1 */
movi r6, 0
mtcr r6, cr<31, 15> /* Clr MSA1 */

/* enable MMU */
mfcr r6, cr18
Expand Down
3 changes: 2 additions & 1 deletion arch/csky/abiv2/inc/abi/fpu.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@

int fpu_libc_helper(struct pt_regs *regs);
void fpu_fpe(struct pt_regs *regs);
void __init init_fpu(void);

static inline void init_fpu(void) { mtcr("cr<1, 2>", 0); }

void save_to_user_fp(struct user_fp *user_fp);
void restore_from_user_fp(struct user_fp *user_fp);
Expand Down
48 changes: 48 additions & 0 deletions arch/csky/abiv2/mcount.S
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@

#include <linux/linkage.h>
#include <asm/ftrace.h>
#include <abi/entry.h>
#include <asm/asm-offsets.h>

/*
* csky-gcc with -pg will put the following asm after prologue:
Expand Down Expand Up @@ -44,6 +46,22 @@
jmp t1
.endm

.macro mcount_enter_regs
subi sp, 8
stw lr, (sp, 0)
stw r8, (sp, 4)
SAVE_REGS_FTRACE
.endm

.macro mcount_exit_regs
RESTORE_REGS_FTRACE
ldw t1, (sp, 0)
ldw r8, (sp, 4)
ldw lr, (sp, 8)
addi sp, 12
jmp t1
.endm

.macro save_return_regs
subi sp, 16
stw a0, (sp, 0)
Expand Down Expand Up @@ -122,6 +140,8 @@ ENTRY(ftrace_caller)
ldw a0, (sp, 16)
subi a0, 4
ldw a1, (sp, 24)
lrw a2, function_trace_op
ldw a2, (a2, 0)

nop
GLOBAL(ftrace_call)
Expand Down Expand Up @@ -157,3 +177,31 @@ ENTRY(return_to_handler)
jmp lr
END(return_to_handler)
#endif

#ifdef CONFIG_DYNAMIC_FTRACE_WITH_REGS
ENTRY(ftrace_regs_caller)
mcount_enter_regs

lrw t1, PT_FRAME_SIZE
add t1, sp

ldw a0, (t1, 0)
subi a0, 4
ldw a1, (t1, 8)
lrw a2, function_trace_op
ldw a2, (a2, 0)
mov a3, sp

nop
GLOBAL(ftrace_regs_call)
nop32_stub

#ifdef CONFIG_FUNCTION_GRAPH_TRACER
nop
GLOBAL(ftrace_graph_regs_call)
nop32_stub
#endif

mcount_exit_regs
ENDPROC(ftrace_regs_caller)
#endif /* CONFIG_DYNAMIC_FTRACE */
2 changes: 2 additions & 0 deletions arch/csky/include/asm/ftrace.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@

#define HAVE_FUNCTION_GRAPH_RET_ADDR_PTR

#define ARCH_SUPPORTS_FTRACE_OPS 1

#define MCOUNT_ADDR ((unsigned long)_mcount)

#ifndef __ASSEMBLY__
Expand Down
48 changes: 48 additions & 0 deletions arch/csky/include/asm/kprobes.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/* SPDX-License-Identifier: GPL-2.0-only */

#ifndef __ASM_CSKY_KPROBES_H
#define __ASM_CSKY_KPROBES_H

#include <asm-generic/kprobes.h>

#ifdef CONFIG_KPROBES
#include <linux/types.h>
#include <linux/ptrace.h>
#include <linux/percpu.h>

#define __ARCH_WANT_KPROBES_INSN_SLOT
#define MAX_INSN_SIZE 1

#define flush_insn_slot(p) do { } while (0)
#define kretprobe_blacklist_size 0

#include <asm/probes.h>

struct prev_kprobe {
struct kprobe *kp;
unsigned int status;
};

/* Single step context for kprobe */
struct kprobe_step_ctx {
unsigned long ss_pending;
unsigned long match_addr;
};

/* per-cpu kprobe control block */
struct kprobe_ctlblk {
unsigned int kprobe_status;
unsigned long saved_sr;
struct prev_kprobe prev_kprobe;
struct kprobe_step_ctx ss_ctx;
};

void arch_remove_kprobe(struct kprobe *p);
int kprobe_fault_handler(struct pt_regs *regs, unsigned int trapnr);
int kprobe_breakpoint_handler(struct pt_regs *regs);
int kprobe_single_step_handler(struct pt_regs *regs);
void kretprobe_trampoline(void);
void __kprobes *trampoline_probe_handler(struct pt_regs *regs);

#endif /* CONFIG_KPROBES */
#endif /* __ASM_CSKY_KPROBES_H */
24 changes: 24 additions & 0 deletions arch/csky/include/asm/probes.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/* SPDX-License-Identifier: GPL-2.0 */

#ifndef __ASM_CSKY_PROBES_H
#define __ASM_CSKY_PROBES_H

typedef u32 probe_opcode_t;
typedef void (probes_handler_t) (u32 opcode, long addr, struct pt_regs *);

/* architecture specific copy of original instruction */
struct arch_probe_insn {
probe_opcode_t *insn;
probes_handler_t *handler;
/* restore address after simulation */
unsigned long restore;
};

#ifdef CONFIG_KPROBES
typedef u32 kprobe_opcode_t;
struct arch_specific_insn {
struct arch_probe_insn api;
};
#endif

#endif /* __ASM_CSKY_PROBES_H */
1 change: 1 addition & 0 deletions arch/csky/include/asm/processor.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ extern struct cpuinfo_csky cpu_data[];
struct thread_struct {
unsigned long ksp; /* kernel stack pointer */
unsigned long sr; /* saved status register */
unsigned long trap_no; /* saved status register */

/* FPU regs */
struct user_fp __aligned(16) user_fp;
Expand Down
43 changes: 43 additions & 0 deletions arch/csky/include/asm/ptrace.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,14 @@
#include <uapi/asm/ptrace.h>
#include <asm/traps.h>
#include <linux/types.h>
#include <linux/compiler.h>

#ifndef __ASSEMBLY__

#define PS_S 0x80000000 /* Supervisor Mode */

#define USR_BKPT 0x1464

#define arch_has_single_step() (1)
#define current_pt_regs() \
({ (struct pt_regs *)((char *)current_thread_info() + THREAD_SIZE) - 1; })
Expand All @@ -22,6 +25,18 @@
#define instruction_pointer(regs) ((regs)->pc)
#define profile_pc(regs) instruction_pointer(regs)

static inline void instruction_pointer_set(struct pt_regs *regs,
unsigned long val)
{
regs->pc = val;
}

#if defined(__CSKYABIV2__)
#define MAX_REG_OFFSET offsetof(struct pt_regs, dcsr)
#else
#define MAX_REG_OFFSET offsetof(struct pt_regs, regs[9])
#endif

static inline bool in_syscall(struct pt_regs const *regs)
{
return ((regs->sr >> 16) & 0xff) == VEC_TRAP0;
Expand All @@ -37,5 +52,33 @@ static inline unsigned long regs_return_value(struct pt_regs *regs)
return regs->a0;
}

/* Valid only for Kernel mode traps. */
static inline unsigned long kernel_stack_pointer(struct pt_regs *regs)
{
return regs->usp;
}

extern int regs_query_register_offset(const char *name);
extern unsigned long regs_get_kernel_stack_nth(struct pt_regs *regs,
unsigned int n);

/*
* regs_get_register() - get register value from its offset
* @regs: pt_regs from which register value is gotten
* @offset: offset of the register.
*
* regs_get_register returns the value of a register whose offset from @regs.
* The @offset is the offset of the register in struct pt_regs.
* If @offset is bigger than MAX_REG_OFFSET, this returns 0.
*/
static inline unsigned long regs_get_register(struct pt_regs *regs,
unsigned int offset)
{
if (unlikely(offset > MAX_REG_OFFSET))
return 0;

return *(unsigned long *)((unsigned long)regs + offset);
}

#endif /* __ASSEMBLY__ */
#endif /* __ASM_CSKY_PTRACE_H */
Loading

0 comments on commit f183d26

Please sign in to comment.