많은 분들이 생각하는 익셉션의 개념은 'Armv7 아키텍처의 익셉션'인 경우가 많아, Armv8 아키텍처를 배울 때 Armv7 아키텍처의 익셉션과 비슷할 것이라 예상합니다. 익셉션이 발생하면 지정한 주소로 프로그램 카운터를 브랜치하는 기본 개념은 Armv7/Armv8 아키텍처가 같으나, 익셉션을 처리하고 분류하는 체계와 세세한 처리 방식이 많이 다릅니다.

Armv8 아키텍처의 익셉션은 고성능 컴퓨터에서 적용되는 트러스트 존이나 가상화 시스템인 하이퍼바이저를 이해하기 위해 반드시 알아야 할 기반 지식이므로, 반드시 잘 알아야 둬야 합니다. 

익셉션(Exception)은 Armv8 아키텍처의 핵심 기능 중 하나입니다. Armv8 아키텍처에서 정의된 익셉션를 활용해 하이퍼바이저와 같은 가상 시스템을 설계할 수 있습니다. 또한 트러스트 존을 제대로 이해하려면 먼저 익셉션의 동작 방식을 알아야 합니다. 

Armv8 아키텍처에서 익셉션은 어떻게 정의내릴 수 있을까요? 기존에 소개된 Armv8 아키텍처의 익셉션과는 어떤 차이점이 있을까요? Armv8 아키텍처에서는 기존 Armv7 아키텍처와 비교해 익셉션의 종류를 분류하는 방식이 조금 다르지만, 익셉션의 동작 원리는 동일합니다. Armv8 아키텍처의 익셉션은 다음과 같이 설명할 수 있습니다.

 

“익셉션이란 Arm 코어가 명령어를 처리하다가 예외 사항이 발생할 때 이를 처리하는
방식이다. 익셉션이 발생하면 익셉션 벡터로 프로그램 카운터가 브랜치된다.”

 


위 문장을 읽으면 "어, Armv8 아키텍처의 익셉션은 Armv7 익셉션과 거의 같네"라는 생각이 들수 있습니다. 하지만 Armv8 아키텍처의 익셉션은 Armv7 익셉션과 비교했을 때 기본 개념은 같지만 익셉션을 분류하고 처리하는 방식이 다릅니다.

이제부터 Armv8 아키텍처의 익셉션에 대해서 배워 봅시다.

그 동안 Arm 아키텍처는 CPU 아키텍처 시장에서 '저전력', '소형 디바이스' 용으로 사용되는 CPU 아키텍처로 분류됐습니다. 최대한 적은 트렌지스터를 사용해 최소의 소모 전력으로 CPU를 설계했기 때문입니다. 물론 Arm 코어의 CPU 아키텍처도 최대한 심플하게 디자인했습니다.

익셉션의 구조 관점으로 보면, Armv7 아키텍처의 익셉션도 다음과 같이 심플하게 설계됐다고 볼 수 있습니다. 

   ❑ 익셉션 벡터가 4바이트 단위로 정렬
   ❑ 어떤 Arm 동작 모드에서 익셉션이 발생해도 익셉션 벡터로 브랜치
   ❑ 익셉션의 종류도 8개로 정의 내림

그런데, Armv8 아키텍처는 CPU 아키텍처 시장에 "우리는 고성능 컴퓨터나 클라우드 서버에 진출하겠다"라고 출사표를 던지고 설계한 것으로 보입니다. 기존의 소형 저전력 디바이스 용으로 설계된 CPU 아키텍처가 아니라 인텔의 x86과 경쟁할 수 있는 CPU 아키텍처를 설계한 것입니다.  

이런 면모는 Armv8 아키텍처의 익셉션에서 볼 수 있습니다. 이제 Armv8 아키텍처의 익셉션의 주요 특징을 Armv7 익셉션과 비교하면서 알아보겠습니다.

하이퍼바이저 콘트롤 레지스터는 하이퍼바이저의 세부 동작을 설정하는 가장 중요한 레지스터 중입니다. HCR_EL2은 EL1에서 일어나는 세부 동작에 따라 EL2으로 진입(트랩)하는 방식을 설정할 수 있는 비트맵으로 구성돼 있습니다.


다음 그림은 HCR_EL2 레지스터의 비트 맵 정보입니다.



