aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Ellerman <michael@ellerman.id.au>2008-06-23 21:33:03 -0400
committerPaul Mackerras <paulus@samba.org>2008-06-30 21:28:30 -0400
commit362e7701fd183d990e0863883461edef61392710 (patch)
treea39d5466e2a6b68dd16187da8fad27ea50fb9851
parent9b1a735de64cc975c31a1642ec55e082ddbdfeaf (diff)
powerpc: Add self-tests of the feature fixup code
This commit adds tests of the feature fixup code, they are run during boot if CONFIG_FTR_FIXUP_SELFTEST=y. Some of the tests manually invoke the patching routines to check their behaviour, and others use the macros and so are patched during the normal patching done during boot. Because we have two sets of macros with different names, we use a macro to generate the test of the macros, very niiiice. Signed-off-by: Michael Ellerman <michael@ellerman.id.au> Signed-off-by: Paul Mackerras <paulus@samba.org>
-rw-r--r--arch/powerpc/Kconfig.debug5
-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
4 files changed, 939 insertions, 0 deletions
diff --git a/arch/powerpc/Kconfig.debug b/arch/powerpc/Kconfig.debug
index dc5893903363..2840ab69ef4e 100644
--- a/arch/powerpc/Kconfig.debug
+++ b/arch/powerpc/Kconfig.debug
@@ -62,6 +62,11 @@ config CODE_PATCHING_SELFTEST
62 depends on DEBUG_KERNEL 62 depends on DEBUG_KERNEL
63 default n 63 default n
64 64
65config FTR_FIXUP_SELFTEST
66 bool "Run self-tests of the feature-fixup code."
67 depends on DEBUG_KERNEL
68 default n
69
65choice 70choice
66 prompt "Serial Port" 71 prompt "Serial Port"
67 depends on KGDB 72 depends on KGDB
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 */