diff options
Diffstat (limited to 'arch/s390/kernel')
| -rw-r--r-- | arch/s390/kernel/ftrace.c | 61 | ||||
| -rw-r--r-- | arch/s390/kernel/perf_cpum_sf.c | 7 | ||||
| -rw-r--r-- | arch/s390/kernel/swsusp_asm64.S | 11 | 
3 files changed, 61 insertions, 18 deletions
| diff --git a/arch/s390/kernel/ftrace.c b/arch/s390/kernel/ftrace.c index 82c19899574f..6c79f1b44fe7 100644 --- a/arch/s390/kernel/ftrace.c +++ b/arch/s390/kernel/ftrace.c @@ -57,6 +57,44 @@  unsigned long ftrace_plt; +static inline void ftrace_generate_orig_insn(struct ftrace_insn *insn) +{ +#ifdef CC_USING_HOTPATCH +	/* brcl 0,0 */ +	insn->opc = 0xc004; +	insn->disp = 0; +#else +	/* stg r14,8(r15) */ +	insn->opc = 0xe3e0; +	insn->disp = 0xf0080024; +#endif +} + +static inline int is_kprobe_on_ftrace(struct ftrace_insn *insn) +{ +#ifdef CONFIG_KPROBES +	if (insn->opc == BREAKPOINT_INSTRUCTION) +		return 1; +#endif +	return 0; +} + +static inline void ftrace_generate_kprobe_nop_insn(struct ftrace_insn *insn) +{ +#ifdef CONFIG_KPROBES +	insn->opc = BREAKPOINT_INSTRUCTION; +	insn->disp = KPROBE_ON_FTRACE_NOP; +#endif +} + +static inline void ftrace_generate_kprobe_call_insn(struct ftrace_insn *insn) +{ +#ifdef CONFIG_KPROBES +	insn->opc = BREAKPOINT_INSTRUCTION; +	insn->disp = KPROBE_ON_FTRACE_CALL; +#endif +} +  int ftrace_modify_call(struct dyn_ftrace *rec, unsigned long old_addr,  		       unsigned long addr)  { @@ -72,16 +110,9 @@ int ftrace_make_nop(struct module *mod, struct dyn_ftrace *rec,  		return -EFAULT;  	if (addr == MCOUNT_ADDR) {  		/* Initial code replacement */ -#ifdef CC_USING_HOTPATCH -		/* We expect to see brcl 0,0 */ -		ftrace_generate_nop_insn(&orig); -#else -		/* We expect to see stg r14,8(r15) */ -		orig.opc = 0xe3e0; -		orig.disp = 0xf0080024; -#endif +		ftrace_generate_orig_insn(&orig);  		ftrace_generate_nop_insn(&new); -	} else if (old.opc == BREAKPOINT_INSTRUCTION) { +	} else if (is_kprobe_on_ftrace(&old)) {  		/*  		 * If we find a breakpoint instruction, a kprobe has been  		 * placed at the beginning of the function. We write the @@ -89,9 +120,8 @@ int ftrace_make_nop(struct module *mod, struct dyn_ftrace *rec,  		 * bytes of the original instruction so that the kprobes  		 * handler can execute a nop, if it reaches this breakpoint.  		 */ -		new.opc = orig.opc = BREAKPOINT_INSTRUCTION; -		orig.disp = KPROBE_ON_FTRACE_CALL; -		new.disp = KPROBE_ON_FTRACE_NOP; +		ftrace_generate_kprobe_call_insn(&orig); +		ftrace_generate_kprobe_nop_insn(&new);  	} else {  		/* Replace ftrace call with a nop. */  		ftrace_generate_call_insn(&orig, rec->ip); @@ -111,7 +141,7 @@ int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)  	if (probe_kernel_read(&old, (void *) rec->ip, sizeof(old)))  		return -EFAULT; -	if (old.opc == BREAKPOINT_INSTRUCTION) { +	if (is_kprobe_on_ftrace(&old)) {  		/*  		 * If we find a breakpoint instruction, a kprobe has been  		 * placed at the beginning of the function. We write the @@ -119,9 +149,8 @@ int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)  		 * bytes of the original instruction so that the kprobes  		 * handler can execute a brasl if it reaches this breakpoint.  		 */ -		new.opc = orig.opc = BREAKPOINT_INSTRUCTION; -		orig.disp = KPROBE_ON_FTRACE_NOP; -		new.disp = KPROBE_ON_FTRACE_CALL; +		ftrace_generate_kprobe_nop_insn(&orig); +		ftrace_generate_kprobe_call_insn(&new);  	} else {  		/* Replace nop with an ftrace call. */  		ftrace_generate_nop_insn(&orig); diff --git a/arch/s390/kernel/perf_cpum_sf.c b/arch/s390/kernel/perf_cpum_sf.c index c3f8d157cb0d..e6a1578fc000 100644 --- a/arch/s390/kernel/perf_cpum_sf.c +++ b/arch/s390/kernel/perf_cpum_sf.c @@ -1415,7 +1415,7 @@ CPUMF_EVENT_ATTR(SF, SF_CYCLES_BASIC_DIAG, PERF_EVENT_CPUM_SF_DIAG);  static struct attribute *cpumsf_pmu_events_attr[] = {  	CPUMF_EVENT_PTR(SF, SF_CYCLES_BASIC), -	CPUMF_EVENT_PTR(SF, SF_CYCLES_BASIC_DIAG), +	NULL,  	NULL,  }; @@ -1606,8 +1606,11 @@ static int __init init_cpum_sampling_pmu(void)  		return -EINVAL;  	} -	if (si.ad) +	if (si.ad) {  		sfb_set_limits(CPUM_SF_MIN_SDB, CPUM_SF_MAX_SDB); +		cpumsf_pmu_events_attr[1] = +			CPUMF_EVENT_PTR(SF, SF_CYCLES_BASIC_DIAG); +	}  	sfdbg = debug_register(KMSG_COMPONENT, 2, 1, 80);  	if (!sfdbg) diff --git a/arch/s390/kernel/swsusp_asm64.S b/arch/s390/kernel/swsusp_asm64.S index 6b09fdffbd2f..ca6294645dd3 100644 --- a/arch/s390/kernel/swsusp_asm64.S +++ b/arch/s390/kernel/swsusp_asm64.S @@ -177,6 +177,17 @@ restart_entry:  	lhi	%r1,1  	sigp	%r1,%r0,SIGP_SET_ARCHITECTURE  	sam64 +#ifdef CONFIG_SMP +	larl	%r1,smp_cpu_mt_shift +	icm	%r1,15,0(%r1) +	jz	smt_done +	llgfr	%r1,%r1 +smt_loop: +	sigp	%r1,%r0,SIGP_SET_MULTI_THREADING +	brc	8,smt_done			/* accepted */ +	brc	2,smt_loop			/* busy, try again */ +smt_done: +#endif  	larl	%r1,.Lnew_pgm_check_psw  	lpswe	0(%r1)  pgm_check_entry: |