Kernel version : 4.0.5


리눅스 커널의 스타트 부분인 head.S 파일 분석중 시작점인 strart: 부분의 이해.


 118 start:

 119                 .type   start,#function

 120                 .rept   7

 121                 mov     r0, r0

 122                 .endr

 123    ARM(         mov     r0, r0          )

 124    ARM(         b       1f              )

 125  THUMB(         adr     r12, BSYM(1f)   )

 126  THUMB(         bx      r12             )


바닐라 커널의 Git log 가 정확히는 않되어있다.

ARM 관련 repo에는 되어있을듯하니 추후 찾아봐야함.

아래는 관련 로그이다.

추후에는 관련 로그를 전부 봐야할듯 - 왜 구현하지 알기 위해.


  1 commit b11fe38883d1de76f2f847943e085a808f83f189

  2 Author: Nicolas Pitre <nico@fluxnic.net>

  3 Date:   Sat Feb 12 22:25:27 2011 +0100

  4

  5     ARM: 6663/1: make Thumb2 kernel entry point more similar to the ARM one

  6

  7     Some installers would binary patch the kernel zImage to replace the

  8     first few nops with custom instructions.  This breaks the Thumb2 kernel

  9     as the mode switch is right at the beginning.  Let's move it towards the

 10     end of the nop sequence instead.

 11

 12     Signed-off-by: Nicolas Pitre <nicolas.pitre@linaro.org>

 13     Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>

 14

  ※ ARM mode, Thumb mode, Thumb2 mode에 대한 이해 필요.

  ※ ref : http://egloos.zum.com/recipes/v/5651064



기존의 코드와 비교하여 어떻게 봐뀌었는지 보자

  4 --- a/arch/arm/boot/compressed/head.S

  5 +++ b/arch/arm/boot/compressed/head.S

  6 @@ -128,14 +128,14 @@ wait:             mrc     p14, 0, pc, c0, c1, 0

  7                 .arm                            @ Always enter in ARM state

  8  start:

  9                 .type   start,#function

 10 - THUMB(                adr     r12, BSYM(1f)   )

 11 - THUMB(                bx      r12             )

 12 - THUMB(                .rept   6               )

 13 - ARM(          .rept   8               )

 14 +               .rept   7

 15                 mov     r0, r0

 16                 .endr

 17 +   ARM(                mov     r0, r0          )

 18 +   ARM(                b       1f              )

 19 + THUMB(                adr     r12, BSYM(1f)   )

 20 + THUMB(                bx      r12             )

 21

 22 -               b       1f

 23                 .word   0x016f2818              @ Magic numbers to help the loader

 24                 .word   start                   @ absolute load/run zImage address

 25                 .word   _edata                  @ zImage end address


 - 의미없는 명령어를 Repeat 하는 이유 예상 및 결과.

   1. Pipe line clear?

       처음에 NOP 역활을 하는 명령어의 반복은 Pipeline clear 역활로 알고 있다.

       Pipe line clear를 하지 않음으로써 예상치 못한 결과

       (Pipe line에 남아있는 명령어를 실행) 할수도 있다.


   2. I-cache clear?

       iamroot.org에 미리 분석해놓은 소스를 보면 위와 같이 되어있다.

       하지만 이와 관련 근거에 대한 자료는 없으므로 물음표로 했다.

       아마도 ARM architecture관련하여 찾아보거나 히스토리 트래킹을 해야겠다.(예상)


   3. 위의 예상이 틀림.

      ARM linux maintainer Russell King과 Jeff Sutherland의 답변

      Russell King의 답변.

      ref : http://archive.arm.linux.org.uk/lurker/message/20060802.141024.fdbb3e29.en.html

      Jeff Sutherland의 답변

      ref : http://archive.arm.linux.org.uk/lurker/message/20060802.141429.8152d57c.en.html

      iamroot.org 토의자료.

      ref : http://www.iamroot.org/xe/QnA/23099



Define ARM & THUMB & Branch


125 Line : 추가 예정.

126 Line : 추가 예정.


