Back to home page

OSCL-LXR

 
 

    


0001 ============
0002 CPU Features
0003 ============
0004 
0005 Hollis Blanchard <hollis@austin.ibm.com>
0006 5 Jun 2002
0007 
0008 This document describes the system (including self-modifying code) used in the
0009 PPC Linux kernel to support a variety of PowerPC CPUs without requiring
0010 compile-time selection.
0011 
0012 Early in the boot process the ppc32 kernel detects the current CPU type and
0013 chooses a set of features accordingly. Some examples include Altivec support,
0014 split instruction and data caches, and if the CPU supports the DOZE and NAP
0015 sleep modes.
0016 
0017 Detection of the feature set is simple. A list of processors can be found in
0018 arch/powerpc/kernel/cputable.c. The PVR register is masked and compared with
0019 each value in the list. If a match is found, the cpu_features of cur_cpu_spec
0020 is assigned to the feature bitmask for this processor and a __setup_cpu
0021 function is called.
0022 
0023 C code may test 'cur_cpu_spec[smp_processor_id()]->cpu_features' for a
0024 particular feature bit. This is done in quite a few places, for example
0025 in ppc_setup_l2cr().
0026 
0027 Implementing cpufeatures in assembly is a little more involved. There are
0028 several paths that are performance-critical and would suffer if an array
0029 index, structure dereference, and conditional branch were added. To avoid the
0030 performance penalty but still allow for runtime (rather than compile-time) CPU
0031 selection, unused code is replaced by 'nop' instructions. This nop'ing is
0032 based on CPU 0's capabilities, so a multi-processor system with non-identical
0033 processors will not work (but such a system would likely have other problems
0034 anyways).
0035 
0036 After detecting the processor type, the kernel patches out sections of code
0037 that shouldn't be used by writing nop's over it. Using cpufeatures requires
0038 just 2 macros (found in arch/powerpc/include/asm/cputable.h), as seen in head.S
0039 transfer_to_handler::
0040 
0041         #ifdef CONFIG_ALTIVEC
0042         BEGIN_FTR_SECTION
0043                 mfspr   r22,SPRN_VRSAVE         /* if G4, save vrsave register value */
0044                 stw     r22,THREAD_VRSAVE(r23)
0045         END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
0046         #endif /* CONFIG_ALTIVEC */
0047 
0048 If CPU 0 supports Altivec, the code is left untouched. If it doesn't, both
0049 instructions are replaced with nop's.
0050 
0051 The END_FTR_SECTION macro has two simpler variations: END_FTR_SECTION_IFSET
0052 and END_FTR_SECTION_IFCLR. These simply test if a flag is set (in
0053 cur_cpu_spec[0]->cpu_features) or is cleared, respectively. These two macros
0054 should be used in the majority of cases.
0055 
0056 The END_FTR_SECTION macros are implemented by storing information about this
0057 code in the '__ftr_fixup' ELF section. When do_cpu_ftr_fixups
0058 (arch/powerpc/kernel/misc.S) is invoked, it will iterate over the records in
0059 __ftr_fixup, and if the required feature is not present it will loop writing
0060 nop's from each BEGIN_FTR_SECTION to END_FTR_SECTION.