유저 공간에서 실행된 레지스터가 커널 Bottom Stack에 Push 되는 디버깅 정보를 예전 페이지에 업데이트했잖아요.
아래와 같은 메모리 덤프를 확인했었죠.(출처:http://rousalome.egloos.com/9966225)
NUD:FFFFFFE4DE6A7EB8| 3C 6B 77 2B 46 76 A8 C2 0xC2A876462B776B3C
NUD:FFFFFFE4DE6A7EC0| 45 00 00 00 00 00 00 00 0x45 // x0
NUD:FFFFFFE4DE6A7EC8| 80 37 81 AF 7B 00 00 00 0x7BAF813780 // x1
NUD:FFFFFFE4DE6A7ED0| 16 00 00 00 00 00 00 00 0x16 // x2
NUD:FFFFFFE4DE6A7ED8| 40 00 00 00 00 00 00 00 0x40 // x3
NUD:FFFFFFE4DE6A7EE0| 20 DD FD AF 7B 00 00 00 0x7BAFFDDD20 // x4
NUD:FFFFFFE4DE6A7EE8| 14 00 00 00 00 00 00 00 0x14 // x5
NUD:FFFFFFE4DE6A7EF0| C8 DC FD AF 7B 00 00 00 0x7BAFFDDCC8 // x6
NUD:FFFFFFE4DE6A7EF8| 01 00 00 00 00 00 00 00 0x1 // x7
NUD:FFFFFFE4DE6A7F00| CE 00 00 00 00 00 00 00 0xCE // x8
NUD:FFFFFFE4DE6A7F08| 02 00 00 00 00 00 00 00 0x2 // x9
NUD:FFFFFFE4DE6A7F10| 00 00 00 00 00 00 00 00 0x0 // x10
NUD:FFFFFFE4DE6A7F18| 00 00 00 00 00 00 00 00 0x0 // x11
NUD:FFFFFFE4DE6A7F20| B9 E6 3B AF 7B 00 00 00 0x7BAF3BE6B9 // x12
NUD:FFFFFFE4DE6A7F28| 40 01 00 00 00 00 00 00 0x140 // x13
NUD:FFFFFFE4DE6A7F30| 0D 00 00 00 00 00 00 00 0x0D // x14
NUD:FFFFFFE4DE6A7F38| AB AA AA AA AA AA AA AA 0xAAAAAAAAAAAAAAAB // x15
NUD:FFFFFFE4DE6A7F40| 98 CF E2 B1 7B 00 00 00 0x7BB1E2CF98 // x16
NUD:FFFFFFE4DE6A7F48| 14 B3 AB B2 7B 00 00 00 0x7BB2ABB314 // x17
NUD:FFFFFFE4DE6A7F50| D6 00 00 00 00 00 00 00 0xD6 // x18
NUD:FFFFFFE4DE6A7F58| 78 DD FD AF 7B 00 00 00 0x7BAFFDDD78 // x19
NUD:FFFFFFE4DE6A7F60| C0 72 81 AF 7B 00 00 00 0x7BAF8172C0 // x20
NUD:FFFFFFE4DE6A7F68| 16 00 00 00 00 00 00 00 0x16 // x21
NUD:FFFFFFE4DE6A7F70| 28 8D E2 B1 7B 00 00 00 0x7BB1E28D28 // x22
NUD:FFFFFFE4DE6A7F78| C0 83 84 AF 7B 00 00 00 0x7BAF8483C0 // x23
NUD:FFFFFFE4DE6A7F80| 70 83 84 AF 7B 00 00 00 0x7BAF848370 // x24
NUD:FFFFFFE4DE6A7F88| B8 83 84 AF 7B 00 00 00 0x7BAF8483B8 // x25
NUD:FFFFFFE4DE6A7F90| 80 D7 80 AF 7B 00 00 00 0x7BAF80D780 // x26
NUD:FFFFFFE4DE6A7F98| 10 B0 90 B1 7B 00 00 00 0x7BB190B010 // x27
NUD:FFFFFFE4DE6A7FA0| 17 4A A6 B1 7B 00 00 00 0x7BB1A64A17 // x28
NUD:FFFFFFE4DE6A7FA8| 10 DD FD AF 7B 00 00 00 0x7BAFFDDD10 // x29
NUD:FFFFFFE4DE6A7FB0| 30 B3 AB B2 7B 00 00 00 0x7BB2ABB330 // x30
NUD:FFFFFFE4DE6A7FB8| 10 DD FD AF 7B 00 00 00 0x7BAFFDDD10 // sp
NUD:FFFFFFE4DE6A7FC0| C4 B7 AF B2 7B 00 00 00 0x7BB2AFB7C4 // pc
NUD:FFFFFFE4DE6A7FC8| 00 00 00 60 00 00 00 00 0x60000000 // cprs
NUD:FFFFFFE4DE6A7FD0| 45 00 00 00 00 00 00 00 0x45
NUD:FFFFFFE4DE6A7FD8| CE 00 00 00 00 00 00 00 0xCE
NUD:FFFFFFE4DE6A7FE0| 00 00 00 00 00 00 00 00 0x0
NUD:FFFFFFE4DE6A7FE8| 00 00 00 00 00 00 00 00 0x0
NUD:FFFFFFE4DE6A7FF0| C8 C3 39 00 EA 71 00 00 0x71EA0039C3C8
NUD:FFFFFFE4DE6A7FF8| 13 00 00 00 00 00 00 00 0x13
NUD:FFFFFFE4DE6A8000| 00 00 00 00 00 00 00 00 0x0
그런데 이 내용을 세미나에서 다뤘는데 이 동작이 수행되는 코드가 어디인지 어떤 분이 질문을 하셔서요.
그 내용을 업데이트하고자 해요.
유저 공간에서 프로그램이 돌다가 IRQ가 Trigger되면 el0_irq 레이블로 점프를 해요.
아래 코드에서 가장 먼저 실행되는 매크로가 kernel_entry인데요.
el0_irq:
kernel_entry 0
el0_irq_naked:
enable_dbg
#ifdef CONFIG_TRACE_IRQFLAGS
bl trace_hardirqs_off
#endif
ct_user_exit
irq_handler
#ifdef CONFIG_TRACE_IRQFLAGS
bl trace_hardirqs_on
#endif
b ret_to_user
ENDPROC(el0_irq)
해당 코드가 실행될 시 스택에 어떻게 레지스터가 Push되는 지 순서대로 살펴볼께요.
[1]: S_FRAME_SIZE는 (struct pt_regs) 구조체의 사이즈인데요. (where: DEFINE(S_FRAME_SIZE, sizeof(struct pt_regs));
레지스터 정보를 표현하고 있어요.
0xFFFFFFE4DE6A7EC0= 0xFFFFFFE4DE6A8000 - 0x140 = FFFFFFE4DE6A8000 - sizeof(struct pt_regs)
[2][3]: x0부터 x29까지 레지스터를 스택에 Push해요.
[4]: PC를 얻어와요.
[5]: SPCR Register를 업데이트해요.
[6]: lr(x30)과 sp(스택) 주소를 스택에 Push해요.
[7]: 이제 프로그램 카운터를 스택에 Push 하죠.
#해당 코드
.macro kernel_entry, el, regsize = 64
sub sp, sp, #S_FRAME_SIZE //<<--[1]
.if \regsize == 32
mov w0, w0 // zero upper 32 bits of x0
.endif
stp x0, x1, [sp, #16 * 0] //<<-[2]
stp x2, x3, [sp, #16 * 1]
stp x4, x5, [sp, #16 * 2]
stp x6, x7, [sp, #16 * 3]
stp x8, x9, [sp, #16 * 4]
stp x10, x11, [sp, #16 * 5]
stp x12, x13, [sp, #16 * 6]
stp x14, x15, [sp, #16 * 7]
stp x16, x17, [sp, #16 * 8]
stp x18, x19, [sp, #16 * 9]
stp x20, x21, [sp, #16 * 10]
stp x22, x23, [sp, #16 * 11]
stp x24, x25, [sp, #16 * 12]
stp x26, x27, [sp, #16 * 13]
stp x28, x29, [sp, #16 * 14] //<<-[3]
.if \el == 0
mrs x21, sp_el0
get_thread_info tsk // Ensure MDSCR_EL1.SS is clear,
ldr x19, [tsk, #TI_FLAGS] // since we can unmask debug
disable_step_tsk x19, x20 // exceptions when scheduling.
.else
add x21, sp, #S_FRAME_SIZE
get_thread_info tsk
/* Save the task's original addr_limit and set USER_DS (TASK_SIZE_64) */
ldr x20, [tsk, #TI_ADDR_LIMIT]
str x20, [sp, #S_ORIG_ADDR_LIMIT]
mov x20, #TASK_SIZE_64
str x20, [tsk, #TI_ADDR_LIMIT]
.endif /* \el == 0 */
mrs x22, elr_el1 //<<--[4]
mrs x23, spsr_el1 //<<--[5]
stp lr, x21, [sp, #S_LR] //<<--[6]
stp x22, x23, [sp, #S_PC] //<<--[7]
#stack dump
NUD:FFFFFFE4DE6A7EB0| 00 00 00 A0 00 00 00 00 0xA0000000
NUD:FFFFFFE4DE6A7EB8| 3C 6B 77 2B 46 76 A8 C2 0xC2A876462B776B3C
NUD:FFFFFFE4DE6A7EC0| 45 00 00 00 00 00 00 00 0x45 // x0
NUD:FFFFFFE4DE6A7EC8| 80 37 81 AF 7B 00 00 00 0x7BAF813780 // x1
NUD:FFFFFFE4DE6A7ED0| 16 00 00 00 00 00 00 00 0x16 // x2
NUD:FFFFFFE4DE6A7ED8| 40 00 00 00 00 00 00 00 0x40 // x3
NUD:FFFFFFE4DE6A7EE0| 20 DD FD AF 7B 00 00 00 0x7BAFFDDD20 // x4
NUD:FFFFFFE4DE6A7EE8| 14 00 00 00 00 00 00 00 0x14 // x5
// .. 생략 ..
NUD:FFFFFFE4DE6A7FA8| 10 DD FD AF 7B 00 00 00 0x7BAFFDDD10 // x29
NUD:FFFFFFE4DE6A7FB0| 30 B3 AB B2 7B 00 00 00 0x7BB2ABB330 // x30
NUD:FFFFFFE4DE6A7FB8| 10 DD FD AF 7B 00 00 00 0x7BAFFDDD10 // sp
NUD:FFFFFFE4DE6A7FC0| C4 B7 AF B2 7B 00 00 00 0x7BB2AFB7C4 // pc
NUD:FFFFFFE4DE6A7FC8| 00 00 00 60 00 00 00 00 0x60000000 // cprs
NUD:FFFFFFE4DE6A7FD0| 45 00 00 00 00 00 00 00 0x45
NUD:FFFFFFE4DE6A7FD8| CE 00 00 00 00 00 00 00 0xCE
NUD:FFFFFFE4DE6A7FE0| 00 00 00 00 00 00 00 00 0x0
NUD:FFFFFFE4DE6A7FE8| 00 00 00 00 00 00 00 00 0x0
NUD:FFFFFFE4DE6A7FF0| C8 C3 39 00 EA 71 00 00 0x71EA0039C3C8
NUD:FFFFFFE4DE6A7FF8| 13 00 00 00 00 00 00 00 0x13
NUD:FFFFFFE4DE6A8000| 00 00 00 00 00 00 00 00 0x0
'시스템 소프트웨어 개발을 위한 Arm 아키텍처의 구조와 원리' 카테고리의 다른 글
[리눅스커널] 라즈비안: vmlinux 소스 코드 정보 추가 : CONFIG_DEBUG_INFO (0) | 2023.06.09 |
---|---|
arm32 - Unwind Idx/prolog 소개 (0) | 2023.06.09 |
ARM64 - 프로세스(Process) preempt_disable(), preemption 스케줄(Schedule) 조건 분석 (0) | 2023.06.09 |
ARM64 - ttrb0 Special Register 설정 건 (0) | 2023.06.09 |
ARM64(Aarch64) - 함수 호출시 Stack Push(스택 푸쉬) 규약 (0) | 2023.06.09 |