linux/arch/arm/include/asm/unified.h 위치에 다음과 같이 define 되어있다.


 27 #ifdef CONFIG_THUMB2_KERNEL

 28

 29 #if __GNUC__ < 4

 30 #error Thumb-2 kernel requires gcc >= 4

 31 #endif

 32

 33 /* The CPSR bit describing the instruction set (Thumb) */

 34 #define PSR_ISETSTATE   PSR_T_BIT

 35

 36 #define ARM(x...)

 37 #define THUMB(x...)     x

 38 #ifdef __ASSEMBLY__

 39 #define W(instr)        instr.w

 40 #define BSYM(sym)       sym + 1

 41 #else

 42 #define WASM(instr)     #instr ".w"

 43 #endif

 44

 45 #else   /* !CONFIG_THUMB2_KERNEL */

 46

 47 /* The CPSR bit describing the instruction set (ARM) */

 48 #define PSR_ISETSTATE   0

 49

 50 #define ARM(x...)       x

 51 #define THUMB(x...)

 52 #ifdef __ASSEMBLY__

 53 #define W(instr)        instr

 54 #define BSYM(sym)       sym

 55 #else

 56 #define WASM(instr)     #instr

 57 #endif

 58

 59 #endif  /* CONFIG_THUMB2_KERNEL */


29 Line : GCC version check

          GNU version 4 이하면 thumb2 mode 지원 않함. Warning 출력.


36, 37 Line : CONFIG에 따라 ARM(x...) THUMB(x...) 값이 존재한다.


40 Line : BSYM(sym)       sym + 1

54 Line : BSYM(sym)       sym

          Mode change, 호환성.

          

참고자료 


Branch


like instructions which jump to a label or symbol usually identify the destination instruction set by having two different forms of the instruction:

Instruction set

Instruction

Destination instruction set

ARM

BBL

ARM

ARM

BXBLX

Thumb

Thumb

BBL

Thumb

Thumb

BXBLX

ARM

To call/jump to external symbols from a .S file, always use B or BL. The linker will translate these to BX/BLX as necessary. (The linker does not translate BX or BLX if you write those explicitly.)



⇒ BSYM은 파라메터(주소)에 1을 더해서 bx명령와 조합되므로 ARM→Thumb 또는 Thumb→ARM 모드 변경이 일어납니다.
armv5 같은 아키텍쳐에서는 thumb용 어셈블리 코드와 arm 어셈블리 코드는 다르게 작성이 되어야 했습니다.
그런데 /arch/arm/boot/compressed/head.S 내용 중 ” THUMB( .thumb ) ” 코드는
이 이후의 코드는 ARM 코드나 Thumb코드로 컴파일 될 수 있음을 말합니다.
즉 한개의 어셈블리 소스로 ARM 코드, Thumb 코드 모두 컴파일 될 수 있다는 것을 알았습니다. (정확하게는 Thumb2)




 127

 128                 .word   _magic_sig      @ Magic numbers to help the loader

 129                 .word   _magic_start    @ absolute load/run zImage address

 130                 .word   _magic_end      @ zImage end address

 131                 .word   0x04030201      @ endianness flag

 132

 133  THUMB(         .thumb                  )


arch/arm/boot/compressed/vmlinux.lds.S 에 위의 값이 정의 되어 있으며 관련 값들은 아래 

참고로 적어놨다.


_magic_sig 위치 : arch/arm/boot/compressed/vmlinux.lds.S

 68   _magic_sig = ZIMAGE_MAGIC(0x016f2818);

 69   _magic_start = ZIMAGE_MAGIC(_start);

 70   _magic_end = ZIMAGE_MAGIC(_edata);


_start 위치 : arch/arm/boot/bootp/init.S

 19                 .section .start,#alloc,#execinstr

 20                 .type   _start, #function

 21                 .globl  _start

 22

 23 _start:         add     lr, pc, #-0x8           @ lr = current load addr


