본문 바로가기

시스템 소프트웨어 개발을 위한 Arm 아키텍처의 구조와 원리/9장: Armv8 - 익셉션

[Arm프로세서] Armv8 아키텍처에서 익셉션 레벨 별로 익셉션이 처리되는 흐름

Armv7 아키텍처의 익셉션과 비교했을 때, Armv8 아키텍처에서는 익셉션을 분류하는 체계와 익셉션 벡터 테이블이 약간 다릅니다. 그 특징에 대해서 더 자세히 알아봅시다.

첫째, Armv8 아키텍처에서는 익셉션의 종류를 계층 구조로 재정의했습니다. 먼저 익셉션을 Synchronous와 Asynchronous와 같이 큰 카테고리로 분류하고, 하부 카테고리로 익셉션 클래스를 정의했습니다. Armv7 의 익셉션의 종류는 익셉션 클래스에서 확인할 수 있습니다.


표 9.1 Armv8 아키텍처에서 익셉션의 분류 체계

먼저 익셉션을 Synchronous와 Asynchronous와 같이 큰 카테고리로 분류합니다. Arm 코어가 명령어를 실행하다가 유발하는 익셉션을 Synchronous, 외부 인터럽트나 외부 메모리 어보트와 같이 외부에서 비동기적으로 유발되는 익셉션을 Asynchronous로 분류합니다. 이처럼 기존 Armv7 아키텍처의 익셉션과 비교해 익셉션을 분류하는 방식이 다릅니다.

둘째, 익셉션 레벨(EL)이란 개념을 도입해 이 기준으로 익셉션을 처리합니다. 익셉션이 유발된 익셉션 레벨 별로 익셉션 벡터 주소가 존재하며, 익셉션 레벨 별로 익셉션 링크 레지스터를 정의합니다.

다음 그림은 Armv8 아키텍처에서 익셉션 레벨 별로 익셉션 처리되는 구조를 나타냅니다.



그림 9.1 Armv8 아키텍처에서 익셉션 레벨 별로 익셉션이 처리되는 흐름

그림의 윗 부분을 먼저 보겠습니다. 유저 애플리케이션이 구동되는 EL0에서 익셉션이 발생하면 다음 순서로 처리됩니다.
  
    1.유저 애플리케이션이 구동되는 EL0에서 익셉션이 발생
    2.EL1으로 진입
    3.EL0용 익셉션 벡터로 브랜치 

이어서 그림의 아랫 부분은 운영체제의 커널이 구동되는 EL1에서 익셉션이 발생하면 처리되는 흐름입니다. EL1에서 익셉션이 유발되면 다음 순서로 처리됩니다.

   1. 운영체제 커널이 구동되는 EL1에서 익셉션이 발생
   2. EL1용 익셉션 벡터로 브랜치

이처럼 Arm코어는 익셉션이 유발되면 익셉션이 발생한 익셉션 레벨 별로 지정된 익셉션 벡터로 프로그램 카운터를 브랜치합니다.

[정보]
EL0과 EL1은 각각 Armv7 아키텍처의 User 모드, Supervisor 모드에 대응됩니다.
Armv7 아키텍처의 User 모드에서는 유저 애플리케이션이 구동하고, Supervisor 모드에서는 운영체제의 커널이 동작합니다. 마찬가지로, Armv8 아키텍처의 EL0에서는 유저 애플리케이션이 실행되고, EL1에서는 운영체제의 커널이 동작합니다.  

Armv7 아키텍처에서는 어떤 Arm 동작 모드에서 익셉션이 유발돼도 익셉션 종류 별로 지정된 익셉션 벡터로 프로그램 카운터가 브랜치됩니다. 예를 들어 유저 애플리케이션이 실행되는 User 모드나 운영체제의 커널이 구동되는 슈퍼바이저 모드에서 데이터 어보트가 유발되면, 데이터 어보트 익셉션에 해당되는 익셉션 벡터로 프로그램 카운터가 브랜치됩니다. 

그래서 익셉션 핸들러에서 익셉션이 유발된 시점의 Arm 동작 모드를 읽어서 이를 세분화하는 명령어를 입력해야 합니다. 예를 들어, 리눅스 커널인 경우 다음 코드와 같이 Arm 동작 모드를 읽어서 세분화해 처리하는 동작을 확인할 수 있습니다. 

다음은 Armv7 아키텍처 기반 리눅스 커널에서 구현된 Undefined Instruction 익셉션 핸들러의 구현부입니다.

01 NSR:FFFF11A0|E88D4001        vector_und:   stm     r13,{r0,r14}
02 NSR:FFFF11A4|E14FE000                      mrs     r14,spsr
03 NSR:FFFF11A8|E58DE008                      str     r14,[r13,#0x8]
04 NSR:FFFF11AC|E10F0000                      mrs     r0,cpsr
05 NSR:FFFF11B0|E2200008                      eor     r0,r0,#0x8       ; r0,r0,#8
06 NSR:FFFF11B4|E16FF000                      msr     spsr_cxsf,r0
07 NSR:FFFF11B8|E20EE00F                      and     r14,r14,#0x0F    ; r14,r14,#15
08 NSR:FFFF11BC|E1A0000D                      cpy     r0,r13
09 NSR:FFFF11C0|E79FE10E                      ldr     r14,[pc,+r14,lsl #0x2]
10 NSR:FFFF11C4|E1B0F00E                      movs    pc,r14
11 NSP:FFFF11C8|C010F680                      dcd     0xC010F680       ; __und_usr
12 NSP:FFFF11CC|C010F130                      dcd     0xC010F130       ; __und_invalid
13 NSP:FFFF11D0|C010F130                      dcd     0xC010F130       ; __und_invalid
14 NSP:FFFF11D4|C010F2C0                      dcd     0xC010F2C0       ; __und_svc

02번째 줄은 spsr 레지스터를 읽어 r14 레지스터에 저장하는 명령어입니다.
r14 레지스터는 익셉션이 발생한 시점의 Arm 동작 모드가 저장돼 있는데, 이 값에 따라 다른 레이블로 브랜치하는 코드(01~10번째 줄)가 실행됩니다.

그런데 Armv8 아키텍처에서는 익셉션이 발생한 익셉션 레벨 기준으로 익셉션 벡터가 브랜치되므로, 구지 소프트웨어적으로 익셉션이 유발된 시점의 익셉션 레벨에 따라 처리할 필요가 없습니다. 

넷째, 기존 Armv7의 익셉션 벡터 주소는 워드(32비트 기준: 4바이트)로 정렬됐으나, Armv8의 경우 0x80바이트 단위로 정렬됐습니다. 익셉션 벡터 주소에서 익셉션를 바로 처리할 수 있는 명령어를 실행할 수 있습니다.

다음은 Arm 사에서 배포한 문서에 담긴 익셉션 벡터 테이블입니다.
 

그림 9.2 Armv8 아키텍처의 익셉션 벡터 테이블

위 그림에서 박스로 표기된 부분을 보면 0x000, 0x080, 0x100, 0x180이 보이는데 이는 익셉션의 종류 별 익셉션 벡터 오프셋을 나타냅니다. 이처럼 Armv8 아키텍처는 익셉션의 종류 별 오프셋 주소의 사이즈가 0x080 바이트입니다.

 


[정보]
익셉션 벡터 베이스 주소에 익셉션 벡터 오프셋 주소를 더한 주소로 프로그램 카운터가 브랜치됩니다.