Linux v6.18.37 · 개념과 코드 읽기

Exception entry: vector table, IDT와 trap entry

이 코드는 어떤 문제를 푸나요?

예외 처리 함수도 레지스터를 사용합니다. 원래 프로그램의 값을 먼저 보관하지 않으면 처리 후 돌아갈 수 없습니다. arm64는 ELR/SPSR와 소프트웨어 pt_regs, x86은 IDT가 만든 프레임과 추가 저장, RISC-V는 sepc·sstatus 및 소프트웨어 저장을 결합합니다. 대표로 arm64 EL0 SVC 진입의 C 부분을 읽습니다.

읽을 범위: v6.18.37 · arch/arm64/kernel/entry-common.c · el0_svc 743–752행입니다. 아래에 이 범위의 원문과 각 줄의 설명을 실었습니다. 주제 전체의 흐름과 다른 경로는 기존 분석에서 함께 읽으실 수 있습니다.

먼저 알아둘 개념

pt_regs

예외 직전 상태를 커널 메모리에 기록한 구조입니다. 아래 함수가 호출되기 전에 어셈블리 진입 코드가 준비합니다.

noinstr

진입처럼 민감한 구간에 일반 계측 코드가 끼어드는 것을 제한하는 표시입니다.

DAIF

디버그·SError·IRQ·FIQ 마스크를 포함합니다. 예외가 왔다고 모든 시점에서 같은 마스크 상태인 것은 아닙니다.

처음 읽을 때

하드웨어가 저장한 상태와 커널이 저장한 범용 레지스터를 나누어 적어 보십시오.

더 깊이 살펴볼 때

사용자 진입 추적, CPU erratum, FP 상태와 인터럽트 허용 시점이 왜 이 순서인지 설명해 보십시오.

그림으로 보는 변화

Exception entry: vector table, IDT와 trap entry의 단계별 개념 그림
각 단계에 화살표 의미와 생략 범위를 표시했습니다. 주소·숫자 예제는 실제 장치 값을 뜻하지 않습니다.
1단계 설명

1단계 고정

GIF 원본 열기

1. 사용자 실행 중단

진입 어셈블리가 pt_regs를 마련합니다.

화살표는 사용자 흐름에서 커널 진입으로의 이동입니다.

2. C 처리 준비

사용자 진입 상태와 CPU별 보완, FP 및 DAIF를 준비합니다.

준비 단계가 시스템 호출 본체보다 앞선다는 뜻입니다.

3. 호출 처리와 복귀

do_el0_svc 후 사용자 복귀 작업과 FP 처리를 마칩니다.

최종 ERET는 이 C 함수 밖의 복귀 경로에서 수행됩니다.

el0_svc를 한 줄씩 읽기

줄 번호는 v6.18.37 원문 기준입니다. 주석·빈 줄을 포함한 함수 전체를 먼저 보고, 그 아래에서 각 줄을 설명합니다.

static void noinstr el0_svc(struct pt_regs *regs)
{
	arm64_enter_from_user_mode(regs);
	cortex_a76_erratum_1463225_svc_handler();
	fpsimd_syscall_enter();
	local_daif_restore(DAIF_PROCCTX);
	do_el0_svc(regs);
	arm64_exit_to_user_mode(regs);
	fpsimd_syscall_exit();
}
static void noinstr el0_svc(struct pt_regs *regs)

EL0에서 온 AArch64 시스템 호출의 C 진입 함수입니다. regs에는 어셈블리에서 준비한 사용자 상태가 들어 있습니다. noinstr는 이 민감한 구간의 계측을 제한합니다.

	arm64_enter_from_user_mode(regs);

사용자 실행에서 커널 실행으로 들어왔음을 커널의 진입 상태 관리에 반영합니다. 원래 레지스터 값을 새로 저장하는 함수 호출로 읽지 않습니다.

	cortex_a76_erratum_1463225_svc_handler();

Cortex-A76의 특정 erratum을 위한 SVC 진입 보완 경로를 호출합니다. 영향을 받지 않는 시스템까지 같은 추가 동작을 한다고 가정하지 않습니다.

	fpsimd_syscall_enter();

시스템 호출 경계에서 FP·벡터 상태와 mode를 정리합니다. 일반 정수 인수만 전달하는 단계와 구분합니다.

	local_daif_restore(DAIF_PROCCTX);

프로세스 문맥에 맞는 DAIF 상태를 복원해 정상 커널 처리에 필요한 예외 허용 상태를 갖춥니다.

	do_el0_svc(regs);

실제 syscall 번호 해석과 공통 진입 작업을 담당하는 do_el0_svc로 넘깁니다.

	arm64_exit_to_user_mode(regs);

사용자 복귀 전에 처리해야 할 일을 수행합니다. 시그널이나 스케줄 작업 등으로 단순히 즉시 복귀하지 않을 수 있습니다.

	fpsimd_syscall_exit();

시스템 호출 종료에 필요한 FP·벡터 상태 처리를 수행합니다. 최종 ERET는 이 함수 밖의 어셈블리 복귀 경로에 있습니다.

함께 생각해 볼 질문

이 함수가 x0~x30을 저장합니까?

아닙니다. 이미 준비된 pt_regs를 인수로 받습니다.

SVC도 예외입니까?

예. 오류가 아니라 서비스를 요청하기 위해 의도적으로 발생시키는 동기 예외입니다.

x86 SYSCALL은 IDT 진입입니까?

아닙니다. SYSCALL은 RCX·R11 등의 별도 규칙을 사용하며 일반 IDT 경로와 구분해야 합니다.

출처와 읽은 범위

Linux stable v6.18.37 · arch/arm64/kernel/entry-common.c

해당 버전 원본 파일 · 기존 코드 분석 · 설명 원고

맨 위로 ↑