_edata 위치 : arch/arm/boot/compressed/vmlinux.lds.S

 64   /* (without a dummy byte, ld just ignores the empty section) */

 65   .pad                  : { BYTE(0); . = ALIGN(8); }

 66   _edata = .;

 67

 68   _magic_sig = ZIMAGE_MAGIC(0x016f2818);

 69   _magic_start = ZIMAGE_MAGIC(_start);

 70   _magic_end = ZIMAGE_MAGIC(_edata);


매직 넘버를 사용하는 이유


5. Loading the kernel image


Kernel images generated by the kernel build process are either uncompressed "Image" files or compressed zImage files.


The uncompressed Image files are generally not used, as they do not contain a readily identifiable magic number. The compressed zImage format is almost universally used in preference.


The zImage has several benefits in addition to the magic number. Typically, the decompression of the image is faster than reading from some external media. The integrity of the image can be assured, as any errors will result in a failed decompress. The kernel has knowledge of its internal structure and state, which allows for better results than a generic external compression method.


The zImage has a magic number and some useful information near its beginning.


Table 2. Useful fields in zImage head code

Offset into zImageValueDescription
0x240x016F2818Magic number used to identify this is an ARM Linux zImage
0x28start addressThe address the zImage starts at
0x2Cend addressThe address the zImage ends at


The start and end offsets can be used to determine the length of the compressed image (size = end - start). This is used by several bootloaders to determine if any data is appended to the kernel image. This data is typically used for an initial RAM disk (initrd). The start address is usually 0 as the zImage code is position independent.


The zImage code is Position Independent Code (PIC) so may be loaded anywhere within the available address space. The maximum kernel size after decompression is 4Megabytes. This is a hard limit and would include the initrd if a bootpImage target was used.


Note


Although the zImage may be located anywhere, care should be taken. Starting a compressed kernel requires additional memory for the image to be uncompressed into. This space has certain constraints.


The zImage decompression code will ensure it is not going to overwrite the compressed data. If the kernel detects such a conflict it will uncompress the image immediately after the compressed zImage data and relocate the kernel after decompression. This obviously has the impact that the memory region the zImage is loaded into must have up to 4Megabytes of space after it (the maximum uncompressed kernel size), i.e. placing the zImage in the same 4Megabyte bank as its ZRELADDR would probably not work as expected.


Despite the ability to place zImage anywhere within memory, convention has it that it is loaded at the base of physical RAM plus an offset of 0x8000 (32K). This leaves space for the parameter block usually placed at offset 0x100, zero page exception vectors and page tables. This convention is very common.


ref : http://www.simtec.co.uk/products/SWLINUX/files/booting_article.html




 134 1:

 135  ARM_BE8(       setend  be )                    @ go BE8 if compiled for BE8

 136                 mrs     r9, cpsr

 137 #ifdef CONFIG_ARM_VIRT_EXT

 138                 bl      __hyp_stub_install      @ get into SVC mode, reversibly

 139 #endif

 140                 mov     r7, r1                  @ save architecture ID

 141                 mov     r8, r2                  @ save atags pointer

 142


135 Line : setend (Set endian) be (Big endian) -> le는 little endian을 의미.

            ref : http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0489f/Cjacabbf.html


136 Line : MRS는 PSR 레지스터의 내용을 범용레지스터로 이동.

            ref : http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0204ik/Cihjcedb.html


140, 141 Line : booting시 레지스터에 parameter로 넘어온 값 저장.

                  save contents of registers r1 and r2 in r7 and r8 to save off architecture ID and

                  atags pointer passed in by bootloader (118)

                  ref : http://joomin.tistory.com/3


 151 #ifndef CONFIG_CPU_V7M

 152                 /*

 153                  * Booting from Angel - need to enter SVC mode and disable

 154                  * FIQs/IRQs (numeric definitions from angel arm.h source).

 155                  * We only do this if we were in user mode on entry.

 156                  */

 157                 mrs     r2, cpsr                @ get current mode

 158                 tst     r2, #3                  @ not user?

 159                 bne     not_angel

 160                 mov     r0, #0x17               @ angel_SWIreason_EnterSVC

 161  ARM(           swi     0x123456        )       @ angel_SWI_ARM

 162  THUMB(         svc     0xab            )       @ angel_SWI_THUMB

 163 not_angel:

 164                 safe_svcmode_maskall r0

 165                 msr     spsr_cxsf, r9           @ Save the CPU boot mode in

 166                                                 @ SPSR

 167 #endif


