blob: ffa4183fdb8b97f66dfd2fb0d8ba8bfa4a98995b [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001Hollis Blanchard <hollis@austin.ibm.com>
25 Jun 2002
3
4This document describes the system (including self-modifying code) used in the
5PPC Linux kernel to support a variety of PowerPC CPUs without requiring
6compile-time selection.
7
8Early in the boot process the ppc32 kernel detects the current CPU type and
9chooses a set of features accordingly. Some examples include Altivec support,
10split instruction and data caches, and if the CPU supports the DOZE and NAP
11sleep modes.
12
13Detection of the feature set is simple. A list of processors can be found in
14arch/ppc/kernel/cputable.c. The PVR register is masked and compared with each
15value in the list. If a match is found, the cpu_features of cur_cpu_spec is
16assigned to the feature bitmask for this processor and a __setup_cpu function
17is called.
18
19C code may test 'cur_cpu_spec[smp_processor_id()]->cpu_features' for a
20particular feature bit. This is done in quite a few places, for example
21in ppc_setup_l2cr().
22
23Implementing cpufeatures in assembly is a little more involved. There are
24several paths that are performance-critical and would suffer if an array
25index, structure dereference, and conditional branch were added. To avoid the
26performance penalty but still allow for runtime (rather than compile-time) CPU
27selection, unused code is replaced by 'nop' instructions. This nop'ing is
28based on CPU 0's capabilities, so a multi-processor system with non-identical
29processors will not work (but such a system would likely have other problems
30anyways).
31
32After detecting the processor type, the kernel patches out sections of code
33that shouldn't be used by writing nop's over it. Using cpufeatures requires
Randy Dunlap07983f02009-01-06 14:42:41 -080034just 2 macros (found in arch/powerpc/include/asm/cputable.h), as seen in head.S
Linus Torvalds1da177e2005-04-16 15:20:36 -070035transfer_to_handler:
36
37 #ifdef CONFIG_ALTIVEC
38 BEGIN_FTR_SECTION
39 mfspr r22,SPRN_VRSAVE /* if G4, save vrsave register value */
40 stw r22,THREAD_VRSAVE(r23)
41 END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
42 #endif /* CONFIG_ALTIVEC */
43
44If CPU 0 supports Altivec, the code is left untouched. If it doesn't, both
45instructions are replaced with nop's.
46
47The END_FTR_SECTION macro has two simpler variations: END_FTR_SECTION_IFSET
48and END_FTR_SECTION_IFCLR. These simply test if a flag is set (in
49cur_cpu_spec[0]->cpu_features) or is cleared, respectively. These two macros
50should be used in the majority of cases.
51
52The END_FTR_SECTION macros are implemented by storing information about this
53code in the '__ftr_fixup' ELF section. When do_cpu_ftr_fixups
54(arch/ppc/kernel/misc.S) is invoked, it will iterate over the records in
55__ftr_fixup, and if the required feature is not present it will loop writing
56nop's from each BEGIN_FTR_SECTION to END_FTR_SECTION.