clocksource: Make clocksource watchdog test safe for slow-HZ systems
[linux-2.6-microblaze.git] / arch / powerpc / kernel / optprobes_head.S
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 /*
3  * Code to prepare detour buffer for optprobes in Kernel.
4  *
5  * Copyright 2017, Anju T, IBM Corp.
6  */
7
8 #include <asm/ppc_asm.h>
9 #include <asm/ptrace.h>
10 #include <asm/asm-offsets.h>
11
12 #ifdef CONFIG_PPC64
13 #define SAVE_30GPRS(base) SAVE_10GPRS(2,base); SAVE_10GPRS(12,base); SAVE_10GPRS(22,base)
14 #define REST_30GPRS(base) REST_10GPRS(2,base); REST_10GPRS(12,base); REST_10GPRS(22,base)
15 #define TEMPLATE_FOR_IMM_LOAD_INSNS     nop; nop; nop; nop; nop
16 #else
17 #define SAVE_30GPRS(base) stmw  r2, GPR2(base)
18 #define REST_30GPRS(base) lmw   r2, GPR2(base)
19 #define TEMPLATE_FOR_IMM_LOAD_INSNS     nop; nop; nop
20 #endif
21
22 #define OPT_SLOT_SIZE   65536
23
24         .balign 4
25
26         /*
27          * Reserve an area to allocate slots for detour buffer.
28          * This is part of .text section (rather than vmalloc area)
29          * as this needs to be within 32MB of the probed address.
30          */
31         .global optinsn_slot
32 optinsn_slot:
33         .space  OPT_SLOT_SIZE
34
35         /*
36          * Optprobe template:
37          * This template gets copied into one of the slots in optinsn_slot
38          * and gets fixed up with real optprobe structures et al.
39          */
40         .global optprobe_template_entry
41 optprobe_template_entry:
42         /* Create an in-memory pt_regs */
43         PPC_STLU        r1,-INT_FRAME_SIZE(r1)
44         SAVE_GPR(0,r1)
45         /* Save the previous SP into stack */
46         addi    r0,r1,INT_FRAME_SIZE
47         PPC_STL r0,GPR1(r1)
48         SAVE_30GPRS(r1)
49         /* Save SPRS */
50         mfmsr   r5
51         PPC_STL r5,_MSR(r1)
52         li      r5,0x700
53         PPC_STL r5,_TRAP(r1)
54         li      r5,0
55         PPC_STL r5,ORIG_GPR3(r1)
56         PPC_STL r5,RESULT(r1)
57         mfctr   r5
58         PPC_STL r5,_CTR(r1)
59         mflr    r5
60         PPC_STL r5,_LINK(r1)
61         mfspr   r5,SPRN_XER
62         PPC_STL r5,_XER(r1)
63         mfcr    r5
64         PPC_STL r5,_CCR(r1)
65 #ifdef CONFIG_PPC64
66         lbz     r5,PACAIRQSOFTMASK(r13)
67         std     r5,SOFTE(r1)
68 #endif
69
70         /*
71          * We may get here from a module, so load the kernel TOC in r2.
72          * The original TOC gets restored when pt_regs is restored
73          * further below.
74          */
75 #ifdef CONFIG_PPC64
76         ld      r2,PACATOC(r13)
77 #endif
78
79         .global optprobe_template_op_address
80 optprobe_template_op_address:
81         /*
82          * Parameters to optimized_callback():
83          * 1. optimized_kprobe structure in r3
84          */
85         TEMPLATE_FOR_IMM_LOAD_INSNS
86
87         /* 2. pt_regs pointer in r4 */
88         addi    r4,r1,STACK_FRAME_OVERHEAD
89
90         .global optprobe_template_call_handler
91 optprobe_template_call_handler:
92         /* Branch to optimized_callback() */
93         nop
94
95         /*
96          * Parameters for instruction emulation:
97          * 1. Pass SP in register r3.
98          */
99         addi    r3,r1,STACK_FRAME_OVERHEAD
100
101         .global optprobe_template_insn
102 optprobe_template_insn:
103         /* 2, Pass instruction to be emulated in r4 */
104         TEMPLATE_FOR_IMM_LOAD_INSNS
105
106         .global optprobe_template_call_emulate
107 optprobe_template_call_emulate:
108         /* Branch to emulate_step()  */
109         nop
110
111         /*
112          * All done.
113          * Now, restore the registers...
114          */
115         PPC_LL  r5,_MSR(r1)
116         mtmsr   r5
117         PPC_LL  r5,_CTR(r1)
118         mtctr   r5
119         PPC_LL  r5,_LINK(r1)
120         mtlr    r5
121         PPC_LL  r5,_XER(r1)
122         mtxer   r5
123         PPC_LL  r5,_CCR(r1)
124         mtcr    r5
125         REST_GPR(0,r1)
126         REST_30GPRS(r1)
127         /* Restore the previous SP */
128         addi    r1,r1,INT_FRAME_SIZE
129
130         .global optprobe_template_ret
131 optprobe_template_ret:
132         /* ... and jump back from trampoline */
133         nop
134
135         .global optprobe_template_end
136 optprobe_template_end: