xref: /openbmc/linux/arch/powerpc/kernel/optprobes_head.S (revision 7ae9fb1b7ecbb5d85d07857943f677fd1a559b18)
12874c5fdSThomas Gleixner/* SPDX-License-Identifier: GPL-2.0-or-later */
251c9c084SAnju T/*
351c9c084SAnju T * Code to prepare detour buffer for optprobes in Kernel.
451c9c084SAnju T *
551c9c084SAnju T * Copyright 2017, Anju T, IBM Corp.
651c9c084SAnju T */
751c9c084SAnju T
851c9c084SAnju T#include <asm/ppc_asm.h>
951c9c084SAnju T#include <asm/ptrace.h>
1051c9c084SAnju T#include <asm/asm-offsets.h>
1151c9c084SAnju T
12eacf4c02SChristophe Leroy#ifdef CONFIG_PPC64
13aebd1fb4SNicholas Piggin#define SAVE_30GPRS(base) SAVE_GPRS(2, 31, base)
14aebd1fb4SNicholas Piggin#define REST_30GPRS(base) REST_GPRS(2, 31, base)
15eacf4c02SChristophe Leroy#define TEMPLATE_FOR_IMM_LOAD_INSNS	nop; nop; nop; nop; nop
16eacf4c02SChristophe Leroy#else
17eacf4c02SChristophe Leroy#define SAVE_30GPRS(base) stmw	r2, GPR2(base)
18eacf4c02SChristophe Leroy#define REST_30GPRS(base) lmw	r2, GPR2(base)
19eacf4c02SChristophe Leroy#define TEMPLATE_FOR_IMM_LOAD_INSNS	nop; nop; nop
20eacf4c02SChristophe Leroy#endif
21eacf4c02SChristophe Leroy
2251c9c084SAnju T#define	OPT_SLOT_SIZE	65536
2351c9c084SAnju T
2451c9c084SAnju T	.balign	4
2551c9c084SAnju T
2651c9c084SAnju T	/*
2751c9c084SAnju T	 * Reserve an area to allocate slots for detour buffer.
2851c9c084SAnju T	 * This is part of .text section (rather than vmalloc area)
2951c9c084SAnju T	 * as this needs to be within 32MB of the probed address.
3051c9c084SAnju T	 */
3151c9c084SAnju T	.global optinsn_slot
3251c9c084SAnju Toptinsn_slot:
3351c9c084SAnju T	.space	OPT_SLOT_SIZE
3451c9c084SAnju T
3551c9c084SAnju T	/*
3651c9c084SAnju T	 * Optprobe template:
3751c9c084SAnju T	 * This template gets copied into one of the slots in optinsn_slot
3851c9c084SAnju T	 * and gets fixed up with real optprobe structures et al.
3951c9c084SAnju T	 */
4051c9c084SAnju T	.global optprobe_template_entry
4151c9c084SAnju Toptprobe_template_entry:
4251c9c084SAnju T	/* Create an in-memory pt_regs */
43eacf4c02SChristophe Leroy	PPC_STLU	r1,-INT_FRAME_SIZE(r1)
4451c9c084SAnju T	SAVE_GPR(0,r1)
4551c9c084SAnju T	/* Save the previous SP into stack */
4651c9c084SAnju T	addi	r0,r1,INT_FRAME_SIZE
47eacf4c02SChristophe Leroy	PPC_STL	r0,GPR1(r1)
48eacf4c02SChristophe Leroy	SAVE_30GPRS(r1)
4951c9c084SAnju T	/* Save SPRS */
5051c9c084SAnju T	mfmsr	r5
51eacf4c02SChristophe Leroy	PPC_STL	r5,_MSR(r1)
5251c9c084SAnju T	li	r5,0x700
53eacf4c02SChristophe Leroy	PPC_STL	r5,_TRAP(r1)
5451c9c084SAnju T	li	r5,0
55eacf4c02SChristophe Leroy	PPC_STL	r5,ORIG_GPR3(r1)
56eacf4c02SChristophe Leroy	PPC_STL	r5,RESULT(r1)
5751c9c084SAnju T	mfctr	r5
58eacf4c02SChristophe Leroy	PPC_STL	r5,_CTR(r1)
5951c9c084SAnju T	mflr	r5
60eacf4c02SChristophe Leroy	PPC_STL	r5,_LINK(r1)
6151c9c084SAnju T	mfspr	r5,SPRN_XER
62eacf4c02SChristophe Leroy	PPC_STL	r5,_XER(r1)
6351c9c084SAnju T	mfcr	r5
64eacf4c02SChristophe Leroy	PPC_STL	r5,_CCR(r1)
65eacf4c02SChristophe Leroy#ifdef CONFIG_PPC64
664e26bc4aSMadhavan Srinivasan	lbz     r5,PACAIRQSOFTMASK(r13)
6751c9c084SAnju T	std     r5,SOFTE(r1)
68eacf4c02SChristophe Leroy#endif
6951c9c084SAnju T
70f558b37bSNaveen N. Rao	/*
71f558b37bSNaveen N. Rao	 * We may get here from a module, so load the kernel TOC in r2.
72f558b37bSNaveen N. Rao	 * The original TOC gets restored when pt_regs is restored
73f558b37bSNaveen N. Rao	 * further below.
74f558b37bSNaveen N. Rao	 */
75eacf4c02SChristophe Leroy#ifdef CONFIG_PPC64
768e93fb33SNicholas Piggin	LOAD_PACA_TOC()
77eacf4c02SChristophe Leroy#endif
78f558b37bSNaveen N. Rao
7951c9c084SAnju T	.global optprobe_template_op_address
8051c9c084SAnju Toptprobe_template_op_address:
8151c9c084SAnju T	/*
8251c9c084SAnju T	 * Parameters to optimized_callback():
8351c9c084SAnju T	 * 1. optimized_kprobe structure in r3
8451c9c084SAnju T	 */
85eacf4c02SChristophe Leroy	TEMPLATE_FOR_IMM_LOAD_INSNS
86eacf4c02SChristophe Leroy
8751c9c084SAnju T	/* 2. pt_regs pointer in r4 */
88*c03be0a3SNicholas Piggin	addi	r4,r1,STACK_INT_FRAME_REGS
8951c9c084SAnju T
9051c9c084SAnju T	.global optprobe_template_call_handler
9151c9c084SAnju Toptprobe_template_call_handler:
9251c9c084SAnju T	/* Branch to optimized_callback() */
9351c9c084SAnju T	nop
9451c9c084SAnju T
9551c9c084SAnju T	/*
9651c9c084SAnju T	 * Parameters for instruction emulation:
9751c9c084SAnju T	 * 1. Pass SP in register r3.
9851c9c084SAnju T	 */
99*c03be0a3SNicholas Piggin	addi	r3,r1,STACK_INT_FRAME_REGS
10051c9c084SAnju T
10151c9c084SAnju T	.global optprobe_template_insn
10251c9c084SAnju Toptprobe_template_insn:
10351c9c084SAnju T	/* 2, Pass instruction to be emulated in r4 */
104eacf4c02SChristophe Leroy	TEMPLATE_FOR_IMM_LOAD_INSNS
10551c9c084SAnju T
10651c9c084SAnju T	.global optprobe_template_call_emulate
10751c9c084SAnju Toptprobe_template_call_emulate:
10851c9c084SAnju T	/* Branch to emulate_step()  */
10951c9c084SAnju T	nop
11051c9c084SAnju T
11151c9c084SAnju T	/*
11251c9c084SAnju T	 * All done.
11351c9c084SAnju T	 * Now, restore the registers...
11451c9c084SAnju T	 */
115eacf4c02SChristophe Leroy	PPC_LL	r5,_MSR(r1)
11651c9c084SAnju T	mtmsr	r5
117eacf4c02SChristophe Leroy	PPC_LL	r5,_CTR(r1)
11851c9c084SAnju T	mtctr	r5
119eacf4c02SChristophe Leroy	PPC_LL	r5,_LINK(r1)
12051c9c084SAnju T	mtlr	r5
121eacf4c02SChristophe Leroy	PPC_LL	r5,_XER(r1)
12251c9c084SAnju T	mtxer	r5
123eacf4c02SChristophe Leroy	PPC_LL	r5,_CCR(r1)
12451c9c084SAnju T	mtcr	r5
12551c9c084SAnju T	REST_GPR(0,r1)
126eacf4c02SChristophe Leroy	REST_30GPRS(r1)
12751c9c084SAnju T	/* Restore the previous SP */
12851c9c084SAnju T	addi	r1,r1,INT_FRAME_SIZE
12951c9c084SAnju T
13051c9c084SAnju T	.global optprobe_template_ret
13151c9c084SAnju Toptprobe_template_ret:
13251c9c084SAnju T	/* ... and jump back from trampoline */
13351c9c084SAnju T	nop
13451c9c084SAnju T
13551c9c084SAnju T	.global optprobe_template_end
13651c9c084SAnju Toptprobe_template_end:
137