본문 바로가기

Linux/ARM64

smp_setup_processor_id()

smp_setup_processor_id 함수 분석

 

리눅스는 기본적으로 물리적 id를 사용하지 않고 부트된 물리 cpu를 logical id 0번으로 배치하여 사용한다고 한다.

 

(문c 블로그 참조:http://jake.dothome.co.kr/smp_setup_processor_id/)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
__attribute__((optimize("-O0"))) void __init smp_setup_processor_id(void)
{   
    u64 dbg_x1, mpidr;
    mpidr = read_cpuid_mpidr() & MPIDR_HWID_BITMASK;   //0
    dbg_x1 = read_cpuid_mpidr();        //  0x80000000
    dbg_x1 = MPIDR_HWID_BITMASK;        //0xff00ffffff
    cpu_logical_map(0= mpidr;
    /* read_cpuid_mpdir 함수를 통해 MPIDR_EL1 값을 읽어 온다.
     * Reserved 영역을 제외한 레지스터 값을 읽어온다.
     *    
     */ 
    /*
     * clear __my_cpu_offset on boot CPU to avoid hang caused by
     * using percpu variable early, for example, lockdep will
     * access percpu variable inside lock_release
     */
    set_my_cpu_offset(0);
    
    /*
      set_my_cpu_offset(0)은 asm language로 되어 있으며 tpidr_el1에 0으로 값을 써준다.(msr 명령어)
      
        104         cpu_logical_map(0) = mpidr;
            
            0xffff000011102d68 <+64>:   adrp    x0, 0xffff000011278000 <init_sighand+1408>
            0xffff000011102d6c <+68>:   add x0, x0, #0x790
            0xffff000011102d70 <+72>:   ldr x1, [x29, #16]
            0xffff000011102d74 <+76>:   str x1, [x0]
            0xffff000011102d78 <+80>:   str xzr, [x29, #40]
        105         set_my_cpu_offset(0);   
                    asm volatile(ALTERNATIVE("msr tpidr_el1, %0",
            ./arch/arm64/include/asm/percpu.h:
            0xffff000011102d7c <+84>:   ldr x0, [x29, #40]
            0xffff000011102d80 <+88>:   msr tpidr_el1, x0
            0xffff000011102d84 <+92>:   mrs x0, midr_el1
    */
    pr_info("Booting Linux on physical CPU 0x%010lx [0x%08x]\n",
        (unsigned long)mpidr, read_cpuid_id());
    /*                       QEMU log 
     *  Booting Linux on physical CPU 0x0000000000 [0x410fd034]
     */
}
 
cs

첫줄에 나타나는 read_cpuid_mpidr를 따라가 보면 결국 read_sysreg로 define 된 mrs asm 명령어를 통해 MPIDR_EL1 값을 읽어 온다. (MRS, MSR 은 특수 레지스터를 읽기 위한 ASM 명령어. 일반 MOV랑 비슷하다)

#define read_sysreg_s(r) ({ \

u64 __val; \

asm volatile("mrs_s %0, " __stringify(r) : "=r" (__val)); \

__val; \

})

 

set_my_cpu_offset(0); 에서 실제 tpidr_el1 에 0으로 값을 써주는 부분이 있는데 이 명령어로 통해 위에 언급된 logical id =0 으로 설정하는 부분인듯 싶다.

 

 

'Linux > ARM64' 카테고리의 다른 글

arch_local_irq_disable()  (0) 2019.12.27
boot_cpu_init()  (0) 2019.12.27
early_ioremap_init(void)  (0) 2019.12.24
early_fixmap_init(void)  (0) 2019.12.22