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

ARM64 Exception과 system call 소스 분석

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

EL0 프로그램의 시스템 호출은 일반 함수 호출보다 준비할 일이 많습니다. 하드웨어의 예외 상태 저장 다음에 Linux가 pt_regs를 만들고 C 처리 환경을 준비합니다. 이 단원은 v6.18.37의 el0_svc 전체를 읽어 원본 entry.S 분석과 C 단계가 이어지는 지점을 설명합니다.

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

먼저 알아둘 개념

EL0와 EL1

일반 사용자 실행과 운영체제의 권한 수준을 구분합니다. VHE 등의 구성 설명과 함께 읽되 모든 예외를 단순히 한 단계 상승이라고 외우지는 않습니다.

하드웨어 저장과 소프트웨어 저장

ELR/SPSR 저장만으로 범용 레지스터가 보존되는 것은 아닙니다. 진입 어셈블리의 추가 저장이 필요합니다.

사용자 복귀 준비

시그널·재스케줄 등의 작업을 처리한 뒤 어셈블리 복귀 경로가 저장 상태로 돌아갑니다.

처음 읽을 때

SVC 전에 사용자가 가진 레지스터 값이 어디에 보관되는지 표시하십시오.

더 깊이 살펴볼 때

noinstr 구간, erratum, FP 상태, DAIF 복원의 순서와 계측 가능 시점을 검토하십시오.

그림으로 보는 변화

ARM64 Exception과 system call 소스 분석의 단계별 개념 그림
각 단계에 화살표 의미와 생략 범위를 표시했습니다. 주소·숫자 예제는 실제 장치 값을 뜻하지 않습니다.
1단계 설명

1단계 고정

GIF 원본 열기

1. pt_regs 완성

어셈블리에서 C에 넘길 저장 프레임을 만듭니다.

화살표는 사용자 상태의 보존입니다.

2. 커널 서비스 실행

el0_svc가 진입 준비 후 do_el0_svc로 넘깁니다.

화살표는 C 함수 호출 관계입니다.

3. 사용자 상태로 복귀

복귀 작업과 FP 처리를 마치고 어셈블리에 돌아갑니다.

최종 예외 복귀 명령은 이 함수 밖에 있습니다.

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는 이 함수 밖의 어셈블리 복귀 경로에 있습니다.

함께 생각해 볼 질문

ESR을 읽으면 모든 레지스터가 저장됩니까?

아닙니다. ESR은 예외 원인 정보입니다.

noinstr는 코드가 실행되지 않는다는 뜻입니까?

아닙니다. 민감한 경로에 일반적인 계측을 제한하는 표시입니다.

시스템 호출마다 FP 레지스터 전체를 복사합니까?

구체적인 FP/SVE/SME 상태와 helper의 조건을 따라야 하며 항상 전체 복사라고 단정할 수 없습니다.

출처와 읽은 범위

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

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

맨 위로 ↑