Skip to content

Commit 309a0a6

Browse files
chleroympe
authored andcommitted
powerpc/code-patching: Replace patch_instruction() by ppc_inst_write() in selftests
The purpose of selftests is to check that instructions are properly formed. Not to check that they properly run. For that test it uses normal memory, not special test memory. In preparation of a future patch enforcing patch_instruction() to be used only on valid text areas, implement a ppc_inst_write() instruction which is the complement of ppc_inst_read(). This new function writes the formated instruction in valid kernel memory and doesn't bother about icache. Signed-off-by: Christophe Leroy <[email protected]> Signed-off-by: Michael Ellerman <[email protected]> Link: https://lore.kernel.org/r/7cf5335cc07ca9b6f8cdaa20ca9887fce4df3bea.1638446239.git.christophe.leroy@csgroup.eu
1 parent f30a578 commit 309a0a6

File tree

2 files changed

+53
-40
lines changed

2 files changed

+53
-40
lines changed

arch/powerpc/include/asm/inst.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,14 @@ static inline unsigned long ppc_inst_as_ulong(ppc_inst_t x)
131131
return (u64)ppc_inst_val(x) << 32 | ppc_inst_suffix(x);
132132
}
133133

134+
static inline void ppc_inst_write(u32 *ptr, ppc_inst_t x)
135+
{
136+
if (!ppc_inst_prefixed(x))
137+
*ptr = ppc_inst_val(x);
138+
else
139+
*(u64 *)ptr = ppc_inst_as_ulong(x);
140+
}
141+
134142
#define PPC_INST_STR_LEN sizeof("00000000 00000000")
135143

136144
static inline char *__ppc_inst_as_str(char str[PPC_INST_STR_LEN], ppc_inst_t x)

arch/powerpc/lib/test-code-patching.c

Lines changed: 45 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -54,39 +54,39 @@ static void __init test_branch_iform(void)
5454
check(!instr_is_branch_iform(ppc_inst(0x7bfffffd)));
5555

5656
/* Absolute branch to 0x100 */
57-
patch_instruction(iptr, ppc_inst(0x48000103));
57+
ppc_inst_write(iptr, ppc_inst(0x48000103));
5858
check(instr_is_branch_to_addr(iptr, 0x100));
5959
/* Absolute branch to 0x420fc */
60-
patch_instruction(iptr, ppc_inst(0x480420ff));
60+
ppc_inst_write(iptr, ppc_inst(0x480420ff));
6161
check(instr_is_branch_to_addr(iptr, 0x420fc));
6262
/* Maximum positive relative branch, + 20MB - 4B */
63-
patch_instruction(iptr, ppc_inst(0x49fffffc));
63+
ppc_inst_write(iptr, ppc_inst(0x49fffffc));
6464
check(instr_is_branch_to_addr(iptr, addr + 0x1FFFFFC));
6565
/* Smallest negative relative branch, - 4B */
66-
patch_instruction(iptr, ppc_inst(0x4bfffffc));
66+
ppc_inst_write(iptr, ppc_inst(0x4bfffffc));
6767
check(instr_is_branch_to_addr(iptr, addr - 4));
6868
/* Largest negative relative branch, - 32 MB */
69-
patch_instruction(iptr, ppc_inst(0x4a000000));
69+
ppc_inst_write(iptr, ppc_inst(0x4a000000));
7070
check(instr_is_branch_to_addr(iptr, addr - 0x2000000));
7171

7272
/* Branch to self, with link */
7373
err = create_branch(&instr, iptr, addr, BRANCH_SET_LINK);
74-
patch_instruction(iptr, instr);
74+
ppc_inst_write(iptr, instr);
7575
check(instr_is_branch_to_addr(iptr, addr));
7676

7777
/* Branch to self - 0x100, with link */
7878
err = create_branch(&instr, iptr, addr - 0x100, BRANCH_SET_LINK);
79-
patch_instruction(iptr, instr);
79+
ppc_inst_write(iptr, instr);
8080
check(instr_is_branch_to_addr(iptr, addr - 0x100));
8181

8282
/* Branch to self + 0x100, no link */
8383
err = create_branch(&instr, iptr, addr + 0x100, 0);
84-
patch_instruction(iptr, instr);
84+
ppc_inst_write(iptr, instr);
8585
check(instr_is_branch_to_addr(iptr, addr + 0x100));
8686

8787
/* Maximum relative negative offset, - 32 MB */
8888
err = create_branch(&instr, iptr, addr - 0x2000000, BRANCH_SET_LINK);
89-
patch_instruction(iptr, instr);
89+
ppc_inst_write(iptr, instr);
9090
check(instr_is_branch_to_addr(iptr, addr - 0x2000000));
9191

9292
/* Out of range relative negative offset, - 32 MB + 4*/
@@ -103,7 +103,7 @@ static void __init test_branch_iform(void)
103103

