티스토리 뷰

개발/arm64 linux 6 분석

250503 head.S

clucle 2025. 5. 3. 15:34

| 명령어 | 설명 |
| adr | 현재 코드 위치 기준으로 label 주소를 저장 |
| adrp | 4kb page 만큼 포인터를 설정. 따라서 12비트만큼 0가 설정됨 |
| adr_l | adrp + add 로 오프셋을 더해 실제 주소 구함 |
| cbnz | 조건이 0이 아니라면 점프 |
| dmb | data memory barrier. 여러 옵션들이 존재함 |
| bl | 고정된 함수 주소로 점프 |
| blr | 레지스터 같은 동적 함수 주소로 점프 |
| mrs | Move from system register. |
| cmp | CPSR (Current Program Status Register) 레지스터에 비교된 값 설정 |
| tbnz | Test bit and Branch if Nonzero. |
| tbz | Test bit and Branch if Zero. |
| tst | Test bits (immediate) CPSR 에 반영 |
| csel | If the condition is true, Conditional Select writes the value of the first source register to the destination register. If the condition is false, it writes the value of the second source register to the destination register. csel destination, operand1, operand2, condition |
| eor | Bitwise exclusive OR (immediate). xor 이군 |
| bic | Bit Clear. |
| stp | Store Pair of Registers calculates an address from a base register value and an immediate offset |

| 레지스터 | 설명 |
| x0 ~ x7 | 함수 인자 전달 |
| x0 | 함수 리턴시 리턴 값 |
| x19 ~ x28 | callee-saved register. 사용하면 원복 시켜줘야 하는 레지스터 |
| x29 | 프레임 포인터 (FP) 함수 호출시 스택 프,레임을 고정 |
| x30 | 링크 레지스터 (LR) 이전 함수로 돌아가기 위한 주소 레지스터 |
| xzr | 64 비트 zero 레지스터 |

head.S 이 시작 지점인 이유

BIOS/UEFI 는 부트 우선순위가 정해져있지 않다면, 기본 순서에 따라 부트 가능한 장치를 발견하고 부트로더를 실행

커널 이미지는 정해진 규칙에 따라 정의해야 합니다.

또한 arm64 의 부트로더의 순서도 정의되어있습니다.

https://github.com/torvalds/linux/blob/master/Documentation/arch/arm64/booting.rst#4-call-the-kernel-image

u32 code0;                    /* Executable code */
u32 code1;                    /* Executable code */
u64 text_offset;              /* Image load offset, little endian */
u64 image_size;               /* Effective Image size, little endian */
u64 flags;                    /* kernel flags, little endian */
u64 res2      = 0;            /* reserved */
u64 res3      = 0;            /* reserved */
u64 res4      = 0;            /* reserved */
u32 magic     = 0x644d5241;   /* Magic number, little endian, "ARM\x64" */
u32 res5;                     /* reserved (used for PE COFF offset) */
  • magic 값으로, 올바른 헤더인지 확인합니다.

include/asm-generic/vmlinux.lds.h

  • lds : 링커 스크립트
/* Section used for early init (in .S files) */
#define HEAD_TEXT  KEEP(*(.head.text))

#define __HEAD        .section    ".head.text","ax"

head.S 에 __HEAD 로 정의된 부분으로 text 의 맨윗부분이 정의됩니다.

record_mmu_state

// 0 : user
#define CurrentEL_EL1        (1 << 2) // 커널모드
#define CurrentEL_EL2        (2 << 2) // 하이퍼 바이저 모드
// 3: secure monitor

/* Common SCTLR_ELx flags. */
// System control register (SCTLR)
#define SCTLR_ELx_EE_SHIFT    25 // 엔디안 비트를 가리키는 shift

#define SCTLR_ELx_C     (BIT(2))

// 2017년 코드에서 어떤 항목인지 확인
// arch/arm/include/asm/system.h
#define CR_M        (1 << 0)    /* MMU enable            */
#define CR_A        (1 << 1)    /* Alignment abort enable    */
#define CR_C        (1 << 2)    /* Dcache enable        */

dcache_inval_poc

poc: Point of Coherency

x0~x1 캐시를 날림

Any partial lines at the ends of the interval are also cleaned to PoC to prevent data loss.

  • 앞뒤로 캐시 align 이 안맞는건 flush 까지 해줌

b.lo 2b // 점프시 b = backward f = forward

dcache

CTR, CacheTypeRegister

/*
 * dcache_line_size - get the safe D-cache line size across all CPUs
 */
 // CTR, Cache Type Register
 // UBFM Unsigned Bitfield Move.
 // lsl Logical Shift Left
    .macro    dcache_line_size, reg, tmp
    read_ctr    \tmp
    ubfm        \tmp, \tmp, #16, #19    // cache line size encoding // tmp[19:16]. dcache 의 사이즈
    mov        \reg, #4        // bytes per word // reg = 4 (0b100)
    lsl        \reg, \reg, \tmp    // actual cache line size
    .endm

| 용어 | 풀네임 | 의미 |
| POU | Point of Unification | CPU instruction fetch (I-cache) 와 D-cache가 합쳐지는 지점 (Instruction 실행 직전) |
| POC | Point of Coherency | 메모리 일관성이 보장되는 지점 (일반적으로 외부 장치와도 공유되는 지점) |

| 약어 | 의미 |
| C | Clean – 데이터를 메모리에 쓰기(flush) |
| IV | Invalidate – 캐시에서 제거 |
| AC | Data or unified Cache line Clean by VA to PoC |
| AU | Data or unified Cache line Clean by VA to PoU |
| AP | Data or unified Cache line Clean by VA to PoP |
| ... | 어디까지 clean 할지 종류가 많음 |

'개발 > arm64 linux 6 분석' 카테고리의 다른 글

jump_label (setup_arch)  (0) 2025.05.31
start_kernel 2 setup_arch  (0) 2025.05.24
start_kernel 1  (0) 2025.05.24
proc.S __primary_switch  (0) 2025.05.17
proc.S __cpu_setup  (0) 2025.05.10
댓글