1*4882a593Smuzhiyun============ 2*4882a593SmuzhiyunCPU Features 3*4882a593Smuzhiyun============ 4*4882a593Smuzhiyun 5*4882a593SmuzhiyunHollis Blanchard <hollis@austin.ibm.com> 6*4882a593Smuzhiyun5 Jun 2002 7*4882a593Smuzhiyun 8*4882a593SmuzhiyunThis document describes the system (including self-modifying code) used in the 9*4882a593SmuzhiyunPPC Linux kernel to support a variety of PowerPC CPUs without requiring 10*4882a593Smuzhiyuncompile-time selection. 11*4882a593Smuzhiyun 12*4882a593SmuzhiyunEarly in the boot process the ppc32 kernel detects the current CPU type and 13*4882a593Smuzhiyunchooses a set of features accordingly. Some examples include Altivec support, 14*4882a593Smuzhiyunsplit instruction and data caches, and if the CPU supports the DOZE and NAP 15*4882a593Smuzhiyunsleep modes. 16*4882a593Smuzhiyun 17*4882a593SmuzhiyunDetection of the feature set is simple. A list of processors can be found in 18*4882a593Smuzhiyunarch/powerpc/kernel/cputable.c. The PVR register is masked and compared with 19*4882a593Smuzhiyuneach value in the list. If a match is found, the cpu_features of cur_cpu_spec 20*4882a593Smuzhiyunis assigned to the feature bitmask for this processor and a __setup_cpu 21*4882a593Smuzhiyunfunction is called. 22*4882a593Smuzhiyun 23*4882a593SmuzhiyunC code may test 'cur_cpu_spec[smp_processor_id()]->cpu_features' for a 24*4882a593Smuzhiyunparticular feature bit. This is done in quite a few places, for example 25*4882a593Smuzhiyunin ppc_setup_l2cr(). 26*4882a593Smuzhiyun 27*4882a593SmuzhiyunImplementing cpufeatures in assembly is a little more involved. There are 28*4882a593Smuzhiyunseveral paths that are performance-critical and would suffer if an array 29*4882a593Smuzhiyunindex, structure dereference, and conditional branch were added. To avoid the 30*4882a593Smuzhiyunperformance penalty but still allow for runtime (rather than compile-time) CPU 31*4882a593Smuzhiyunselection, unused code is replaced by 'nop' instructions. This nop'ing is 32*4882a593Smuzhiyunbased on CPU 0's capabilities, so a multi-processor system with non-identical 33*4882a593Smuzhiyunprocessors will not work (but such a system would likely have other problems 34*4882a593Smuzhiyunanyways). 35*4882a593Smuzhiyun 36*4882a593SmuzhiyunAfter detecting the processor type, the kernel patches out sections of code 37*4882a593Smuzhiyunthat shouldn't be used by writing nop's over it. Using cpufeatures requires 38*4882a593Smuzhiyunjust 2 macros (found in arch/powerpc/include/asm/cputable.h), as seen in head.S 39*4882a593Smuzhiyuntransfer_to_handler:: 40*4882a593Smuzhiyun 41*4882a593Smuzhiyun #ifdef CONFIG_ALTIVEC 42*4882a593Smuzhiyun BEGIN_FTR_SECTION 43*4882a593Smuzhiyun mfspr r22,SPRN_VRSAVE /* if G4, save vrsave register value */ 44*4882a593Smuzhiyun stw r22,THREAD_VRSAVE(r23) 45*4882a593Smuzhiyun END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC) 46*4882a593Smuzhiyun #endif /* CONFIG_ALTIVEC */ 47*4882a593Smuzhiyun 48*4882a593SmuzhiyunIf CPU 0 supports Altivec, the code is left untouched. If it doesn't, both 49*4882a593Smuzhiyuninstructions are replaced with nop's. 50*4882a593Smuzhiyun 51*4882a593SmuzhiyunThe END_FTR_SECTION macro has two simpler variations: END_FTR_SECTION_IFSET 52*4882a593Smuzhiyunand END_FTR_SECTION_IFCLR. These simply test if a flag is set (in 53*4882a593Smuzhiyuncur_cpu_spec[0]->cpu_features) or is cleared, respectively. These two macros 54*4882a593Smuzhiyunshould be used in the majority of cases. 55*4882a593Smuzhiyun 56*4882a593SmuzhiyunThe END_FTR_SECTION macros are implemented by storing information about this 57*4882a593Smuzhiyuncode in the '__ftr_fixup' ELF section. When do_cpu_ftr_fixups 58*4882a593Smuzhiyun(arch/powerpc/kernel/misc.S) is invoked, it will iterate over the records in 59*4882a593Smuzhiyun__ftr_fixup, and if the required feature is not present it will loop writing 60*4882a593Smuzhiyunnop's from each BEGIN_FTR_SECTION to END_FTR_SECTION. 61