104104
/* Check flags are masked correctly */
105105
err = create_branch(&instr, iptr, addr, 0xFFFFFFFC);
106-
patch_instruction(iptr, instr);
106+
ppc_inst_write(iptr, instr);
107107
check(instr_is_branch_to_addr(iptr, addr));
108108
check(ppc_inst_equal(instr, ppc_inst(0x48000000)));
109109
}
@@ -143,42 +143,42 @@ static void __init test_branch_bform(void)
143143
check(!instr_is_branch_bform(ppc_inst(0x7bffffff)));
144144

145145
/* Absolute conditional branch to 0x100 */
146-
patch_instruction(iptr, ppc_inst(0x43ff0103));
146+
ppc_inst_write(iptr, ppc_inst(0x43ff0103));
147147
check(instr_is_branch_to_addr(iptr, 0x100));
148148
/* Absolute conditional branch to 0x20fc */
149-
patch_instruction(iptr, ppc_inst(0x43ff20ff));
149+
ppc_inst_write(iptr, ppc_inst(0x43ff20ff));
150150
check(instr_is_branch_to_addr(iptr, 0x20fc));
151151
/* Maximum positive relative conditional branch, + 32 KB - 4B */
152-
patch_instruction(iptr, ppc_inst(0x43ff7ffc));
152+
ppc_inst_write(iptr, ppc_inst(0x43ff7ffc));
153153
check(instr_is_branch_to_addr(iptr, addr + 0x7FFC));
154154
/* Smallest negative relative conditional branch, - 4B */
155-
patch_instruction(iptr, ppc_inst(0x43fffffc));
155+
ppc_inst_write(iptr, ppc_inst(0x43fffffc));
156156
check(instr_is_branch_to_addr(iptr, addr - 4));
157157
/* Largest negative relative conditional branch, - 32 KB */
158-
patch_instruction(iptr, ppc_inst(0x43ff8000));
158+
ppc_inst_write(iptr, ppc_inst(0x43ff8000));
159159
check(instr_is_branch_to_addr(iptr, addr - 0x8000));
160160

161161
/* All condition code bits set & link */
162162
flags = 0x3ff000 | BRANCH_SET_LINK;
163163

164164
/* Branch to self */
165165
err = create_cond_branch(&instr, iptr, addr, flags);
166-
patch_instruction(iptr, instr);
166+
ppc_inst_write(iptr, instr);
167167
check(instr_is_branch_to_addr(iptr, addr));
168168

169169
/* Branch to self - 0x100 */
170170
err = create_cond_branch(&instr, iptr, addr - 0x100, flags);
171-
patch_instruction(iptr, instr);
171+
ppc_inst_write(iptr, instr);
172172
check(instr_is_branch_to_addr(iptr, addr - 0x100));
173173

174174
/* Branch to self + 0x100 */
175175
err = create_cond_branch(&instr, iptr, addr + 0x100, flags);
176-
patch_instruction(iptr, instr);
176+
ppc_inst_write(iptr, instr);
177177
check(instr_is_branch_to_addr(iptr, addr + 0x100));
178178

179179
/* Maximum relative negative offset, - 32 KB */
180180
err = create_cond_branch(&instr, iptr, addr - 0x8000, flags);
181-
patch_instruction(iptr, instr);
181+
ppc_inst_write(iptr, instr);
182182
check(instr_is_branch_to_addr(iptr, addr - 0x8000));
183183

184184
/* Out of range relative negative offset, - 32 KB + 4*/
@@ -195,7 +195,7 @@ static void __init test_branch_bform(void)
195195

196196
/* Check flags are masked correctly */
197197
err = create_cond_branch(&instr, iptr, addr, 0xFFFFFFFC);
198-
patch_instruction(iptr, instr);
198+
ppc_inst_write(iptr, instr);
199199
check(instr_is_branch_to_addr(iptr, addr));
200200
check(ppc_inst_equal(instr, ppc_inst(0x43FF0000)));
201201
}
@@ -215,52 +215,57 @@ static void __init test_translate_branch(void)
215215
/* Simple case, branch to self moved a little */
216216
p = buf;
217217
addr = (unsigned long)p;
218-
patch_branch(p, addr, 0);
218+
create_branch(&instr, p, addr, 0);
219+
ppc_inst_write(p, instr);
219220
check(instr_is_branch_to_addr(p, addr));
220221
q = p + 4;
221222
translate_branch(&instr, q, p);
222-
patch_instruction(q, instr);
223+
ppc_inst_write(q, instr);
223224
check(instr_is_branch_to_addr(q, addr));
224225

225226
/* Maximum negative case, move b . to addr + 32 MB */
226227
p = buf;
227228
addr = (unsigned long)p;
228-
patch_branch(p, addr, 0);
229+
create_branch(&instr, p, addr, 0);
230+
ppc_inst_write(p, instr);
229231
q = buf + 0x2000000;
230232
translate_branch(&instr, q, p);
231-
patch_instruction(q, instr);
233+
ppc_inst_write(q, instr);
232234
check(instr_is_branch_to_addr(p, addr));
233235
check(instr_is_branch_to_addr(q, addr));
234236
check(ppc_inst_equal(ppc_inst_read(q), ppc_inst(0x4a000000)));
235237

