[커널 20차] 12주차

2023.07.22 23:22

이민찬 조회 수:87

head.S의 preserve_boot_args 분석

1. preserve_boot_args (arch/arm64/kernel/head.S)

/* 
 * IAMROOT20_START 2023.07.22
 * - 1) DTB : booting 시 kernel이  device 들을 인식할 때(어느 device가 어느 주소에 mapping되어 있는지)
              유의미한 정보들을 tree 형태로 저장해놓은 구조
 * - DTB와 FDT 차이점에 대한 논의 (미결)
 * - 2) POC와 POU? 
 *      https://developer.arm.com/documentation/den0024/a/Caches/Point-of-coherency-and-unification
 * - 3) cache invalidation과 clean? 
 *      https://developer.arm.com/documentation/den0024/a/Caches/Cache-maintenance
 * - 4) MMU가 Off 일 때, D-cache는 어떻게 사용되는가? 
 *      https://community.arm.com/support-forums/f/architectures-and-processors-forum/45760/can-i-enable-and-use-d-cache-with-disabled-mmu
 */

SYM_CODE_START_LOCAL(preserve_boot_args)
    /* 
    * IAMROOT20 2023.07.22 
    * x0에 들어있는 DTB 시작 주소를 x21에 저장한다. (DTB와 FDT의 차이?)
    */
    mov    x21, x0                // x21=FDT            

    

   /* 
    * IAMROOT20 2023.07.22
    * x0에 boot_args 주소를 넣는다. (u64 __cachline_aligned boot_args[4], 4개의 index를 가진 배열의 형태) global variable
        * arm64에서는 심볼의 주소를 가져올 때, 이런 식으로 동작을 한다.
        * 매크로 위치(adr_l) : /arch/arm64/include/asm/assembler.h
        * 심볼 정의 위치(boot_args) : /arch/arm64/include/asm/setup.c 
    */
    adr_l    x0, boot_args            // record the contents of         
                                                                                             
    /* IAMROOT20 2023.07.22  
     * x0에는 boot_args의 주소가 있고, 이 주소에 x21(DTB 주소)과 x1(reserved 0)의 값을 차례로 저장한다.
     * 그 뒤로 x2(reserved 0)과 x3(reserved 0)을 차례로 저장한다.
         * cf) stp : store pair
         * cf) [ ] : addressing mode (programmer's guide 참고)
         */
    stp    x21, x1, [x0]            // x0 .. x3 at kernel entry    
    stp    x2, x3, [x0, #16]                            

    

    /* IAMROOT20 2023.07.22  
     * x19가 0이 아니라면 레이블 0으로 이동한다. x19가 1인 경우는 MMU On & Cache On 이다.
     */
    cbnz    x19, 0f                // skip cache invalidation if MMU is on 

    

    /* IAMROOT20 2023.07.22  
     * 앞에 있는 stp 명령어가 내부 버퍼에서 완전히 처리되도록 보장하기 위해 배리어 명령어를 사용한다.
     * data memory barrier : CPU가 최적화를 위해 명령어의 순서를 바꿔서 처리할 때, 문제가 생길 수 있다. 
         * 이 때, 메모리에 접근하는 명령어(load, store)는 reordering 되지 않도록 순서를 보장하는 명령어이다.
     */
    dmb    sy                // needed before dc ivac with        
                        // MMU off                
                                            
     /* IAMROOT20 2023.07.22  
      * boot_args의 끝 주소를 x1에 저장한다. (이후에 invalidation 과정에서 필요할 것으로 예상)
      */
    add    x1, x0, #0x20            // 4 x 8 bytes                

    

    /* IAMROOT20 2023.07.22  
     * dcache_inval_poc로 이동한다.
     * 위치 : /arch/arm64/mm/cache.S
     */
    b    dcache_inval_poc        // tail call

 

 

2. dcache_inval_poc (arch/arm64/mm/cache.S)

SYM_FUNC_START(__pi_dcache_inval_poc)
    /* IAMROOT20 2023.07.22
     * x2에 cache line-size를 저장하고(64byte), x3에는 ctr_el0[19:16]의 값이 저장되어있다. 
     * 매크로 위치 : /arch/arm64/include/asm/assembler.h
     */    
    dcache_line_size x2, x3

 

3. 매크로 (arch/arm64/include/asm/assembler.h)

1) adr_l

    .macro    adr_l, dst, sym
    /* IAMROOT20 2023.07.22
         * symbol이 있는 page의 주소를 dst에 저장한다. 
         * arm64에서 모든 명령어는 4바이트이기 때문에, 명령어 내에 주소를 포함하지 못한다.
         */
    adrp    \dst, \sym

    /* IAMROOT20 2023.07.22
     * symbol의 하위 12비트 주소(page offset)를 dst에 더한 후 dst에 저장한다.
     * 페이지 크기가 4K 이므로 하위 12비트가 page offset이 된다.
     */
    add    \dst, \dst, :lo12:\sym
    .endm

 

