aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/lib
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/lib')
-rw-r--r--arch/powerpc/lib/Makefile1
-rw-r--r--arch/powerpc/lib/feature-fixups-test.S727
-rw-r--r--arch/powerpc/lib/feature-fixups.c206
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
28obj-y += code-patching.o 28obj-y += code-patching.o
29obj-y += feature-fixups.o 29obj-y += feature-fixups.o
30obj-$(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; \
18x:
19
20globl(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
25globl(end_ftr_fixup_test1)
26
27globl(ftr_fixup_test1_orig)
28 or 1,1,1
29 or 2,2,2
30 or 3,3,3
31
32globl(ftr_fixup_test1_expected)
33 or 1,1,1
34 nop
35 or 3,3,3
36
37globl(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
42globl(end_ftr_fixup_test2)
43
44globl(ftr_fixup_test2_orig)
45 or 1,1,1
46 or 2,2,2
47 or 3,3,3
48
49globl(ftr_fixup_test2_alt)
50 or 31,31,31
51
52globl(ftr_fixup_test2_expected)
53 or 1,1,1
54 or 31,31,31
55 or 3,3,3
56
57globl(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
62globl(end_ftr_fixup_test3)
63
64globl(ftr_fixup_test3_orig)
65 or 1,1,1
66 or 2,2,2
67 or 3,3,3
68
69globl(ftr_fixup_test3_alt)
70 or 31,31,31
71 or 31,31,31
72
73globl(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
81globl(end_ftr_fixup_test4)
82
83globl(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
91globl(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
99globl(ftr_fixup_test4_alt)
100 or 31,31,31
101 or 31,31,31
102
103
104globl(ftr_fixup_test5)
105 or 1,1,1
106BEGIN_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
114FTR_SECTION_ELSE
1152: b 3f
1163: or 5,5,5
117 beq 3b
118 b 1f
119 or 6,6,6
120 b 2b
1211: bdnz 3b
122ALT_FTR_SECTION_END(0, 1)
123 or 1,1,1
124
125globl(end_ftr_fixup_test5)
126
127globl(ftr_fixup_test5_expected)
128 or 1,1,1
1292: b 3f
1303: or 5,5,5
131 beq 3b
132 b 1f
133 or 6,6,6
134 b 2b
1351: bdnz 3b
136 or 1,1,1
137
138globl(ftr_fixup_test6)
1391: or 1,1,1
140BEGIN_FTR_SECTION
141 or 5,5,5
1422: cmpdi r3,0
143 beq 4f
144 blt 2b
145 b 1b
146 b 4f
147FTR_SECTION_ELSE
1482: or 2,2,2
149 cmpdi r3,1
150 beq 3f
151 blt 2b
152 b 3f
153 b 1b
154ALT_FTR_SECTION_END(0, 1)
1553: or 1,1,1
156 or 2,2,2
1574: or 3,3,3
158
159globl(end_ftr_fixup_test6)
160
161globl(ftr_fixup_test6_expected)
1621: or 1,1,1
1632: or 2,2,2
164 cmpdi r3,1
165 beq 3f
166 blt 2b
167 b 3f
168 b 1b
1692: or 1,1,1
170 or 2,2,2
1713: or 3,3,3
172
173
174#define MAKE_MACRO_TEST(TYPE) \
175globl(ftr_fixup_test_ ##TYPE##_macros) \
176 or 1,1,1; \
177 /* Basic test, this section should all be nop'ed */ \
178BEGIN_##TYPE##_SECTION \
179 or 2,2,2; \
180 or 2,2,2; \
181 or 2,2,2; \
182END_##TYPE##_SECTION(0, 1) \
183 or 1,1,1; \
184 or 1,1,1; \
185 /* Basic test, this section should NOT be nop'ed */ \
186BEGIN_##TYPE##_SECTION \
187 or 2,2,2; \
188 or 2,2,2; \
189 or 2,2,2; \
190END_##TYPE##_SECTION(0, 0) \
191 or 1,1,1; \
192 or 1,1,1; \
193 /* Nesting test, inner section should be nop'ed */ \
194BEGIN_##TYPE##_SECTION \
195 or 2,2,2; \
196 or 2,2,2; \
197BEGIN_##TYPE##_SECTION_NESTED(80) \
198 or 3,3,3; \
199 or 3,3,3; \
200END_##TYPE##_SECTION_NESTED(0, 1, 80) \
201 or 2,2,2; \
202 or 2,2,2; \
203END_##TYPE##_SECTION(0, 0) \
204 or 1,1,1; \
205 or 1,1,1; \
206 /* Nesting test, whole section should be nop'ed */ \
207BEGIN_##TYPE##_SECTION \
208 or 2,2,2; \
209 or 2,2,2; \
210BEGIN_##TYPE##_SECTION_NESTED(80) \
211 or 3,3,3; \
212 or 3,3,3; \
213END_##TYPE##_SECTION_NESTED(0, 0, 80) \
214 or 2,2,2; \
215 or 2,2,2; \
216END_##TYPE##_SECTION(0, 1) \
217 or 1,1,1; \
218 or 1,1,1; \
219 /* Nesting test, none should be nop'ed */ \
220BEGIN_##TYPE##_SECTION \
221 or 2,2,2; \
222 or 2,2,2; \
223BEGIN_##TYPE##_SECTION_NESTED(80) \
224 or 3,3,3; \
225 or 3,3,3; \
226END_##TYPE##_SECTION_NESTED(0, 0, 80) \
227 or 2,2,2; \
228 or 2,2,2; \
229END_##TYPE##_SECTION(0, 0) \
230 or 1,1,1; \
231 or 1,1,1; \
232 /* Basic alt section test, default case should be taken */ \
233BEGIN_##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; \
240ALT_##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 */ \
244BEGIN_##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; \
252ALT_##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 */ \
256BEGIN_##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; \
262ALT_##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 */ \
267BEGIN_##TYPE##_SECTION \
268 or 3,3,3; \
269BEGIN_##TYPE##_SECTION_NESTED(95) \
270 or 3,3,3; \
271 or 3,3,3; \
272END_##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; \
277ALT_##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 */ \
281BEGIN_##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; \
287BEGIN_##TYPE##_SECTION_NESTED(95) \
288 or 3,3,3; \
289END_##TYPE##_SECTION_NESTED(0, 1, 95) \
290 or 5,5,5; \
291ALT_##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 */ \
295BEGIN_##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; \
301BEGIN_##TYPE##_SECTION_NESTED(95) \
302 or 3,3,3; \
303END_##TYPE##_SECTION_NESTED(0, 1, 95) \
304 or 5,5,5; \
305ALT_##TYPE##_SECTION_END(0, 1) \
306 or 1,1,1; \
307 or 1,1,1; \
308 /* Feature section with nested alt section, default taken */ \
309BEGIN_##TYPE##_SECTION \
310 or 2,2,2; \
311BEGIN_##TYPE##_SECTION_NESTED(95) \
312 or 1,1,1; \
313##TYPE##_SECTION_ELSE_NESTED(95) \
314 or 5,5,5; \
315ALT_##TYPE##_SECTION_END_NESTED(0, 0, 95) \
316 or 2,2,2; \
317END_##TYPE##_SECTION(0, 0) \
318 or 1,1,1; \
319 or 1,1,1; \
320 /* Feature section with nested alt section, else taken */ \
321BEGIN_##TYPE##_SECTION \
322 or 2,2,2; \
323BEGIN_##TYPE##_SECTION_NESTED(95) \
324 or 1,1,1; \
325##TYPE##_SECTION_ELSE_NESTED(95) \
326 or 5,5,5; \
327ALT_##TYPE##_SECTION_END_NESTED(0, 1, 95) \
328 or 2,2,2; \
329END_##TYPE##_SECTION(0, 0) \
330 or 1,1,1; \
331 or 1,1,1; \
332 /* Feature section with nested alt section, all nop'ed */ \
333BEGIN_##TYPE##_SECTION \
334 or 2,2,2; \
335BEGIN_##TYPE##_SECTION_NESTED(95) \
336 or 1,1,1; \
337##TYPE##_SECTION_ELSE_NESTED(95) \
338 or 5,5,5; \
339ALT_##TYPE##_SECTION_END_NESTED(0, 0, 95) \
340 or 2,2,2; \
341END_##TYPE##_SECTION(0, 1) \
342 or 1,1,1; \
343 or 1,1,1; \
344 /* Nested alt sections, default with inner default taken */ \
345BEGIN_##TYPE##_SECTION \
346 or 2,2,2; \
347BEGIN_##TYPE##_SECTION_NESTED(95) \
348 or 1,1,1; \
349##TYPE##_SECTION_ELSE_NESTED(95) \
350 or 5,5,5; \
351ALT_##TYPE##_SECTION_END_NESTED(0, 0, 95) \
352 or 2,2,2; \
353##TYPE##_SECTION_ELSE \
354 or 31,31,31; \
355BEGIN_##TYPE##_SECTION_NESTED(94) \
356 or 5,5,5; \
357##TYPE##_SECTION_ELSE_NESTED(94) \
358 or 1,1,1; \
359ALT_##TYPE##_SECTION_END_NESTED(0, 0, 94) \
360 or 31,31,31; \
361ALT_##TYPE##_SECTION_END(0, 0) \
362 or 1,1,1; \
363 or 1,1,1; \
364 /* Nested alt sections, default with inner else taken */ \
365BEGIN_##TYPE##_SECTION \
366 or 2,2,2; \
367BEGIN_##TYPE##_SECTION_NESTED(95) \
368 or 1,1,1; \
369##TYPE##_SECTION_ELSE_NESTED(95) \
370 or 5,5,5; \
371ALT_##TYPE##_SECTION_END_NESTED(0, 1, 95) \
372 or 2,2,2; \
373##TYPE##_SECTION_ELSE \
374 or 31,31,31; \
375BEGIN_##TYPE##_SECTION_NESTED(94) \
376 or 5,5,5; \
377##TYPE##_SECTION_ELSE_NESTED(94) \
378 or 1,1,1; \
379ALT_##TYPE##_SECTION_END_NESTED(0, 0, 94) \
380 or 31,31,31; \
381ALT_##TYPE##_SECTION_END(0, 0) \
382 or 1,1,1; \
383 or 1,1,1; \
384 /* Nested alt sections, else with inner default taken */ \
385BEGIN_##TYPE##_SECTION \
386 or 2,2,2; \
387BEGIN_##TYPE##_SECTION_NESTED(95) \
388 or 1,1,1; \
389##TYPE##_SECTION_ELSE_NESTED(95) \
390 or 5,5,5; \
391ALT_##TYPE##_SECTION_END_NESTED(0, 1, 95) \
392 or 2,2,2; \
393##TYPE##_SECTION_ELSE \
394 or 31,31,31; \
395BEGIN_##TYPE##_SECTION_NESTED(94) \
396 or 5,5,5; \
397##TYPE##_SECTION_ELSE_NESTED(94) \
398 or 1,1,1; \
399ALT_##TYPE##_SECTION_END_NESTED(0, 0, 94) \
400 or 31,31,31; \
401ALT_##TYPE##_SECTION_END(0, 1) \
402 or 1,1,1; \
403 or 1,1,1; \
404 /* Nested alt sections, else with inner else taken */ \
405BEGIN_##TYPE##_SECTION \
406 or 2,2,2; \
407BEGIN_##TYPE##_SECTION_NESTED(95) \
408 or 1,1,1; \
409##TYPE##_SECTION_ELSE_NESTED(95) \
410 or 5,5,5; \
411ALT_##TYPE##_SECTION_END_NESTED(0, 1, 95) \
412 or 2,2,2; \
413##TYPE##_SECTION_ELSE \
414 or 31,31,31; \
415BEGIN_##TYPE##_SECTION_NESTED(94) \
416 or 5,5,5; \
417##TYPE##_SECTION_ELSE_NESTED(94) \
418 or 1,1,1; \
419ALT_##TYPE##_SECTION_END_NESTED(0, 1, 94) \
420 or 31,31,31; \
421ALT_##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 */ \
425BEGIN_##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 \
431BEGIN_##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; \
441ALT_##TYPE##_SECTION_END_NESTED(0, 1, 94) \
442ALT_##TYPE##_SECTION_END(0, 1) \
443 or 1,1,1; \
444 or 1,1,1;
445
446#define MAKE_MACRO_TEST_EXPECTED(TYPE) \
447globl(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
721MAKE_MACRO_TEST(FTR);
722MAKE_MACRO_TEST_EXPECTED(FTR);
723
724#ifdef CONFIG_PPC64
725MAKE_MACRO_TEST(FW_FTR);
726MAKE_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 */
119static struct fixup_entry fixup;
120
121static long calc_offset(struct fixup_entry *entry, unsigned int *p)
122{
123 return (unsigned long)p - (unsigned long)entry;
124}
125
126void 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
157static 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
190static 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
216static 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
252static 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
262static 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
272static 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
284static 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
298static 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}
313late_initcall(test_feature_fixups);
314
315#endif /* CONFIG_FTR_FIXUP_SELFTEST */