diff options
Diffstat (limited to 'arch/powerpc/lib')
-rw-r--r-- | arch/powerpc/lib/Makefile | 1 | ||||
-rw-r--r-- | arch/powerpc/lib/feature-fixups-test.S | 727 | ||||
-rw-r--r-- | arch/powerpc/lib/feature-fixups.c | 206 |
3 files changed, 934 insertions, 0 deletions
diff --git a/arch/powerpc/lib/Makefile b/arch/powerpc/lib/Makefile index fc52771f0cdb..2a88e8b9a3c6 100644 --- a/arch/powerpc/lib/Makefile +++ b/arch/powerpc/lib/Makefile | |||
@@ -27,3 +27,4 @@ obj-$(CONFIG_PPC_LIB_RHEAP) += rheap.o | |||
27 | 27 | ||
28 | obj-y += code-patching.o | 28 | obj-y += code-patching.o |
29 | obj-y += feature-fixups.o | 29 | obj-y += feature-fixups.o |
30 | obj-$(CONFIG_FTR_FIXUP_SELFTEST) += feature-fixups-test.o | ||
diff --git a/arch/powerpc/lib/feature-fixups-test.S b/arch/powerpc/lib/feature-fixups-test.S new file mode 100644 index 000000000000..10d038b501a6 --- /dev/null +++ b/arch/powerpc/lib/feature-fixups-test.S | |||
@@ -0,0 +1,727 @@ | |||
1 | /* | ||
2 | * Copyright 2008 Michael Ellerman, IBM Corporation. | ||
3 | * | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or | ||
6 | * modify it under the terms of the GNU General Public License | ||
7 | * as published by the Free Software Foundation; either version | ||
8 | * 2 of the License, or (at your option) any later version. | ||
9 | */ | ||
10 | |||
11 | #include <asm/feature-fixups.h> | ||
12 | #include <asm/ppc_asm.h> | ||
13 | |||
14 | .text | ||
15 | |||
16 | #define globl(x) \ | ||
17 | .globl x; \ | ||
18 | x: | ||
19 | |||
20 | globl(ftr_fixup_test1) | ||
21 | or 1,1,1 | ||
22 | or 2,2,2 /* fixup will nop out this instruction */ | ||
23 | or 3,3,3 | ||
24 | |||
25 | globl(end_ftr_fixup_test1) | ||
26 | |||
27 | globl(ftr_fixup_test1_orig) | ||
28 | or 1,1,1 | ||
29 | or 2,2,2 | ||
30 | or 3,3,3 | ||
31 | |||
32 | globl(ftr_fixup_test1_expected) | ||
33 | or 1,1,1 | ||
34 | nop | ||
35 | or 3,3,3 | ||
36 | |||
37 | globl(ftr_fixup_test2) | ||
38 | or 1,1,1 | ||
39 | or 2,2,2 /* fixup will replace this with ftr_fixup_test2_alt */ | ||
40 | or 3,3,3 | ||
41 | |||
42 | globl(end_ftr_fixup_test2) | ||
43 | |||
44 | globl(ftr_fixup_test2_orig) | ||
45 | or 1,1,1 | ||
46 | or 2,2,2 | ||
47 | or 3,3,3 | ||
48 | |||
49 | globl(ftr_fixup_test2_alt) | ||
50 | or 31,31,31 | ||
51 | |||
52 | globl(ftr_fixup_test2_expected) | ||
53 | or 1,1,1 | ||
54 | or 31,31,31 | ||
55 | or 3,3,3 | ||
56 | |||
57 | globl(ftr_fixup_test3) | ||
58 | or 1,1,1 | ||
59 | or 2,2,2 /* fixup will fail to replace this */ | ||
60 | or 3,3,3 | ||
61 | |||
62 | globl(end_ftr_fixup_test3) | ||
63 | |||
64 | globl(ftr_fixup_test3_orig) | ||
65 | or 1,1,1 | ||
66 | or 2,2,2 | ||
67 | or 3,3,3 | ||
68 | |||
69 | globl(ftr_fixup_test3_alt) | ||
70 | or 31,31,31 | ||
71 | or 31,31,31 | ||
72 | |||
73 | globl(ftr_fixup_test4) | ||
74 | or 1,1,1 | ||
75 | or 2,2,2 | ||
76 | or 2,2,2 | ||
77 | or 2,2,2 | ||
78 | or 2,2,2 | ||
79 | or 3,3,3 | ||
80 | |||
81 | globl(end_ftr_fixup_test4) | ||
82 | |||
83 | globl(ftr_fixup_test4_expected) | ||
84 | or 1,1,1 | ||
85 | or 31,31,31 | ||
86 | or 31,31,31 | ||
87 | nop | ||
88 | nop | ||
89 | or 3,3,3 | ||
90 | |||
91 | globl(ftr_fixup_test4_orig) | ||
92 | or 1,1,1 | ||
93 | or 2,2,2 | ||
94 | or 2,2,2 | ||
95 | or 2,2,2 | ||
96 | or 2,2,2 | ||
97 | or 3,3,3 | ||
98 | |||
99 | globl(ftr_fixup_test4_alt) | ||
100 | or 31,31,31 | ||
101 | or 31,31,31 | ||
102 | |||
103 | |||
104 | globl(ftr_fixup_test5) | ||
105 | or 1,1,1 | ||
106 | BEGIN_FTR_SECTION | ||
107 | or 2,2,2 | ||
108 | or 2,2,2 | ||
109 | or 2,2,2 | ||
110 | or 2,2,2 | ||
111 | or 2,2,2 | ||
112 | or 2,2,2 | ||
113 | or 2,2,2 | ||
114 | FTR_SECTION_ELSE | ||
115 | 2: b 3f | ||
116 | 3: or 5,5,5 | ||
117 | beq 3b | ||
118 | b 1f | ||
119 | or 6,6,6 | ||
120 | b 2b | ||
121 | 1: bdnz 3b | ||
122 | ALT_FTR_SECTION_END(0, 1) | ||
123 | or 1,1,1 | ||
124 | |||
125 | globl(end_ftr_fixup_test5) | ||
126 | |||
127 | globl(ftr_fixup_test5_expected) | ||
128 | or 1,1,1 | ||
129 | 2: b 3f | ||
130 | 3: or 5,5,5 | ||
131 | beq 3b | ||
132 | b 1f | ||
133 | or 6,6,6 | ||
134 | b 2b | ||
135 | 1: bdnz 3b | ||
136 | or 1,1,1 | ||
137 | |||
138 | globl(ftr_fixup_test6) | ||
139 | 1: or 1,1,1 | ||
140 | BEGIN_FTR_SECTION | ||
141 | or 5,5,5 | ||
142 | 2: cmpdi r3,0 | ||
143 | beq 4f | ||
144 | blt 2b | ||
145 | b 1b | ||
146 | b 4f | ||
147 | FTR_SECTION_ELSE | ||
148 | 2: or 2,2,2 | ||
149 | cmpdi r3,1 | ||
150 | beq 3f | ||
151 | blt 2b | ||
152 | b 3f | ||
153 | b 1b | ||
154 | ALT_FTR_SECTION_END(0, 1) | ||
155 | 3: or 1,1,1 | ||
156 | or 2,2,2 | ||
157 | 4: or 3,3,3 | ||
158 | |||
159 | globl(end_ftr_fixup_test6) | ||
160 | |||
161 | globl(ftr_fixup_test6_expected) | ||
162 | 1: or 1,1,1 | ||
163 | 2: or 2,2,2 | ||
164 | cmpdi r3,1 | ||
165 | beq 3f | ||
166 | blt 2b | ||
167 | b 3f | ||
168 | b 1b | ||
169 | 2: or 1,1,1 | ||
170 | or 2,2,2 | ||
171 | 3: or 3,3,3 | ||
172 | |||
173 | |||
174 | #define MAKE_MACRO_TEST(TYPE) \ | ||
175 | globl(ftr_fixup_test_ ##TYPE##_macros) \ | ||
176 | or 1,1,1; \ | ||
177 | /* Basic test, this section should all be nop'ed */ \ | ||
178 | BEGIN_##TYPE##_SECTION \ | ||
179 | or 2,2,2; \ | ||
180 | or 2,2,2; \ | ||
181 | or 2,2,2; \ | ||
182 | END_##TYPE##_SECTION(0, 1) \ | ||
183 | or 1,1,1; \ | ||
184 | or 1,1,1; \ | ||
185 | /* Basic test, this section should NOT be nop'ed */ \ | ||
186 | BEGIN_##TYPE##_SECTION \ | ||
187 | or 2,2,2; \ | ||
188 | or 2,2,2; \ | ||
189 | or 2,2,2; \ | ||
190 | END_##TYPE##_SECTION(0, 0) \ | ||
191 | or 1,1,1; \ | ||
192 | or 1,1,1; \ | ||
193 | /* Nesting test, inner section should be nop'ed */ \ | ||
194 | BEGIN_##TYPE##_SECTION \ | ||
195 | or 2,2,2; \ | ||
196 | or 2,2,2; \ | ||
197 | BEGIN_##TYPE##_SECTION_NESTED(80) \ | ||
198 | or 3,3,3; \ | ||
199 | or 3,3,3; \ | ||
200 | END_##TYPE##_SECTION_NESTED(0, 1, 80) \ | ||
201 | or 2,2,2; \ | ||
202 | or 2,2,2; \ | ||
203 | END_##TYPE##_SECTION(0, 0) \ | ||
204 | or 1,1,1; \ | ||
205 | or 1,1,1; \ | ||
206 | /* Nesting test, whole section should be nop'ed */ \ | ||
207 | BEGIN_##TYPE##_SECTION \ | ||
208 | or 2,2,2; \ | ||
209 | or 2,2,2; \ | ||
210 | BEGIN_##TYPE##_SECTION_NESTED(80) \ | ||
211 | or 3,3,3; \ | ||
212 | or 3,3,3; \ | ||
213 | END_##TYPE##_SECTION_NESTED(0, 0, 80) \ | ||
214 | or 2,2,2; \ | ||
215 | or 2,2,2; \ | ||
216 | END_##TYPE##_SECTION(0, 1) \ | ||
217 | or 1,1,1; \ | ||
218 | or 1,1,1; \ | ||
219 | /* Nesting test, none should be nop'ed */ \ | ||
220 | BEGIN_##TYPE##_SECTION \ | ||
221 | or 2,2,2; \ | ||
222 | or 2,2,2; \ | ||
223 | BEGIN_##TYPE##_SECTION_NESTED(80) \ | ||
224 | or 3,3,3; \ | ||
225 | or 3,3,3; \ | ||
226 | END_##TYPE##_SECTION_NESTED(0, 0, 80) \ | ||
227 | or 2,2,2; \ | ||
228 | or 2,2,2; \ | ||
229 | END_##TYPE##_SECTION(0, 0) \ | ||
230 | or 1,1,1; \ | ||
231 | or 1,1,1; \ | ||
232 | /* Basic alt section test, default case should be taken */ \ | ||
233 | BEGIN_##TYPE##_SECTION \ | ||
234 | or 3,3,3; \ | ||
235 | or 3,3,3; \ | ||
236 | or 3,3,3; \ | ||
237 | ##TYPE##_SECTION_ELSE \ | ||
238 | or 5,5,5; \ | ||
239 | or 5,5,5; \ | ||
240 | ALT_##TYPE##_SECTION_END(0, 0) \ | ||
241 | or 1,1,1; \ | ||
242 | or 1,1,1; \ | ||
243 | /* Basic alt section test, else case should be taken */ \ | ||
244 | BEGIN_##TYPE##_SECTION \ | ||
245 | or 3,3,3; \ | ||
246 | or 3,3,3; \ | ||
247 | or 3,3,3; \ | ||
248 | ##TYPE##_SECTION_ELSE \ | ||
249 | or 31,31,31; \ | ||
250 | or 31,31,31; \ | ||
251 | or 31,31,31; \ | ||
252 | ALT_##TYPE##_SECTION_END(0, 1) \ | ||
253 | or 1,1,1; \ | ||
254 | or 1,1,1; \ | ||
255 | /* Alt with smaller else case, should be padded with nops */ \ | ||
256 | BEGIN_##TYPE##_SECTION \ | ||
257 | or 3,3,3; \ | ||
258 | or 3,3,3; \ | ||
259 | or 3,3,3; \ | ||
260 | ##TYPE##_SECTION_ELSE \ | ||
261 | or 31,31,31; \ | ||
262 | ALT_##TYPE##_SECTION_END(0, 1) \ | ||
263 | or 1,1,1; \ | ||
264 | or 1,1,1; \ | ||
265 | /* Alt section with nested section in default case */ \ | ||
266 | /* Default case should be taken, with nop'ed inner section */ \ | ||
267 | BEGIN_##TYPE##_SECTION \ | ||
268 | or 3,3,3; \ | ||
269 | BEGIN_##TYPE##_SECTION_NESTED(95) \ | ||
270 | or 3,3,3; \ | ||
271 | or 3,3,3; \ | ||
272 | END_##TYPE##_SECTION_NESTED(0, 1, 95) \ | ||
273 | or 3,3,3; \ | ||
274 | ##TYPE##_SECTION_ELSE \ | ||
275 | or 2,2,2; \ | ||
276 | or 2,2,2; \ | ||
277 | ALT_##TYPE##_SECTION_END(0, 0) \ | ||
278 | or 1,1,1; \ | ||
279 | or 1,1,1; \ | ||
280 | /* Alt section with nested section in else, default taken */ \ | ||
281 | BEGIN_##TYPE##_SECTION \ | ||
282 | or 3,3,3; \ | ||
283 | or 3,3,3; \ | ||
284 | or 3,3,3; \ | ||
285 | ##TYPE##_SECTION_ELSE \ | ||
286 | or 5,5,5; \ | ||
287 | BEGIN_##TYPE##_SECTION_NESTED(95) \ | ||
288 | or 3,3,3; \ | ||
289 | END_##TYPE##_SECTION_NESTED(0, 1, 95) \ | ||
290 | or 5,5,5; \ | ||
291 | ALT_##TYPE##_SECTION_END(0, 0) \ | ||
292 | or 1,1,1; \ | ||
293 | or 1,1,1; \ | ||
294 | /* Alt section with nested section in else, else taken & nop */ \ | ||
295 | BEGIN_##TYPE##_SECTION \ | ||
296 | or 3,3,3; \ | ||
297 | or 3,3,3; \ | ||
298 | or 3,3,3; \ | ||
299 | ##TYPE##_SECTION_ELSE \ | ||
300 | or 5,5,5; \ | ||
301 | BEGIN_##TYPE##_SECTION_NESTED(95) \ | ||
302 | or 3,3,3; \ | ||
303 | END_##TYPE##_SECTION_NESTED(0, 1, 95) \ | ||
304 | or 5,5,5; \ | ||
305 | ALT_##TYPE##_SECTION_END(0, 1) \ | ||
306 | or 1,1,1; \ | ||
307 | or 1,1,1; \ | ||
308 | /* Feature section with nested alt section, default taken */ \ | ||
309 | BEGIN_##TYPE##_SECTION \ | ||
310 | or 2,2,2; \ | ||
311 | BEGIN_##TYPE##_SECTION_NESTED(95) \ | ||
312 | or 1,1,1; \ | ||
313 | ##TYPE##_SECTION_ELSE_NESTED(95) \ | ||
314 | or 5,5,5; \ | ||
315 | ALT_##TYPE##_SECTION_END_NESTED(0, 0, 95) \ | ||
316 | or 2,2,2; \ | ||
317 | END_##TYPE##_SECTION(0, 0) \ | ||
318 | or 1,1,1; \ | ||
319 | or 1,1,1; \ | ||
320 | /* Feature section with nested alt section, else taken */ \ | ||
321 | BEGIN_##TYPE##_SECTION \ | ||
322 | or 2,2,2; \ | ||
323 | BEGIN_##TYPE##_SECTION_NESTED(95) \ | ||
324 | or 1,1,1; \ | ||
325 | ##TYPE##_SECTION_ELSE_NESTED(95) \ | ||
326 | or 5,5,5; \ | ||
327 | ALT_##TYPE##_SECTION_END_NESTED(0, 1, 95) \ | ||
328 | or 2,2,2; \ | ||
329 | END_##TYPE##_SECTION(0, 0) \ | ||
330 | or 1,1,1; \ | ||
331 | or 1,1,1; \ | ||
332 | /* Feature section with nested alt section, all nop'ed */ \ | ||
333 | BEGIN_##TYPE##_SECTION \ | ||
334 | or 2,2,2; \ | ||
335 | BEGIN_##TYPE##_SECTION_NESTED(95) \ | ||
336 | or 1,1,1; \ | ||
337 | ##TYPE##_SECTION_ELSE_NESTED(95) \ | ||
338 | or 5,5,5; \ | ||
339 | ALT_##TYPE##_SECTION_END_NESTED(0, 0, 95) \ | ||
340 | or 2,2,2; \ | ||
341 | END_##TYPE##_SECTION(0, 1) \ | ||
342 | or 1,1,1; \ | ||
343 | or 1,1,1; \ | ||
344 | /* Nested alt sections, default with inner default taken */ \ | ||
345 | BEGIN_##TYPE##_SECTION \ | ||
346 | or 2,2,2; \ | ||
347 | BEGIN_##TYPE##_SECTION_NESTED(95) \ | ||
348 | or 1,1,1; \ | ||
349 | ##TYPE##_SECTION_ELSE_NESTED(95) \ | ||
350 | or 5,5,5; \ | ||
351 | ALT_##TYPE##_SECTION_END_NESTED(0, 0, 95) \ | ||
352 | or 2,2,2; \ | ||
353 | ##TYPE##_SECTION_ELSE \ | ||
354 | or 31,31,31; \ | ||
355 | BEGIN_##TYPE##_SECTION_NESTED(94) \ | ||
356 | or 5,5,5; \ | ||
357 | ##TYPE##_SECTION_ELSE_NESTED(94) \ | ||
358 | or 1,1,1; \ | ||
359 | ALT_##TYPE##_SECTION_END_NESTED(0, 0, 94) \ | ||
360 | or 31,31,31; \ | ||
361 | ALT_##TYPE##_SECTION_END(0, 0) \ | ||
362 | or 1,1,1; \ | ||
363 | or 1,1,1; \ | ||
364 | /* Nested alt sections, default with inner else taken */ \ | ||
365 | BEGIN_##TYPE##_SECTION \ | ||
366 | or 2,2,2; \ | ||
367 | BEGIN_##TYPE##_SECTION_NESTED(95) \ | ||
368 | or 1,1,1; \ | ||
369 | ##TYPE##_SECTION_ELSE_NESTED(95) \ | ||
370 | or 5,5,5; \ | ||
371 | ALT_##TYPE##_SECTION_END_NESTED(0, 1, 95) \ | ||
372 | or 2,2,2; \ | ||
373 | ##TYPE##_SECTION_ELSE \ | ||
374 | or 31,31,31; \ | ||
375 | BEGIN_##TYPE##_SECTION_NESTED(94) \ | ||
376 | or 5,5,5; \ | ||
377 | ##TYPE##_SECTION_ELSE_NESTED(94) \ | ||
378 | or 1,1,1; \ | ||
379 | ALT_##TYPE##_SECTION_END_NESTED(0, 0, 94) \ | ||
380 | or 31,31,31; \ | ||
381 | ALT_##TYPE##_SECTION_END(0, 0) \ | ||
382 | or 1,1,1; \ | ||
383 | or 1,1,1; \ | ||
384 | /* Nested alt sections, else with inner default taken */ \ | ||
385 | BEGIN_##TYPE##_SECTION \ | ||
386 | or 2,2,2; \ | ||
387 | BEGIN_##TYPE##_SECTION_NESTED(95) \ | ||
388 | or 1,1,1; \ | ||
389 | ##TYPE##_SECTION_ELSE_NESTED(95) \ | ||
390 | or 5,5,5; \ | ||
391 | ALT_##TYPE##_SECTION_END_NESTED(0, 1, 95) \ | ||
392 | or 2,2,2; \ | ||
393 | ##TYPE##_SECTION_ELSE \ | ||
394 | or 31,31,31; \ | ||
395 | BEGIN_##TYPE##_SECTION_NESTED(94) \ | ||
396 | or 5,5,5; \ | ||
397 | ##TYPE##_SECTION_ELSE_NESTED(94) \ | ||
398 | or 1,1,1; \ | ||
399 | ALT_##TYPE##_SECTION_END_NESTED(0, 0, 94) \ | ||
400 | or 31,31,31; \ | ||
401 | ALT_##TYPE##_SECTION_END(0, 1) \ | ||
402 | or 1,1,1; \ | ||
403 | or 1,1,1; \ | ||
404 | /* Nested alt sections, else with inner else taken */ \ | ||
405 | BEGIN_##TYPE##_SECTION \ | ||
406 | or 2,2,2; \ | ||
407 | BEGIN_##TYPE##_SECTION_NESTED(95) \ | ||
408 | or 1,1,1; \ | ||
409 | ##TYPE##_SECTION_ELSE_NESTED(95) \ | ||
410 | or 5,5,5; \ | ||
411 | ALT_##TYPE##_SECTION_END_NESTED(0, 1, 95) \ | ||
412 | or 2,2,2; \ | ||
413 | ##TYPE##_SECTION_ELSE \ | ||
414 | or 31,31,31; \ | ||
415 | BEGIN_##TYPE##_SECTION_NESTED(94) \ | ||
416 | or 5,5,5; \ | ||
417 | ##TYPE##_SECTION_ELSE_NESTED(94) \ | ||
418 | or 1,1,1; \ | ||
419 | ALT_##TYPE##_SECTION_END_NESTED(0, 1, 94) \ | ||
420 | or 31,31,31; \ | ||
421 | ALT_##TYPE##_SECTION_END(0, 1) \ | ||
422 | or 1,1,1; \ | ||
423 | or 1,1,1; \ | ||
424 | /* Nested alt sections, else can have large else case */ \ | ||
425 | BEGIN_##TYPE##_SECTION \ | ||
426 | or 2,2,2; \ | ||
427 | or 2,2,2; \ | ||
428 | or 2,2,2; \ | ||
429 | or 2,2,2; \ | ||
430 | ##TYPE##_SECTION_ELSE \ | ||
431 | BEGIN_##TYPE##_SECTION_NESTED(94) \ | ||
432 | or 5,5,5; \ | ||
433 | or 5,5,5; \ | ||
434 | or 5,5,5; \ | ||
435 | or 5,5,5; \ | ||
436 | ##TYPE##_SECTION_ELSE_NESTED(94) \ | ||
437 | or 1,1,1; \ | ||
438 | or 1,1,1; \ | ||
439 | or 1,1,1; \ | ||
440 | or 1,1,1; \ | ||
441 | ALT_##TYPE##_SECTION_END_NESTED(0, 1, 94) \ | ||
442 | ALT_##TYPE##_SECTION_END(0, 1) \ | ||
443 | or 1,1,1; \ | ||
444 | or 1,1,1; | ||
445 | |||
446 | #define MAKE_MACRO_TEST_EXPECTED(TYPE) \ | ||
447 | globl(ftr_fixup_test_ ##TYPE##_macros_expected) \ | ||
448 | or 1,1,1; \ | ||
449 | /* Basic test, this section should all be nop'ed */ \ | ||
450 | /* BEGIN_##TYPE##_SECTION */ \ | ||
451 | nop; \ | ||
452 | nop; \ | ||
453 | nop; \ | ||
454 | /* END_##TYPE##_SECTION(0, 1) */ \ | ||
455 | or 1,1,1; \ | ||
456 | or 1,1,1; \ | ||
457 | /* Basic test, this section should NOT be nop'ed */ \ | ||
458 | /* BEGIN_##TYPE##_SECTION */ \ | ||
459 | or 2,2,2; \ | ||
460 | or 2,2,2; \ | ||
461 | or 2,2,2; \ | ||
462 | /* END_##TYPE##_SECTION(0, 0) */ \ | ||
463 | or 1,1,1; \ | ||
464 | or 1,1,1; \ | ||
465 | /* Nesting test, inner section should be nop'ed */ \ | ||
466 | /* BEGIN_##TYPE##_SECTION */ \ | ||
467 | or 2,2,2; \ | ||
468 | or 2,2,2; \ | ||
469 | /* BEGIN_##TYPE##_SECTION_NESTED(80) */ \ | ||
470 | nop; \ | ||
471 | nop; \ | ||
472 | /* END_##TYPE##_SECTION_NESTED(0, 1, 80) */ \ | ||
473 | or 2,2,2; \ | ||
474 | or 2,2,2; \ | ||
475 | /* END_##TYPE##_SECTION(0, 0) */ \ | ||
476 | or 1,1,1; \ | ||
477 | or 1,1,1; \ | ||
478 | /* Nesting test, whole section should be nop'ed */ \ | ||
479 | /* NB. inner section is not nop'ed, but then entire outer is */ \ | ||
480 | /* BEGIN_##TYPE##_SECTION */ \ | ||
481 | nop; \ | ||
482 | nop; \ | ||
483 | /* BEGIN_##TYPE##_SECTION_NESTED(80) */ \ | ||
484 | nop; \ | ||
485 | nop; \ | ||
486 | /* END_##TYPE##_SECTION_NESTED(0, 0, 80) */ \ | ||
487 | nop; \ | ||
488 | nop; \ | ||
489 | /* END_##TYPE##_SECTION(0, 1) */ \ | ||
490 | or 1,1,1; \ | ||
491 | or 1,1,1; \ | ||
492 | /* Nesting test, none should be nop'ed */ \ | ||
493 | /* BEGIN_##TYPE##_SECTION */ \ | ||
494 | or 2,2,2; \ | ||
495 | or 2,2,2; \ | ||
496 | /* BEGIN_##TYPE##_SECTION_NESTED(80) */ \ | ||
497 | or 3,3,3; \ | ||
498 | or 3,3,3; \ | ||
499 | /* END_##TYPE##_SECTION_NESTED(0, 0, 80) */ \ | ||
500 | or 2,2,2; \ | ||
501 | or 2,2,2; \ | ||
502 | /* END_##TYPE##_SECTION(0, 0) */ \ | ||
503 | or 1,1,1; \ | ||
504 | or 1,1,1; \ | ||
505 | /* Basic alt section test, default case should be taken */ \ | ||
506 | /* BEGIN_##TYPE##_SECTION */ \ | ||
507 | or 3,3,3; \ | ||
508 | or 3,3,3; \ | ||
509 | or 3,3,3; \ | ||
510 | /* ##TYPE##_SECTION_ELSE */ \ | ||
511 | /* or 5,5,5; */ \ | ||
512 | /* or 5,5,5; */ \ | ||
513 | /* ALT_##TYPE##_SECTION_END(0, 0) */ \ | ||
514 | or 1,1,1; \ | ||
515 | or 1,1,1; \ | ||
516 | /* Basic alt section test, else case should be taken */ \ | ||
517 | /* BEGIN_##TYPE##_SECTION */ \ | ||
518 | /* or 3,3,3; */ \ | ||
519 | /* or 3,3,3; */ \ | ||
520 | /* or 3,3,3; */ \ | ||
521 | /* ##TYPE##_SECTION_ELSE */ \ | ||
522 | or 31,31,31; \ | ||
523 | or 31,31,31; \ | ||
524 | or 31,31,31; \ | ||
525 | /* ALT_##TYPE##_SECTION_END(0, 1) */ \ | ||
526 | or 1,1,1; \ | ||
527 | or 1,1,1; \ | ||
528 | /* Alt with smaller else case, should be padded with nops */ \ | ||
529 | /* BEGIN_##TYPE##_SECTION */ \ | ||
530 | /* or 3,3,3; */ \ | ||
531 | /* or 3,3,3; */ \ | ||
532 | /* or 3,3,3; */ \ | ||
533 | /* ##TYPE##_SECTION_ELSE */ \ | ||
534 | or 31,31,31; \ | ||
535 | nop; \ | ||
536 | nop; \ | ||
537 | /* ALT_##TYPE##_SECTION_END(0, 1) */ \ | ||
538 | or 1,1,1; \ | ||
539 | or 1,1,1; \ | ||
540 | /* Alt section with nested section in default case */ \ | ||
541 | /* Default case should be taken, with nop'ed inner section */ \ | ||
542 | /* BEGIN_##TYPE##_SECTION */ \ | ||
543 | or 3,3,3; \ | ||
544 | /* BEGIN_##TYPE##_SECTION_NESTED(95) */ \ | ||
545 | nop; \ | ||
546 | nop; \ | ||
547 | /* END_##TYPE##_SECTION_NESTED(0, 1, 95) */ \ | ||
548 | or 3,3,3; \ | ||
549 | /* ##TYPE##_SECTION_ELSE */ \ | ||
550 | /* or 2,2,2; */ \ | ||
551 | /* or 2,2,2; */ \ | ||
552 | /* ALT_##TYPE##_SECTION_END(0, 0) */ \ | ||
553 | or 1,1,1; \ | ||
554 | or 1,1,1; \ | ||
555 | /* Alt section with nested section in else, default taken */ \ | ||
556 | /* BEGIN_##TYPE##_SECTION */ \ | ||
557 | or 3,3,3; \ | ||
558 | or 3,3,3; \ | ||
559 | or 3,3,3; \ | ||
560 | /* ##TYPE##_SECTION_ELSE */ \ | ||
561 | /* or 5,5,5; */ \ | ||
562 | /* BEGIN_##TYPE##_SECTION_NESTED(95) */ \ | ||
563 | /* or 3,3,3; */ \ | ||
564 | /* END_##TYPE##_SECTION_NESTED(0, 1, 95) */ \ | ||
565 | /* or 5,5,5; */ \ | ||
566 | /* ALT_##TYPE##_SECTION_END(0, 0) */ \ | ||
567 | or 1,1,1; \ | ||
568 | or 1,1,1; \ | ||
569 | /* Alt section with nested section in else, else taken & nop */ \ | ||
570 | /* BEGIN_##TYPE##_SECTION */ \ | ||
571 | /* or 3,3,3; */ \ | ||
572 | /* or 3,3,3; */ \ | ||
573 | /* or 3,3,3; */ \ | ||
574 | /* ##TYPE##_SECTION_ELSE */ \ | ||
575 | or 5,5,5; \ | ||
576 | /* BEGIN_##TYPE##_SECTION_NESTED(95) */ \ | ||
577 | nop; \ | ||
578 | /* END_##TYPE##_SECTION_NESTED(0, 1, 95) */ \ | ||
579 | or 5,5,5; \ | ||
580 | /* ALT_##TYPE##_SECTION_END(0, 1) */ \ | ||
581 | or 1,1,1; \ | ||
582 | or 1,1,1; \ | ||
583 | /* Feature section with nested alt section, default taken */ \ | ||
584 | /* BEGIN_##TYPE##_SECTION */ \ | ||
585 | or 2,2,2; \ | ||
586 | /* BEGIN_##TYPE##_SECTION_NESTED(95) */ \ | ||
587 | or 1,1,1; \ | ||
588 | /* ##TYPE##_SECTION_ELSE_NESTED(95) */ \ | ||
589 | /* or 5,5,5; */ \ | ||
590 | /* ALT_##TYPE##_SECTION_END_NESTED(0, 0, 95) */ \ | ||
591 | or 2,2,2; \ | ||
592 | /* END_##TYPE##_SECTION(0, 0) */ \ | ||
593 | or 1,1,1; \ | ||
594 | or 1,1,1; \ | ||
595 | /* Feature section with nested alt section, else taken */ \ | ||
596 | /* BEGIN_##TYPE##_SECTION */ \ | ||
597 | or 2,2,2; \ | ||
598 | /* BEGIN_##TYPE##_SECTION_NESTED(95) */ \ | ||
599 | /* or 1,1,1; */ \ | ||
600 | /* ##TYPE##_SECTION_ELSE_NESTED(95) */ \ | ||
601 | or 5,5,5; \ | ||
602 | /* ALT_##TYPE##_SECTION_END_NESTED(0, 1, 95) */ \ | ||
603 | or 2,2,2; \ | ||
604 | /* END_##TYPE##_SECTION(0, 0) */ \ | ||
605 | or 1,1,1; \ | ||
606 | or 1,1,1; \ | ||
607 | /* Feature section with nested alt section, all nop'ed */ \ | ||
608 | /* BEGIN_##TYPE##_SECTION */ \ | ||
609 | nop; \ | ||
610 | /* BEGIN_##TYPE##_SECTION_NESTED(95) */ \ | ||
611 | nop; \ | ||
612 | /* ##TYPE##_SECTION_ELSE_NESTED(95) */ \ | ||
613 | /* or 5,5,5; */ \ | ||
614 | /* ALT_##TYPE##_SECTION_END_NESTED(0, 0, 95) */ \ | ||
615 | nop; \ | ||
616 | /* END_##TYPE##_SECTION(0, 1) */ \ | ||
617 | or 1,1,1; \ | ||
618 | or 1,1,1; \ | ||
619 | /* Nested alt sections, default with inner default taken */ \ | ||
620 | /* BEGIN_##TYPE##_SECTION */ \ | ||
621 | or 2,2,2; \ | ||
622 | /* BEGIN_##TYPE##_SECTION_NESTED(95) */ \ | ||
623 | or 1,1,1; \ | ||
624 | /* ##TYPE##_SECTION_ELSE_NESTED(95) */ \ | ||
625 | /* or 5,5,5; */ \ | ||
626 | /* ALT_##TYPE##_SECTION_END_NESTED(0, 0, 95) */ \ | ||
627 | or 2,2,2; \ | ||
628 | /* ##TYPE##_SECTION_ELSE */ \ | ||
629 | /* or 31,31,31; */ \ | ||
630 | /* BEGIN_##TYPE##_SECTION_NESTED(94) */ \ | ||
631 | /* or 5,5,5; */ \ | ||
632 | /* ##TYPE##_SECTION_ELSE_NESTED(94) */ \ | ||
633 | /* or 1,1,1; */ \ | ||
634 | /* ALT_##TYPE##_SECTION_END_NESTED(0, 0, 94) */ \ | ||
635 | /* or 31,31,31; */ \ | ||
636 | /* ALT_##TYPE##_SECTION_END(0, 0) */ \ | ||
637 | or 1,1,1; \ | ||
638 | or 1,1,1; \ | ||
639 | /* Nested alt sections, default with inner else taken */ \ | ||
640 | /* BEGIN_##TYPE##_SECTION */ \ | ||
641 | or 2,2,2; \ | ||
642 | /* BEGIN_##TYPE##_SECTION_NESTED(95) */ \ | ||
643 | /* or 1,1,1; */ \ | ||
644 | /* ##TYPE##_SECTION_ELSE_NESTED(95) */ \ | ||
645 | or 5,5,5; \ | ||
646 | /* ALT_##TYPE##_SECTION_END_NESTED(0, 1, 95) */ \ | ||
647 | or 2,2,2; \ | ||
648 | /* ##TYPE##_SECTION_ELSE */ \ | ||
649 | /* or 31,31,31; */ \ | ||
650 | /* BEGIN_##TYPE##_SECTION_NESTED(94) */ \ | ||
651 | /* or 5,5,5; */ \ | ||
652 | /* ##TYPE##_SECTION_ELSE_NESTED(94) */ \ | ||
653 | /* or 1,1,1; */ \ | ||
654 | /* ALT_##TYPE##_SECTION_END_NESTED(0, 0, 94) */ \ | ||
655 | /* or 31,31,31; */ \ | ||
656 | /* ALT_##TYPE##_SECTION_END(0, 0) */ \ | ||
657 | or 1,1,1; \ | ||
658 | or 1,1,1; \ | ||
659 | /* Nested alt sections, else with inner default taken */ \ | ||
660 | /* BEGIN_##TYPE##_SECTION */ \ | ||
661 | /* or 2,2,2; */ \ | ||
662 | /* BEGIN_##TYPE##_SECTION_NESTED(95) */ \ | ||
663 | /* or 1,1,1; */ \ | ||
664 | /* ##TYPE##_SECTION_ELSE_NESTED(95) */ \ | ||
665 | /* or 5,5,5; */ \ | ||
666 | /* ALT_##TYPE##_SECTION_END_NESTED(0, 1, 95) */ \ | ||
667 | /* or 2,2,2; */ \ | ||
668 | /* ##TYPE##_SECTION_ELSE */ \ | ||
669 | or 31,31,31; \ | ||
670 | /* BEGIN_##TYPE##_SECTION_NESTED(94) */ \ | ||
671 | or 5,5,5; \ | ||
672 | /* ##TYPE##_SECTION_ELSE_NESTED(94) */ \ | ||
673 | /* or 1,1,1; */ \ | ||
674 | /* ALT_##TYPE##_SECTION_END_NESTED(0, 0, 94) */ \ | ||
675 | or 31,31,31; \ | ||
676 | /* ALT_##TYPE##_SECTION_END(0, 1) */ \ | ||
677 | or 1,1,1; \ | ||
678 | or 1,1,1; \ | ||
679 | /* Nested alt sections, else with inner else taken */ \ | ||
680 | /* BEGIN_##TYPE##_SECTION */ \ | ||
681 | /* or 2,2,2; */ \ | ||
682 | /* BEGIN_##TYPE##_SECTION_NESTED(95) */ \ | ||
683 | /* or 1,1,1; */ \ | ||
684 | /* ##TYPE##_SECTION_ELSE_NESTED(95) */ \ | ||
685 | /* or 5,5,5; */ \ | ||
686 | /* ALT_##TYPE##_SECTION_END_NESTED(0, 1, 95) */ \ | ||
687 | /* or 2,2,2; */ \ | ||
688 | /* ##TYPE##_SECTION_ELSE */ \ | ||
689 | or 31,31,31; \ | ||
690 | /* BEGIN_##TYPE##_SECTION_NESTED(94) */ \ | ||
691 | /* or 5,5,5; */ \ | ||
692 | /* ##TYPE##_SECTION_ELSE_NESTED(94) */ \ | ||
693 | or 1,1,1; \ | ||
694 | /* ALT_##TYPE##_SECTION_END_NESTED(0, 1, 94) */ \ | ||
695 | or 31,31,31; \ | ||
696 | /* ALT_##TYPE##_SECTION_END(0, 1) */ \ | ||
697 | or 1,1,1; \ | ||
698 | or 1,1,1; \ | ||
699 | /* Nested alt sections, else can have large else case */ \ | ||
700 | /* BEGIN_##TYPE##_SECTION */ \ | ||
701 | /* or 2,2,2; */ \ | ||
702 | /* or 2,2,2; */ \ | ||
703 | /* or 2,2,2; */ \ | ||
704 | /* or 2,2,2; */ \ | ||
705 | /* ##TYPE##_SECTION_ELSE */ \ | ||
706 | /* BEGIN_##TYPE##_SECTION_NESTED(94) */ \ | ||
707 | /* or 5,5,5; */ \ | ||
708 | /* or 5,5,5; */ \ | ||
709 | /* or 5,5,5; */ \ | ||
710 | /* or 5,5,5; */ \ | ||
711 | /* ##TYPE##_SECTION_ELSE_NESTED(94) */ \ | ||
712 | or 1,1,1; \ | ||
713 | or 1,1,1; \ | ||
714 | or 1,1,1; \ | ||
715 | or 1,1,1; \ | ||
716 | /* ALT_##TYPE##_SECTION_END_NESTED(0, 1, 94) */ \ | ||
717 | /* ALT_##TYPE##_SECTION_END(0, 1) */ \ | ||
718 | or 1,1,1; \ | ||
719 | or 1,1,1; | ||
720 | |||
721 | MAKE_MACRO_TEST(FTR); | ||
722 | MAKE_MACRO_TEST_EXPECTED(FTR); | ||
723 | |||
724 | #ifdef CONFIG_PPC64 | ||
725 | MAKE_MACRO_TEST(FW_FTR); | ||
726 | MAKE_MACRO_TEST_EXPECTED(FW_FTR); | ||
727 | #endif | ||
diff --git a/arch/powerpc/lib/feature-fixups.c b/arch/powerpc/lib/feature-fixups.c index 174c1eba9ac8..48e1ed89052d 100644 --- a/arch/powerpc/lib/feature-fixups.c +++ b/arch/powerpc/lib/feature-fixups.c | |||
@@ -13,6 +13,8 @@ | |||
13 | */ | 13 | */ |
14 | 14 | ||
15 | #include <linux/kernel.h> | 15 | #include <linux/kernel.h> |
16 | #include <linux/string.h> | ||
17 | #include <linux/init.h> | ||
16 | #include <asm/cputable.h> | 18 | #include <asm/cputable.h> |
17 | #include <asm/code-patching.h> | 19 | #include <asm/code-patching.h> |
18 | 20 | ||
@@ -107,3 +109,207 @@ void do_feature_fixups(unsigned long value, void *fixup_start, void *fixup_end) | |||
107 | } | 109 | } |
108 | } | 110 | } |
109 | } | 111 | } |
112 | |||
113 | #ifdef CONFIG_FTR_FIXUP_SELFTEST | ||
114 | |||
115 | #define check(x) \ | ||
116 | if (!(x)) printk("feature-fixups: test failed at line %d\n", __LINE__); | ||
117 | |||
118 | /* This must be after the text it fixes up, vmlinux.lds.S enforces that atm */ | ||
119 | static struct fixup_entry fixup; | ||
120 | |||
121 | static long calc_offset(struct fixup_entry *entry, unsigned int *p) | ||
122 | { | ||
123 | return (unsigned long)p - (unsigned long)entry; | ||
124 | } | ||
125 | |||
126 | void test_basic_patching(void) | ||
127 | { | ||
128 | extern unsigned int ftr_fixup_test1; | ||
129 | extern unsigned int end_ftr_fixup_test1; | ||
130 | extern unsigned int ftr_fixup_test1_orig; | ||
131 | extern unsigned int ftr_fixup_test1_expected; | ||
132 | int size = &end_ftr_fixup_test1 - &ftr_fixup_test1; | ||
133 | |||
134 | fixup.value = fixup.mask = 8; | ||
135 | fixup.start_off = calc_offset(&fixup, &ftr_fixup_test1 + 1); | ||
136 | fixup.end_off = calc_offset(&fixup, &ftr_fixup_test1 + 2); | ||
137 | fixup.alt_start_off = fixup.alt_end_off = 0; | ||
138 | |||
139 | /* Sanity check */ | ||
140 | check(memcmp(&ftr_fixup_test1, &ftr_fixup_test1_orig, size) == 0); | ||
141 | |||
142 | /* Check we don't patch if the value matches */ | ||
143 | patch_feature_section(8, &fixup); | ||
144 | check(memcmp(&ftr_fixup_test1, &ftr_fixup_test1_orig, size) == 0); | ||
145 | |||
146 | /* Check we do patch if the value doesn't match */ | ||
147 | patch_feature_section(0, &fixup); | ||
148 | check(memcmp(&ftr_fixup_test1, &ftr_fixup_test1_expected, size) == 0); | ||
149 | |||
150 | /* Check we do patch if the mask doesn't match */ | ||
151 | memcpy(&ftr_fixup_test1, &ftr_fixup_test1_orig, size); | ||
152 | check(memcmp(&ftr_fixup_test1, &ftr_fixup_test1_orig, size) == 0); | ||
153 | patch_feature_section(~8, &fixup); | ||
154 | check(memcmp(&ftr_fixup_test1, &ftr_fixup_test1_expected, size) == 0); | ||
155 | } | ||
156 | |||
157 | static void test_alternative_patching(void) | ||
158 | { | ||
159 | extern unsigned int ftr_fixup_test2; | ||
160 | extern unsigned int end_ftr_fixup_test2; | ||
161 | extern unsigned int ftr_fixup_test2_orig; | ||
162 | extern unsigned int ftr_fixup_test2_alt; | ||
163 | extern unsigned int ftr_fixup_test2_expected; | ||
164 | int size = &end_ftr_fixup_test2 - &ftr_fixup_test2; | ||
165 | |||
166 | fixup.value = fixup.mask = 0xF; | ||
167 | fixup.start_off = calc_offset(&fixup, &ftr_fixup_test2 + 1); | ||
168 | fixup.end_off = calc_offset(&fixup, &ftr_fixup_test2 + 2); | ||
169 | fixup.alt_start_off = calc_offset(&fixup, &ftr_fixup_test2_alt); | ||
170 | fixup.alt_end_off = calc_offset(&fixup, &ftr_fixup_test2_alt + 1); | ||
171 | |||
172 | /* Sanity check */ | ||
173 | check(memcmp(&ftr_fixup_test2, &ftr_fixup_test2_orig, size) == 0); | ||
174 | |||
175 | /* Check we don't patch if the value matches */ | ||
176 | patch_feature_section(0xF, &fixup); | ||
177 | check(memcmp(&ftr_fixup_test2, &ftr_fixup_test2_orig, size) == 0); | ||
178 | |||
179 | /* Check we do patch if the value doesn't match */ | ||
180 | patch_feature_section(0, &fixup); | ||
181 | check(memcmp(&ftr_fixup_test2, &ftr_fixup_test2_expected, size) == 0); | ||
182 | |||
183 | /* Check we do patch if the mask doesn't match */ | ||
184 | memcpy(&ftr_fixup_test2, &ftr_fixup_test2_orig, size); | ||
185 | check(memcmp(&ftr_fixup_test2, &ftr_fixup_test2_orig, size) == 0); | ||
186 | patch_feature_section(~0xF, &fixup); | ||
187 | check(memcmp(&ftr_fixup_test2, &ftr_fixup_test2_expected, size) == 0); | ||
188 | } | ||
189 | |||
190 | static void test_alternative_case_too_big(void) | ||
191 | { | ||
192 | extern unsigned int ftr_fixup_test3; | ||
193 | extern unsigned int end_ftr_fixup_test3; | ||
194 | extern unsigned int ftr_fixup_test3_orig; | ||
195 | extern unsigned int ftr_fixup_test3_alt; | ||
196 | int size = &end_ftr_fixup_test3 - &ftr_fixup_test3; | ||
197 | |||
198 | fixup.value = fixup.mask = 0xC; | ||
199 | fixup.start_off = calc_offset(&fixup, &ftr_fixup_test3 + 1); | ||
200 | fixup.end_off = calc_offset(&fixup, &ftr_fixup_test3 + 2); | ||
201 | fixup.alt_start_off = calc_offset(&fixup, &ftr_fixup_test3_alt); | ||
202 | fixup.alt_end_off = calc_offset(&fixup, &ftr_fixup_test3_alt + 2); | ||
203 | |||
204 | /* Sanity check */ | ||
205 | check(memcmp(&ftr_fixup_test3, &ftr_fixup_test3_orig, size) == 0); | ||
206 | |||
207 | /* Expect nothing to be patched, and the error returned to us */ | ||
208 | check(patch_feature_section(0xF, &fixup) == 1); | ||
209 | check(memcmp(&ftr_fixup_test3, &ftr_fixup_test3_orig, size) == 0); | ||
210 | check(patch_feature_section(0, &fixup) == 1); | ||
211 | check(memcmp(&ftr_fixup_test3, &ftr_fixup_test3_orig, size) == 0); | ||
212 | check(patch_feature_section(~0xF, &fixup) == 1); | ||
213 | check(memcmp(&ftr_fixup_test3, &ftr_fixup_test3_orig, size) == 0); | ||
214 | } | ||
215 | |||
216 | static void test_alternative_case_too_small(void) | ||
217 | { | ||
218 | extern unsigned int ftr_fixup_test4; | ||
219 | extern unsigned int end_ftr_fixup_test4; | ||
220 | extern unsigned int ftr_fixup_test4_orig; | ||
221 | extern unsigned int ftr_fixup_test4_alt; | ||
222 | extern unsigned int ftr_fixup_test4_expected; | ||
223 | int size = &end_ftr_fixup_test4 - &ftr_fixup_test4; | ||
224 | unsigned long flag; | ||
225 | |||
226 | /* Check a high-bit flag */ | ||
227 | flag = 1UL << ((sizeof(unsigned long) - 1) * 8); | ||
228 | fixup.value = fixup.mask = flag; | ||
229 | fixup.start_off = calc_offset(&fixup, &ftr_fixup_test4 + 1); | ||
230 | fixup.end_off = calc_offset(&fixup, &ftr_fixup_test4 + 5); | ||
231 | fixup.alt_start_off = calc_offset(&fixup, &ftr_fixup_test4_alt); | ||
232 | fixup.alt_end_off = calc_offset(&fixup, &ftr_fixup_test4_alt + 2); | ||
233 | |||
234 | /* Sanity check */ | ||
235 | check(memcmp(&ftr_fixup_test4, &ftr_fixup_test4_orig, size) == 0); | ||
236 | |||
237 | /* Check we don't patch if the value matches */ | ||
238 | patch_feature_section(flag, &fixup); | ||
239 | check(memcmp(&ftr_fixup_test4, &ftr_fixup_test4_orig, size) == 0); | ||
240 | |||
241 | /* Check we do patch if the value doesn't match */ | ||
242 | patch_feature_section(0, &fixup); | ||
243 | check(memcmp(&ftr_fixup_test4, &ftr_fixup_test4_expected, size) == 0); | ||
244 | |||
245 | /* Check we do patch if the mask doesn't match */ | ||
246 | memcpy(&ftr_fixup_test4, &ftr_fixup_test4_orig, size); | ||
247 | check(memcmp(&ftr_fixup_test4, &ftr_fixup_test4_orig, size) == 0); | ||
248 | patch_feature_section(~flag, &fixup); | ||
249 | check(memcmp(&ftr_fixup_test4, &ftr_fixup_test4_expected, size) == 0); | ||
250 | } | ||
251 | |||
252 | static void test_alternative_case_with_branch(void) | ||
253 | { | ||
254 | extern unsigned int ftr_fixup_test5; | ||
255 | extern unsigned int end_ftr_fixup_test5; | ||
256 | extern unsigned int ftr_fixup_test5_expected; | ||
257 | int size = &end_ftr_fixup_test5 - &ftr_fixup_test5; | ||
258 | |||
259 | check(memcmp(&ftr_fixup_test5, &ftr_fixup_test5_expected, size) == 0); | ||
260 | } | ||
261 | |||
262 | static void test_alternative_case_with_external_branch(void) | ||
263 | { | ||
264 | extern unsigned int ftr_fixup_test6; | ||
265 | extern unsigned int end_ftr_fixup_test6; | ||
266 | extern unsigned int ftr_fixup_test6_expected; | ||
267 | int size = &end_ftr_fixup_test6 - &ftr_fixup_test6; | ||
268 | |||
269 | check(memcmp(&ftr_fixup_test6, &ftr_fixup_test6_expected, size) == 0); | ||
270 | } | ||
271 | |||
272 | static void test_cpu_macros(void) | ||
273 | { | ||
274 | extern void ftr_fixup_test_FTR_macros; | ||
275 | extern void ftr_fixup_test_FTR_macros_expected; | ||
276 | unsigned long size = &ftr_fixup_test_FTR_macros_expected - | ||
277 | &ftr_fixup_test_FTR_macros; | ||
278 | |||
279 | /* The fixups have already been done for us during boot */ | ||
280 | check(memcmp(&ftr_fixup_test_FTR_macros, | ||
281 | &ftr_fixup_test_FTR_macros_expected, size) == 0); | ||
282 | } | ||
283 | |||
284 | static void test_fw_macros(void) | ||
285 | { | ||
286 | #ifdef CONFIG_PPC64 | ||
287 | extern void ftr_fixup_test_FW_FTR_macros; | ||
288 | extern void ftr_fixup_test_FW_FTR_macros_expected; | ||
289 | unsigned long size = &ftr_fixup_test_FW_FTR_macros_expected - | ||
290 | &ftr_fixup_test_FW_FTR_macros; | ||
291 | |||
292 | /* The fixups have already been done for us during boot */ | ||
293 | check(memcmp(&ftr_fixup_test_FW_FTR_macros, | ||
294 | &ftr_fixup_test_FW_FTR_macros_expected, size) == 0); | ||
295 | #endif | ||
296 | } | ||
297 | |||
298 | static int __init test_feature_fixups(void) | ||
299 | { | ||
300 | printk(KERN_DEBUG "Running feature fixup self-tests ...\n"); | ||
301 | |||
302 | test_basic_patching(); | ||
303 | test_alternative_patching(); | ||
304 | test_alternative_case_too_big(); | ||
305 | test_alternative_case_too_small(); | ||
306 | test_alternative_case_with_branch(); | ||
307 | test_alternative_case_with_external_branch(); | ||
308 | test_cpu_macros(); | ||
309 | test_fw_macros(); | ||
310 | |||
311 | return 0; | ||
312 | } | ||
313 | late_initcall(test_feature_fixups); | ||
314 | |||
315 | #endif /* CONFIG_FTR_FIXUP_SELFTEST */ | ||