해결된 질문
작성
·
21
0
안녕하세요. 좋은강의 감사합니다.
설명해주신대로 코드를 보면 sp_el0 를 이용해서 current 주소를 얻어온다는것을 이해할 수 있었습니다.
그런데 문득 sp_el1 도 있을텐데 왜 sp_el0 를 활용한건지 궁금합니다. sp_el0 는 user process 들이 활용하는 sp 이고 sp_el1 은 kernel process 들이 활용하는 sp 로 알고 있는데 요,
그런용도가 아니라 그냥 sp_el0 를 모든 process 의 task_struct 의 시작주소를 저장하는 용도로 활용하는걸까요?
<arch/arm64/include/asm/current.h>
15 static __always_inline struct task_struct *get_current(void)
16 {
17 unsigned long sp_el0;
18
19 asm ("mrs %0, sp_el0" : "=r" (sp_el0));
20
21 return (struct task_struct *)sp_el0;
22 }
<arch/arm64/kernel/entry.S>
829 SYM_FUNC_START(cpu_switch_to)
830 mov x10, #THREAD_CPU_CONTEXT
831 add x8, x0, x10
832 mov x9, sp
833 stp x19, x20, [x8], #16 // store callee-saved registers
834 stp x21, x22, [x8], #16
835 stp x23, x24, [x8], #16
836 stp x25, x26, [x8], #16
837 stp x27, x28, [x8], #16
838 stp x29, x9, [x8], #16
839 str lr, [x8]
840 add x8, x1, x10
841 ldp x19, x20, [x8], #16 // restore callee-saved registers
842 ldp x21, x22, [x8], #16
843 ldp x23, x24, [x8], #16
844 ldp x25, x26, [x8], #16
845 ldp x27, x28, [x8], #16
846 ldp x29, x9, [x8], #16
847 ldr lr, [x8]
848 mov sp, x9
849 msr sp_el0, x1
850 ptrauth_keys_install_kernel x1, x8, x9, x10
851 scs_save x0
852 scs_load_current
853 ret
854 SYM_FUNC_END(cpu_switch_to)
855 NOKPROBE(cpu_switch_to)
답변 2
0
0
정말 쉽게 정리할게요.
1. sp_el0
는 항상 current
, 즉 현재 실행 중인 Task의 주소를 가리키도록 설계되었습니다.
즉 어떤 모드든 상관 없이 무조건 sp_el0는 current를 가르킵니다.
2. 리눅스 커널에서 sp_el0
의 용도 변경
ARM64의 기본 설계에서sp_el0
는 유저 모드의 스택 포인터를 가리키도록 되어 있지만, 리눅스 커널에서는 이렇게 사용하지 않습니다. 대신sp_el0
를 "현재 실행 중인 프로세스의task_struct
를 가리키는 전용 레지스터"로 사용합니다.
굳이 왜 이러시나요?
1. 아주 빠르고 쉽게 일관되게 current를 찾기 위해.
결론
ARM64 아키텍처 기본 설계: sp_el0
는 "유저 모드의 스택 포인터"로 사용하라고 설계됨.
리눅스 커널: "그 말을 안 듣고, sp_el0
를 current
관리용으로 사용하겠다."