236238
/* Maximum positive case, move x to x - 32 MB + 4 */
237239
p = buf + 0x2000000;
238240
addr = (unsigned long)p;
239-
patch_branch(p, addr, 0);
241+
create_branch(&instr, p, addr, 0);
242+
ppc_inst_write(p, instr);
240243
q = buf + 4;
241244
translate_branch(&instr, q, p);
242-
patch_instruction(q, instr);
245+
ppc_inst_write(q, instr);
243246
check(instr_is_branch_to_addr(p, addr));
244247
check(instr_is_branch_to_addr(q, addr));
245248
check(ppc_inst_equal(ppc_inst_read(q), ppc_inst(0x49fffffc)));
246249

247250
/* Jump to x + 16 MB moved to x + 20 MB */
248251
p = buf;
249252
addr = 0x1000000 + (unsigned long)buf;
250-
patch_branch(p, addr, BRANCH_SET_LINK);
253+
create_branch(&instr, p, addr, BRANCH_SET_LINK);
254+
ppc_inst_write(p, instr);
251255
q = buf + 0x1400000;
252256
translate_branch(&instr, q, p);
253-
patch_instruction(q, instr);
257+
ppc_inst_write(q, instr);
254258
check(instr_is_branch_to_addr(p, addr));
255259
check(instr_is_branch_to_addr(q, addr));
256260

257261
/* Jump to x + 16 MB moved to x - 16 MB + 4 */
258262
p = buf + 0x1000000;
259263
addr = 0x2000000 + (unsigned long)buf;
260-
patch_branch(p, addr, 0);
264+
create_branch(&instr, p, addr, 0);
265+
ppc_inst_write(p, instr);
261266
q = buf + 4;
262267
translate_branch(&instr, q, p);
263-
patch_instruction(q, instr);
268+
ppc_inst_write(q, instr);
264269
check(instr_is_branch_to_addr(p, addr));
265270
check(instr_is_branch_to_addr(q, addr));
266271

@@ -271,21 +276,21 @@ static void __init test_translate_branch(void)
271276
p = buf;
272277
addr = (unsigned long)p;
273278
create_cond_branch(&instr, p, addr, 0);
274-
patch_instruction(p, instr);
279+
ppc_inst_write(p, instr);
275280
check(instr_is_branch_to_addr(p, addr));
276281
q = buf + 4;
277282
translate_branch(&instr, q, p);
278-
patch_instruction(q, instr);
283+
ppc_inst_write(q, instr);
279284
check(instr_is_branch_to_addr(q, addr));
280285

281286
/* Maximum negative case, move b . to addr + 32 KB */
282287
p = buf;
283288
addr = (unsigned long)p;
284289
create_cond_branch(&instr, p, addr, 0xFFFFFFFC);
285-
patch_instruction(p, instr);
290+
ppc_inst_write(p, instr);
286291
q = buf + 0x8000;
287292
translate_branch(&instr, q, p);
288-
patch_instruction(q, instr);
293+
ppc_inst_write(q, instr);
289294
check(instr_is_branch_to_addr(p, addr));
290295
check(instr_is_branch_to_addr(q, addr));
291296
check(ppc_inst_equal(ppc_inst_read(q), ppc_inst(0x43ff8000)));
@@ -294,10 +299,10 @@ static void __init test_translate_branch(void)
294299
p = buf + 0x8000;
295300
addr = (unsigned long)p;
296301
create_cond_branch(&instr, p, addr, 0xFFFFFFFC);
297-
patch_instruction(p, instr);
302+
ppc_inst_write(p, instr);
298303
q = buf + 4;
299304
translate_branch(&instr, q, p);
300-
patch_instruction(q, instr);
305+
ppc_inst_write(q, instr);
301306
check(instr_is_branch_to_addr(p, addr));
302307
check(instr_is_branch_to_addr(q, addr));
303308
check(ppc_inst_equal(ppc_inst_read(q), ppc_inst(0x43ff7ffc)));
@@ -306,21 +311,21 @@ static void __init test_translate_branch(void)
306311
p = buf;
307312
addr = 0x3000 + (unsigned long)buf;
308313
create_cond_branch(&instr, p, addr, BRANCH_SET_LINK);
309-
patch_instruction(p, instr);
314+
ppc_inst_write(p, instr);
310315
q = buf + 0x5000;
311316
translate_branch(&instr, q, p);
312-
patch_instruction(q, instr);
317+
ppc_inst_write(q, instr);
313318
check(instr_is_branch_to_addr(p, addr));
314319
check(instr_is_branch_to_addr(q, addr));
315320

316321
/* Jump to x + 8 KB moved to x - 8 KB + 4 */
317322
p = buf + 0x2000;
318323
addr = 0x4000 + (unsigned long)buf;
319324
create_cond_branch(&instr, p, addr, 0);
320-
patch_instruction(p, instr);
325+
ppc_inst_write(p, instr);
321326
q = buf + 4;
322327
translate_branch(&instr, q, p);
323-
patch_instruction(q, instr);
328+
ppc_inst_write(q, instr);
324329
check(instr_is_branch_to_addr(p, addr));
325330
check(instr_is_branch_to_addr(q, addr));
326331

0 commit comments

Comments
 (0)