2)  dcache_line_size

/*
 * dcache_line_size - get the safe D-cache line size across all CPUs
 */
    /* IAMROOT20 2023.07.22
     * 캐시 라인 사이즈를 얻는 매크로
     */
    .macro    dcache_line_size, reg, tmp

 

    /* IAMROOT20 2023.07.22
         * ctr_el0의 값을 tmp 레지스터에 넣는다.
     * 매크로 위치 : arch/arm64/include/asm/assembler.h
     */
    read_ctr    \tmp

 

    /* IAMROOT20 2023.07.22
     * ctr_el0 레지스터에서 캐시 라인 사이즈 부분을 얻어온다.
     * ctr_el0[19:16]은 DminLine으로 데이터 캐시 라인 사이즈를 나타내는 비트이다. 2^n 워드 단위로 저장된다.
     */
    ubfm        \tmp, \tmp, #16, #19    // cache line size encoding
    
    /* IAMROOT20 2023.07.22
     * reg 레지스터에 4를 넣는다. 이 때, 4는 word 크기를 의미한다. 
     */
    mov        \reg, #4        // bytes per word

 

    /* IAMROOT20 2023.07.22
         * reg 레지스터에 캐시 라인 크기를 넣는다. 
     * 워드 사이즈: 4, 캐시 라인 당 데이터 저장 개수 : 16, ctr_el0[19:16] : 4
     * 계산 : 4 << 4 => 4 * 2^4 => 64
     */
    lsl        \reg, \reg, \tmp    // actual cache line size
    .endm

 

3)  read_ctr

/*
 * read_ctr - read CTR_EL0. If the system has mismatched register fields,
 * provide the system wide safe value from arm64_ftr_reg_ctrel0.sys_val
 */
    .macro    read_ctr, reg
#ifndef __KVM_NVHE_HYPERVISOR__
alternative_if_not ARM64_MISMATCHED_CACHE_TYPE
    /* IAMROOT20 2023.07.22
     * ctr_el0 레지스터 값을 reg 레지스터에 넣는다.
     */
    mrs    \reg, ctr_el0            // read CTR
    nop

 

4. 기타 논의 사항들 

Q: PoC, PoU가 뭔가?

A: https://developer.arm.com/documentation/den0024/a/Caches/Point-of-coherency-and-unification

 

Q: cache invalidation과 cache clean의 차이점은?

A: https://developer.arm.com/documentation/den0024/a/Caches/Cache-maintenance

 

Q: MMU가 disabled 상태일 때 D-Cache는 어떻게 사용되는가?

A: https://community.arm.com/support-forums/f/architectures-and-processors-forum/45760/can-i-enable-and-use-d-cache-with-disabled-mmu

 

SYM_CODE_START_LOCAL(preserve_boot_args)

Mov x21, x0 // x21=FDT

Q. DTB와 FDT의 차이는?

A. 디바이스 트리, Device Tree : 커널 부팅시 어떤 디바이스를 관리해야하는지, 주소는 어디인지, 메모리 매핑주소 등을 관리하기 위한 정보를 트리형태로 저장하는 자료, 이를 바이너리 형태로 저장해 둔 자료를 DTB (Binary)

A. Other names for Flattened Device Tree (FDT) are "binary blob" and ".dtb".  즉 DTB와 FDT는 같은 용어

https://elinux.org/Device_Tree_Reference#FDT_format



 

개념. Addressing Modes - 특정 메모리 address 에 접근하는 방법을 정의한 모드

출처 : DEN0024A_v8_architecture_PG.pdf 6.3.4 Specifying the address for a Load or Store instruction

 

LDR x0, [x1],

X1의 값(메모리 주소)을 reference 해서 그 곳(메모리)에 저장된 값을  x0 에 load 해라.

 

LDR x0, [x1, #8]

X1 + 8의 값(메모리 주소)을 reference 해서 그 곳(메모리)에 저장된 값을  x0 에 load 해라.

(x1의 값은 변경되지 않음)

 

LDR x0, [x1, #8]!

X1 + 8의 값(메모리 주소)을 reference 해서 그 곳(메모리)에 저장된 값을  x0 에 load 해라. 그리 x1의 값을 x1+8 로 업데이트 해라.)

 

LDR x0, [x1], #8

먼저 X1의 값(메모리 주소)을 reference 해서 그 곳(메모리)에 저장된 값을  x0 에 load 하고

x1의 값을 x1+8 로 업데이트 해라)


 

개념. Addressing multiple memory locations

LDP (Load Pair) 와 STP (Store Pair) 는 두 개 레지스터의 값을 메모리에 저장한다.

stp Rt1, Rt2, [Rn]

- Rt1 과 Rt2 두 레지스터의 값을 Rn에 저장된 address의 메모리 공간에 차례대로 저장한다.

