xref: /openbmc/linux/arch/powerpc/lib/sstep.c (revision 643d1f7f)
1 /*
2  * Single-step support.
3  *
4  * Copyright (C) 2004 Paul Mackerras <paulus@au.ibm.com>, IBM
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version
9  * 2 of the License, or (at your option) any later version.
10  */
11 #include <linux/kernel.h>
12 #include <linux/kprobes.h>
13 #include <linux/ptrace.h>
14 #include <asm/sstep.h>
15 #include <asm/processor.h>
16 
17 extern char system_call_common[];
18 
19 #ifdef CONFIG_PPC64
20 /* Bits in SRR1 that are copied from MSR */
21 #define MSR_MASK	0xffffffff87c0ffffUL
22 #else
23 #define MSR_MASK	0x87c0ffff
24 #endif
25 
26 /*
27  * Determine whether a conditional branch instruction would branch.
28  */
29 static int __kprobes branch_taken(unsigned int instr, struct pt_regs *regs)
30 {
31 	unsigned int bo = (instr >> 21) & 0x1f;
32 	unsigned int bi;
33 
34 	if ((bo & 4) == 0) {
35 		/* decrement counter */
36 		--regs->ctr;
37 		if (((bo >> 1) & 1) ^ (regs->ctr == 0))
38 			return 0;
39 	}
40 	if ((bo & 0x10) == 0) {
41 		/* check bit from CR */
42 		bi = (instr >> 16) & 0x1f;
43 		if (((regs->ccr >> (31 - bi)) & 1) != ((bo >> 3) & 1))
44 			return 0;
45 	}
46 	return 1;
47 }
48 
49 /*
50  * Emulate instructions that cause a transfer of control.
51  * Returns 1 if the step was emulated, 0 if not,
52  * or -1 if the instruction is one that should not be stepped,
53  * such as an rfid, or a mtmsrd that would clear MSR_RI.
54  */
55 int __kprobes emulate_step(struct pt_regs *regs, unsigned int instr)
56 {
57 	unsigned int opcode, rs, rb, rd, spr;
58 	unsigned long int imm;
59 
60 	opcode = instr >> 26;
61 	switch (opcode) {
62 	case 16:	/* bc */
63 		imm = (signed short)(instr & 0xfffc);
64 		if ((instr & 2) == 0)
65 			imm += regs->nip;
66 		regs->nip += 4;
67 		if ((regs->msr & MSR_SF) == 0)
68 			regs->nip &= 0xffffffffUL;
69 		if (instr & 1)
70 			regs->link = regs->nip;
71 		if (branch_taken(instr, regs))
72 			regs->nip = imm;
73 		return 1;
74 #ifdef CONFIG_PPC64
75 	case 17:	/* sc */
76 		/*
77 		 * N.B. this uses knowledge about how the syscall
78 		 * entry code works.  If that is changed, this will
79 		 * need to be changed also.
80 		 */
81 		regs->gpr[9] = regs->gpr[13];
82 		regs->gpr[11] = regs->nip + 4;
83 		regs->gpr[12] = regs->msr & MSR_MASK;
84 		regs->gpr[13] = (unsigned long) get_paca();
85 		regs->nip = (unsigned long) &system_call_common;
86 		regs->msr = MSR_KERNEL;
87 		return 1;
88 #endif
89 	case 18:	/* b */
90 		imm = instr & 0x03fffffc;
91 		if (imm & 0x02000000)
92 			imm -= 0x04000000;
93 		if ((instr & 2) == 0)
94 			imm += regs->nip;
95 		if (instr & 1) {
96 			regs->link = regs->nip + 4;
97 			if ((regs->msr & MSR_SF) == 0)
98 				regs->link &= 0xffffffffUL;
99 		}
100 		if ((regs->msr & MSR_SF) == 0)
101 			imm &= 0xffffffffUL;
102 		regs->nip = imm;
103 		return 1;
104 	case 19:
105 		switch (instr & 0x7fe) {
106 		case 0x20:	/* bclr */
107 		case 0x420:	/* bcctr */
108 			imm = (instr & 0x400)? regs->ctr: regs->link;
109 			regs->nip += 4;
110 			if ((regs->msr & MSR_SF) == 0) {
111 				regs->nip &= 0xffffffffUL;
112 				imm &= 0xffffffffUL;
113 			}
114 			if (instr & 1)
115 				regs->link = regs->nip;
116 			if (branch_taken(instr, regs))
117 				regs->nip = imm;
118 			return 1;
119 		case 0x24:	/* rfid, scary */
120 			return -1;
121 		}
122 	case 31:
123 		rd = (instr >> 21) & 0x1f;
124 		switch (instr & 0x7fe) {
125 		case 0xa6:	/* mfmsr */
126 			regs->gpr[rd] = regs->msr & MSR_MASK;
127 			regs->nip += 4;
128 			if ((regs->msr & MSR_SF) == 0)
129 				regs->nip &= 0xffffffffUL;
130 			return 1;
131 		case 0x124:	/* mtmsr */
132 			imm = regs->gpr[rd];
133 			if ((imm & MSR_RI) == 0)
134 				/* can't step mtmsr that would clear MSR_RI */
135 				return -1;
136 			regs->msr = imm;
137 			regs->nip += 4;
138 			return 1;
139 #ifdef CONFIG_PPC64
140 		case 0x164:	/* mtmsrd */
141 			/* only MSR_EE and MSR_RI get changed if bit 15 set */
142 			/* mtmsrd doesn't change MSR_HV and MSR_ME */
143 			imm = (instr & 0x10000)? 0x8002: 0xefffffffffffefffUL;
144 			imm = (regs->msr & MSR_MASK & ~imm)
145 				| (regs->gpr[rd] & imm);
146 			if ((imm & MSR_RI) == 0)
147 				/* can't step mtmsrd that would clear MSR_RI */
148 				return -1;
149 			regs->msr = imm;
150 			regs->nip += 4;
151 			if ((imm & MSR_SF) == 0)
152 				regs->nip &= 0xffffffffUL;
153 			return 1;
154 #endif
155 		case 0x26:	/* mfcr */
156 			regs->gpr[rd] = regs->ccr;
157 			regs->gpr[rd] &= 0xffffffffUL;
158 			goto mtspr_out;
159 		case 0x2a6:	/* mfspr */
160 			spr = (instr >> 11) & 0x3ff;
161 			switch (spr) {
162 			case 0x20:	/* mfxer */
163 				regs->gpr[rd] = regs->xer;
164 				regs->gpr[rd] &= 0xffffffffUL;
165 				goto mtspr_out;
166 			case 0x100:	/* mflr */
167 				regs->gpr[rd] = regs->link;
168 				goto mtspr_out;
169 			case 0x120:	/* mfctr */
170 				regs->gpr[rd] = regs->ctr;
171 				goto mtspr_out;
172 			}
173 			break;
174 		case 0x378:	/* orx */
175 			rs = (instr >> 21) & 0x1f;
176 			rb = (instr >> 11) & 0x1f;
177 			if (rs == rb) {		/* mr */
178 				rd = (instr >> 16) & 0x1f;
179 				regs->gpr[rd] = regs->gpr[rs];
180 				goto mtspr_out;
181 			}
182 			break;
183 		case 0x3a6:	/* mtspr */
184 			spr = (instr >> 11) & 0x3ff;
185 			switch (spr) {
186 			case 0x20:	/* mtxer */
187 				regs->xer = (regs->gpr[rd] & 0xffffffffUL);
188 				goto mtspr_out;
189 			case 0x100:	/* mtlr */
190 				regs->link = regs->gpr[rd];
191 				goto mtspr_out;
192 			case 0x120:	/* mtctr */
193 				regs->ctr = regs->gpr[rd];
194 mtspr_out:
195 				regs->nip += 4;
196 				return 1;
197 			}
198 		}
199 	}
200 	return 0;
201 }
202