Arm Linux Kernel Hacks

rousalome.egloos.com

포토로그 Kernel Crash


통계 위젯 (화이트)

8179
1390
307630


[Arm프로세서] Armv8: 익셉션 핸들러(Exception Handler) Armv8: 익셉션(Exception)

Arm 코어가 익셉션을 감지하면 익셉션 벡터 주소로 프로그램 카운터를 브랜치합니다. 여기까지가 Arm 코어가 하드웨어적으로 처리하는 부분인데, 그 다음부터 어떻게 동작할까요? Arm 코어의 프로그램 카운터가 특정 주소로 바뀌면, 해당 주소에 위치한 어셈블리 명령어를 페치해 실행합니다. 즉, 익셉션 벡터 주소로 프로그램 카운터를 브랜치하면 이 주소에 위치한 명령어가 실행되는 것입니다. 이 부분부터 소프트웨어적으로 익셉션을 핸들링하는 동작이라고 볼 수 있습니다. 익셉션 벡터에 위치한 명령어가 실행되면 이를 "익셉션 핸들러가 처리된다"라고 합니다.

익셉션 벡터에 위치한 명령어 세트를 보통 익셉션 핸들러라고 하는데, 이해를 돕기 위해 다음과 같이 Armv8 아키텍처에서 빌드된 익셉션 핸들러 코드를 소개합니다.

01 ffffff8008082000 <vectors>:
02 ffffff8008082000:   d10503ff    sub sp, sp, #0x140
03 ffffff8008082004:   8b2063ff    add sp, sp, x0
...
04 ffffff8008082200:   d10503ff    sub sp, sp, #0x140
05 ffffff8008082204:   8b2063ff    add sp, sp, x0
06 ffffff8008082208:   cb2063e0    sub x0, sp, x0
07 ffffff800808220c:   37700080    tbnz    w0, #14, ffffff800808221c <vectors+0x21c>

만약 Arm 코어가 익셉션(EL1에서 Synchronous 익셉션 유발)을 감지하면 04번째 줄과 같이 ffffff8008082200 주소로 프로그램 카운터가 바뀝니다. ffffff8008082200와 같은 주소가 익셉션 벡터이고, 02~05번째 줄에 있는 명령어를 익셉션 핸들러라고 합니다.

익셉션의 종류에 따라 익셉션 핸들러는 각기 다른 방식으로 처리합니다.

   ❑ Synchronous 익셉션: 시스템 리셋/시스템 콜 실행
   ❑ IRQ 익셉션: 인터럽트를 처리하는 인터럽트 서비스 루틴 실행 
   ❑ SError 익셉션: 시스템 리셋  

그럼 익셉션 핸들러가 익셉션의 종류 별로 어떤 동작을 하는 지 더 자세히 알아보겠습니다.

첫 번째로, Synchronous 익셉션 핸들러는 크게 2가지 방식으로 익셉션을 처리합니다. 먼저 소프트웨어적으로 치명적인 오류를 유발하는 명령어가 실행되면, Synchronous 익셉션이 유발됩니다. 이후 Synchronous 익셉션 핸들러에서는 익셉션이 발생한 세부 원인을 ESR_ELx(익셉션 신드롬 레지스터)를 읽어 체크한 후 다음과 같은 동작을 수행합니다.

   ❑ 유저 애플리케이션: 프로세스를 종료
   ❑ 운영체제의 커널이나 커널 드라이버: 시스템을 리셋

또한 유저 애플리케이션이 구동되는 EL0에서 svc 명령어를 실행(시스템 콜)하면 Arm 코어는 Synchronous 익셉션을 유발합니다. Synchronous 익셉션 핸들러에서는 익셉션이 발생한 세부 원인을 ESR_ELx 레지스터를 통해 확인한 후, 시스템 콜 핸들러를 호출합니다.