151 Line : 아래의 로그 참조


  1 commit c20611df13c3e3070607c267cf781ba8645a185e

  2 Author: Joachim Eastwood <manabian@gmail.com>

  3 Date:   Wed Mar 25 08:47:18 2015 +0100

  4

  5     ARM: 8327/1: zImage: add support for ARMv7-M

  6

  7     This patch makes it possible to enter zImage in Thumb mode for ARMv7-M

  8     (Cortex-M) CPUs that do not support ARM mode. The kernel entry is also

  9     made in Thumb mode.

 10

 11     [ukl: fix spelling in commit log, return early in call_cache_fn]

 12

 13     Signed-off-by: Joachim Eastwood <manabian@gmail.com>

 14     Tested-by: Stefan Agner <stefan@agner.ch>

 15     Tested-by: Ezequiel Garcia <ezequiel@vanguardiasur.com.ar>

 16     Tested-by: Chanwoo Choi <cw00.choi@samsung.com>

 17     Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>

 18     Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>


157 Line : cpsr 을 r2에 복사.


158 Line : cpsr 의 3번째 비트 검사.

            ref : http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0204ik/Cihcdehh.html


159 Line : bne (branch not equal) 3번째 비트가 set 되어 있지 않을 경우 not_angel로 branch 

   참고 : http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.kui0100a/armasm_cegihjgh.htm


160 Line : 


161 Line : 

            ref : SWI의 이해 http://egloos.zum.com/recipes/v/5037342



 168                 .text

 169

 170 #ifdef CONFIG_AUTO_ZRELADDR

 171                 @ determine final kernel image address

 172                 mov     r4, pc

 173                 and     r4, r4, #0xf8000000

 174                 add     r4, r4, #TEXT_OFFSET

 175 #else

 176                 ldr     r4, =zreladdr

 177 #endif

 178



170 Line : AUTO_ZRELADDR 설명 및 바닐라 커널 주석.

            참고자료 : Documentation/arm/Porting

2032 config AUTO_ZRELADDR

2033         bool "Auto calculation of the decompressed kernel image address"

2034         help

2035           ZRELADDR is the physical address where the decompressed kernel

2036           image will be placed. If AUTO_ZRELADDR is selected, the address

2037           will be determined at run-time by masking the current IP with

2038           0xf8000000. This assumes the zImage being placed in the first 128MB

2039           from start of memory.


 181                 /*

 182                  * Find the start of physical memory.  As we are executing

 183                  * without the MMU on, we are in the physical address space.

 184                  * We just need to get rid of any offset by aligning the

 185                  * address.

 186                  *

 187                  * This alignment is a balance between the requirements of

 188                  * different platforms - we have chosen 128MB to allow

 189                  * platforms which align the start of their physical memory

 190                  * to 128MB to use this feature, while allowing the zImage

 191                  * to be placed within the first 128MB of memory on other

 192                  * platforms.  Increasing the alignment means we place

 193                  * stricter alignment requirements on the start of physical

 194                  * memory, but relaxing it means that we break people who

 195                  * are already placing their zImage in (eg) the top 64MB

 196                  * of this range.

 197                  */

172 Line : 현제 PC주소를 r4레지스터에 넣어준다.

            현제 PC주소값은?


173 Line : 현재 PC 주소에서 상위 5비트를 제외한 모든 비트를 클리어한다.


174 Line : 






'Development > Linux_Kernel' 카테고리의 다른 글

Linux booting time  (0) 2015.10.01
linux kernel analysis map  (0) 2015.07.05
<참고> ARM Linux Boot Sequence  (0) 2015.06.29