- Rn 이 레지스터는 메모리 주소를 가리킨다. Rt1과 Rt2의 값을 이 주소에 저장한다.

 

stp x21, x1, [x0]

레지스터 x21, x1 값을 레지스터 x0가 가리키는 메모리 주소에 저장. 이때 x21의 값을 먼저 저장하고, 그 뒤 x1의 값을 저장한다. 


 

DMB 명령어를 통해, 데이터 캐시를 invalidate하여 제거하기 전에 위의 stp 명령이 내부 버퍼에서 완전하게 마무리되도록 메모리 베리어를 사용할 수 있다.



 

Q. 캐시 라인이란?

  • 캐시를 구성하는 기본 단위 (logical block)

  • Cache에 로드 가능한 최소 단위

  • Main memory의 연속된 word들의 집합

 

Q. ubfm Instruction 이란?

https://developer.arm.com/documentation/dui0802/a/A64-General-Instructions/UBFM

 

UBFM Xd, Xn, #immr, #imms ; 64-bit general registers

- Xd : 0 ~ 31 범위의 destination register

- Xn : 0 ~ 31 범위의 source register

- immr : 64-bit 의 경우 0 ~ 63 범위의 right rotate 량

- imms : source 에서 이동할 가장 왼쪽 비트 범위 (0~63)

 

Q. 캐시의 Tag란?

A. 지역성을 위해 같은 태그를 모아놓는다. 모여있는 데이터를 위해 캐시를 사용한다. 메모리 위치의 세부적인 지점은 index로 표현되고, 메모리 위치의 대략적인 위치는 tag로 표현된다. 먼저 세부적인 영역부터 확인하고, 대략적인 위치를 그 다음에 확인하는 방식. 두 개가 모두 찾고자 하는 주소와 일치하고, valid bit 가 1이면, 캐시 히트가 된다. 캐시 미스라면, 메모리로 데이터를 찾으러 간다.

 

Cache line 사이즈를 구하기 위해 dminline 필드의 값으로 계산을 한다.

 

 

디버깅을 통해 배우는 리눅스 커널의 구조와 원리 

 

3.4 ftrace

3.4.3 ftrace 메시지는 어떻게 분석할까?

Q. ftrace 로그에서 h/s, hardirq/softirq가 있는데, 이 둘에 대해서..

  1. Hardware Interrupt / Software Interrupt

  2. Hardirq : 일반적인 HW 인터럽트 전반부 처리(top half)를 의미하고
    softIrq :  Interrupt 후반부(bottom half) 서비스중 하나인 soft Irq 처리를 하는 서비스의 한 종류가 실행 되고 있을 경우를 말합니다.

 

Q. ftrace 로그에서 n, 선점 스케줄링 될 수 있는 상태는 어떨 때?

  1. 선점 스케줄링 - RTOS 환경에서 높은 우선 순위의 task가 시간 내에 완료가 되어야할 때 

  2. 리눅스에서 Default는 선점 스케줄링 (Resource 활용 차원), 그럼에도 비선점인 경우가 있음. 설정하는 flag가 있을 것이다. 같은 우선 순위에 대해서는 스케줄링 정책에 따라 선점형으로 동작한다. 

  3.  

참고 문서: http://books.gigatux.nl/mirror/kerneldevelopment/0672327201/ch09lev1sec9.html

 

Q. preempt_count

  1. https://lwn.net/Articles/831678/

번호 제목 글쓴이 날짜 조회 수
공지 [공지] 스터디 정리 노트 공간입니다. woos 2016.05.14 627
228 [커널 20차] 20주차 [2] 이민찬 2023.09.17 182
227 [커널 20차] 19주차 이민찬 2023.09.10 103
226 [커널 20차] 18주차 이민찬 2023.09.03 85
225 [커널 20차] 17주차 이민찬 2023.08.27 129
224 [커널 20차] 16주차 이민찬 2023.08.20 132
223 [커널 19차] 64 주차 Min 2023.08.19 91
222 [커널 20차] 15주차 이민찬 2023.08.13 126
221 [커널 19차] 63 주차 Min 2023.08.12 60
220 [커널 19차] 62 주차 Min 2023.08.05 79
219 [커널 20차] 13주차 이민찬 2023.07.30 106
218 [커널 19차] 61 주차 Min 2023.07.30 45
» [커널 20차] 12주차 이민찬 2023.07.22 87
216 [커널 19차] 59 ~ 60 주차 Min 2023.07.22 37
215 [커널 18차] 113주차 kkr 2023.07.22 78
214 [커널20차] 11주차 이경재 2023.07.15 86
213 [커널20차] 10주차 이경재 2023.07.09 90
212 [커널20차] 9주차 이경재 2023.07.02 85
211 [커널 19차] 58 주차 Min 2023.07.01 41
210 [커널 19차] 56 ~ 57 주차 Min 2023.06.25 40
209 [커널 18차] 109주차 kkr 2023.06.24 33
XE Login