[중요] 
Synchronous 익셉션이 유발되면 익셉션 핸들러에서 ESR_ELx를 읽으면 익셉션이 유발된 세부 원인을 파악할 수 있습니다. Arm8 아키텍처에서 익셉션이 유발된 세부 원인을 익셉션 클래스라고 정의하는데, 익셉션 클래스는 어떤 이유로 익셉션이 유발됐는지를 나타내는 6개의 비트 정보로 구성돼 있습니다. 참고로 Arm 코어는 익셉션을 감지하는 과정에서, 익셉션이 유발된 원인을 확인한 후 익셉션 클래스에서 정의된 비트를 ESR_ELx 레지스터의 [31:26] 비트에 저장합니다. 


둘째, IRQ 익셉션이 유발되면 호출되는 익셉션 핸들러의 처리 방식은 Arm7 아키텍처와 같습니다. IRQ 익셉션은 외부 하드웨어의 변화를 알리기 위한 인터페이스로 동작하므로, 익셉션 핸들러에서 인터럽트 서비스 루틴을 실행합니다. 운영체제의 커널은 인터럽트 서비스 루틴을 통해 인터럽트 핸들러를 호출하며, 인터럽트 핸들러에서는 발생한 인터럽트에 대한 세세한 처리를 수행합니다.

셋째, Armv8 아키텍처에서 새롭게 정의된 SError 익셉션은 외부 메모리 유닛에서 어보트가 감지될 경우 비동기적으로 유발됩니다. 대부분 소프트웨어적으로 치명적인 오류가 있을 때 외부 메모리 유닛에서 어보트가 감지되므로, SError 익셉션 핸들러는 주요 레지스터 정보를 콘솔 로그로 출력한 다음 시스템을 리셋시키는 동작을 수행합니다. 

아래 링크에서 SError 익셉션 핸들러가 실행될 때 출력되는 로그를 확인할 수 있습니다.

https://bugzilla.kernel.org/show_bug.cgi?id=200429

[  192.082927] Kernel panic - not syncing: Asynchronous SError Interrupt
[  192.082928] CPU: 4 PID: 2424 Comm: devmem Not tainted 4.17.0-02102-gdcfa25a-dirty #109
[  192.082929] Hardware name: Stingray Combo SVK (BCM958742K) (DT)
[  192.082930] Call trace:
[  192.082939]  dump_backtrace+0x0/0x1b8
[  192.082941]  show_stack+0x14/0x1c
[  192.082943]  dump_stack+0x90/0xb0
[  192.082945]  panic+0x140/0x2a8
[  192.082946]  __stack_chk_fail+0x0/0x18 // nmi_panic
[  192.082947]  arm64_serror_panic+0x74/0x80
[  192.082948]  do_serror+0x48/0xa0
[  192.082949]  el0_error_naked+0x10/0x18
[  192.082954] SMP: stopping secondary CPUs
[  192.082957] Kernel Offset: disabled
[  192.082959] CPU features: 0x21806008
[  192.082959] Memory Limit: none
[  192.267536] ---[ end Kernel panic - not syncing: Asynchronous SError Interrupt ]---

로그에는 SError 익셉션이 발생한 콜 스택과 커널 패닉이 실행될 것이라는 정보를 확인할 수 있습니다.

여기까지 Armv8 아키텍처의 익셉션을 구성하는 주요 기능에 대해 소개했습니다. 각 기능이 어떤 방식으로 동작하는지 대해서는 이어지는 절에서 살펴보겠습니다. 이어지는 절에서는 전체 시스템의 관점으로 익셉션의 타입 별로 처리되는 실행 흐름을 살펴보겠습니다.

Reference: ARMv8 아키텍처 - 익셉션(Exception)

Armv8 익셉션의 종류와 분류 체계 
익셉션의 전체 실행 흐름  

Written by <디버깅을 통해 배우는 리눅스 커널의 구조와 원리(2021년 대한민국 학술원 우수도서)> 저자



---

핑백

덧글

댓글 입력 영역