그림 12.3 HCR_EL2 레지스터의 비트 맵 <출처: DDI0487G_b_armv8_arm.pdf> 

다른 레지스터와 같이 레지스터를 구성하는 비트를 1로 설정하면, 해당 비트 맵과 관련된 동작이 수행됩니다. HCR_EL2 레지스터를 구성하는 비트 맵 중에 중요한 내용을 소개하겠습니다.

IMO, bit [4]

이 비트가 1로 설정되면 EL2이나 EL1에서 설정된 인터럽트를 EL2에서 받아 처리합니다. 만약 SCR_EL3.IRQ 비트가 1로 설정되면 EL3가 인터럽트를 받아 처리합니다. 만약 0으로 설정되면 EL2보다 낮은 익셉션 레벨에서 설정된 인터럽트를 EL2가 받지 않습니다.

AMO, bit [5]

이 비트는 EL1에서 발생한 Asynchronous 익셉션을 EL2에서 처리하기 위한 용도로 사용됩니다.
AMO 비트가 1로 설정됐으면 EL2이나 EL2보다 낮은 익셉션 레벨에서 Asynchronous 혹은 SError 인터럽트가 발생하면 EL2로 트랩됩니다. 

TWI, bit [13]

이 비트를 1로 설정하고 EL0 혹은 EL1에서 wfi 명령어를 실행하면 트랩이 발생하면서 EL2로 익셉션 레벨이 바뀝니다. 만약 0으로 설정된 경우 wfi 명령어를 실행하면 arm 코어가 저전력 모드로 진입하게 동작합니다. 

TWE, bit [14]

이 비트를 1로 설정하고 EL0 혹은 EL1에서 wfe 명령어를 실행하면 트랩이 일어나며, 이 과정에서 EL2로 진입합니다. 만약 0으로 설정된 경우에 wfe 명령어를 실행하면 arm 코어가 저전력 모드로 실행됩니다.

TSC, bit [19]

TSC 비트가 1로 설정된 경우, EL1에서 smc 명령어를 실행하면 EL2로 트랩됩니다. 일반적으로 EL1에서 smc 명령어를 실행하면 EL3에 존재하는 모니터 모드로 진입합니다.

그런데 여러 게스트 OS에서 smc 명령어를 동시다발적으로 실행하면 예기치 못한 문제가 발생할 수 있어, smc 명령어를 하이퍼바이저가 받아서 제어해야 할 상황이 있습니다. 이를 smc 명령어 후킹이라고 합니다.

TVM, bit [26]

가상 메모리를 제어하기 위한 트랩을 설정하는 비트입니다. TVM 비트가 1로 설정되면, EL1에서 다음와 같은 메모리를 제어하는 레지스터에 어떤 값을 쓰면 EL2로 트랩됩니다. 

   * SCTLR_EL1, TTBR0_EL1, TTBR1_EL1, TCR_EL1, ESR_EL1, FAR_EL1, AFSR0_EL1, AFSR1_EL1, MAIR_EL1, AMAIR_EL1, CONTEXTIDR_EL1.

EL2로 트랩될 때 Arm 코어는 하드웨어적으로 익셉션 신드롬 레지스터에 0x18값을 써줍니다.

TGE, bit [27]

TGE 비트가 1로 설정되면 EL1에서 발생한 익셉션이 EL2로 라우팅됩니다. EL1에서 익셉션이 발생하면 EL1에 존재하는 익셉션 벡터 주소(VBAR_EL1 기준)로 프로그램 카운터가 브랜치되는 것이 아니라, EL2로 익셉션 레벨이 바뀌면서 EL2이 위치한 익셉션 벡터 주소(VBAR_EL2 기준)로 프로그램 카운터가 바뀝니다.

운영체제의 커널에서 실행되는 시스템 정보를 EL2에서 실행되는 하이퍼바이저가 후킹할 때도 사용됩니다.

HCD, bit [29]

HCD 비트는 하이퍼바이저 콜을 설정하는 기능입니다. HCD 비트가 1로 설정되면 hvc 명령어가 활성화되고, HCD 비트가 0으로 설정되면 hvc 명령어가 비활성화(Undefined)됩니다.

 

< '시스템 소프트웨어 개발을 위한 Arm 아키텍처의 구조와 원리' 저자>

 

 

 

+ Recent posts