TIL/2025

Learn the architecture - Generic Interrupt Controller v3 and v4, Overview

고무 오리 2025. 6. 12. 20:13
728x90
📢 GIC 봐도봐도 헷갈려서 간단하게 정리해봤어요

 

GIC는 무엇이고 왜 필요한가?

Interrupt는 보통 외부 peripheral가 발생 시키는 event를 의미해요

이 Interrupt에 우선순위를 매기고 적합한 PE(Process Element, CPU)에게 전달하는 역할을 하는게 ARM이 설계한 GIC에요

 

요즘은 멀티 코어를 사용하다보니 peripheral이 발생 시킨 Interrupt를 목적 CPU에 라우팅하기 위한 별도의 controller가 꼭 필요하죠

 

 

Interrupt는 어떤 경로로 전달 되나?

Interrupt 종류 별 전달 경로가 다르다

SPI (Shared Peripheral Interrupt)

  • 모든 core에게 전달 될 수 있는 interrupt (별도 세팅 없으면 적절한 core에 전달)
  • Peripheral > Distributor > Redistributor > CPU Interface > Core

PPI (Private Peripheral Interrupt)

  • 특정 core를 위한 interrupt (예시, Timer interrupt)
  • Private Peripheral > CPU Interface > Redistributor > CPU Interface > Core

SGI (Software Generated Interrupt)

  • core 간 통신을 위해 Software적으로 발생 시키는 Interrupt
  • Core A > CPU Interface A > Redistributor A > Redistributor B > CPU Interface B > Core B

LPI : 특별한 친구

 

Interrupt ID는 누가 정해?

GIC Architecture로 정해놓음

interrupt 종류 별 Interrupt ID 범위를 정해놓음

  • SGI (INTID 0~15)  / SPI (INTID 32~) / PPI (INTID 16~31) 

 

Interrupt 상태 4가지는?

Peripheral -> GIC -> PE

 

Inactive : Peripheral에서 아직 인터럽트 신호를 발생시키지 않음

Pending : Peripheral이 인터럽트 신호를 GIC에 전달 했으나, PE가 아직 읽어보진 않음

Active : PE가 인터럽트를 받아 (acknowledge), ISR 핸들러 진입

Active and Pending : PE가 첫 요청을 처리 중인데, 같은 Peripheral 인터럽트 추가 발생

 

 

PE(Core)는 인터럽트 종류 어떻게 식별하나?

IAR Register로 인터럽트 ID 식별, EOI Register로 인터럽트 완료 설정

 

 

SPI Interrupt 발생 시 특정 pcpu에만 전달하는 방법이 있나?

있다! Interrupt 별 affinity Register 에 Target PE의 MPIDR 값을 지정

 

affinity 지정 포맷은 하기와 같으며

<affinity level 0><affinity level 1><affinity level 2><affinity level 3>

 

보통 이렇게 지정하여 하나의 core를 식별 함

<group of processors><group of groups><processor><core>

 

예를 들어, SPI 42번은 2번 core에게 전달 하려면 초기화 시 아래와 같이 설정

GICD_IROUTER42 = (0 << 32) | (0 << 16) | (0 << 8) | 2;

 

 

그럼 GIC HW Register 세팅은 어떤 순서로 진행할까?

1. Distributor

GICD register로 제어 (memory mapping 방식)

  • SPI 설정 (인터럽트 별로 활성화,우선순위, SPI 라우팅, trigger 방식 설정)
  • affinity routing 사용 여부 설정
  • 필요한 group enable (Secure / Non-secure)

 

2. Redistributor

PE 별 존재하는 GICR Register로 설정

  • 해당 core 전용 interrupt인 ppi/sgi 설정 (활성화, 우선순위, 트리거 방식)
  • PE online임을 보장하는 GICR_WAKER 설정 (CPU Interface 설정 전 PE가 online 임을 꼭 확인 해야함)

 

3. CPU Interface

ICC_SRE_ELn 레지스터로 시스템 레지스터 접근 허용 후

  • EOI 모드 설정
  • Interrupt 인지 및 IAR 읽기, 처리완료 EOI
  • 우선순위 mask 설정

 

이외에 PE 자체 설정도 필요해요

  • HCR_EL2 설정통해 인터럽트 어떤 EL에 전달할지 결정
  • PSTATE 설정으로 인터럽트 수신 여부 설정
  • Vector table 설정

 

더 자세하게 살펴보면.. (열면 다쳐)

더보기

🔧 GICv3 설정 항목별 용도 정리

 

Distributor 설정 (GICD)

GICD_CTLR (ARE, Group Enable 등)
GICv3 모드 활성화 (ARE=1), 어떤 Group (0, 1S, 1NS)의 인터럽트를 사용할지 시스템 전체적으로 결정

GICD_IPRIORITYn (SPI 별 우선순위)
각 SPI(INTID 32~)의 우선순위 지정, 값이 낮을수록 높은 우선순위
Preemption과 Priority Mask 비교에 사용됨.

GICD_IGROUPn (SPI 보안 그룹 설정)
SPI가 Secure/Non-secure Group 중 어디에 속하는지 결정

GICD_ICFGRn (SPI 트리거 타입)
각 SPI가 Level-sensitive 또는 Edge-triggered 인지 결정. Peripheral 특성에 따라 선택.

GICD_ISENABLERn (SPI Enable)
해당 SPI를 활성화하여 인터럽트 발생 가능 상태로 설정

GICD_IROUTERn (SPI 라우팅)
해당 SPI를 어느 PE (core)로 전달할지 결정. Affinity 값을 사용하여 타겟 지정.

 

 

Redistributor 설정 (GICR)

GICR_WAKER (PE online 상태 보장)
Redistributor가 해당 PE를 인터럽트 수신 가능한 상태로 만들지 결정. ProcessorSleep 비트 클리어 시 online.

GICR_IPRIORITYn (SGI/PPI 우선순위)
PPI/SGI(INTID 0~31) 우선순위 설정. SPI와 마찬가지로 낮은 값이 높은 우선순위.

GICR_IGROUPn (SGI/PPI 그룹 설정)
SGI/PPI가 Secure/Non-secure Group 중 어디에 속하는지 결정.

GICR_ICFGRn (PPI 트리거 타입)
PPI에 대해 Edge-triggered 또는 Level-sensitive 설정. (SGI는 항상 edge로 고정)

GICR_ISENABLERn (SGI/PPI Enable)
해당 SGI/PPI를 활성화하여 인터럽트 발생 가능 상태로 설정.

 

 

CPU Interface 설정 (ICC_*)

ICC_SRE_ELn (System Register Interface Enable)
System register 기반의 GIC interface 사용을 활성화 (GICv3 필수). 대부분 프로세서에서 항상 enable됨.

ICC_PMR_EL1 (Priority Mask)
현재 PE에서 허용할 우선순위 상한선 결정. 이 값보다 높은 우선순위만 인터럽트 허용.

ICC_BPR_ELn (Binary Point)
Priority를 그룹핑하여 preemption을 제한할 depth 결정. Nested interrupt control에 사용됨.

ICC_CTLR_ELn (EOI Mode 등)
인터럽트 종료 시 Active 상태 해제 방법을 설정. EOImode=1이면 단순화됨.

ICC_IGRPENx_ELn (Group Enable)
PE에서 각 Group (0, 1S, 1NS) 인터럽트를 받을지 여부를 결정.

ICC_IAR / ICC_EOIR
인터럽트 인지 (Acknowledge) 및 종료 (End Of Interrupt) 처리에 사용됨.

 

 

PE 자체 설정

HCR_EL2, SCR_EL3 (Routing Control)
인터럽트 발생 시 어떤 Exception Level로 들어갈지 결정. Hypervisor/Monitor 진입 여부를 이걸로 통제.

PSTATE.DAIF (Interrupt Mask Bits)
인터럽트 수신 여부를 결정. DAIF 클리어하면 인터럽트 수신 가능.

VBAR_ELn (Vector Table Base)
Exception 발생 시 진입할 핸들러 테이블의 base 주소 지정.



🔑 한 줄 요약

GIC는 Distributor → Redistributor → CPU Interface → PE 초기화 순서로 세팅되며, 각 단계마다 "누가 받을지", "언제 받을지", "어떤 우선순위로 받을지"를 명확히 설정해줘야 한다.

 

 

PE가 인터럽트 처리 중인데 다른 인터럽트가 발생해 끼어들면?

GIC가 새로운 인터럽트 끼어들기 가능 여부를 아래 두가지 기준으로 평가

 

판단1. Priority Mask (ICC_PMR_EL1) 보다 높은 priority인지 확인

  • 여기서 걸리면 interrupt 무시! (pending도 못감)

판단2. Running Priority (ICC_RPR_EL1) 보다 높은 우선순위 인터럽트인가?

  • Yes → Preemption 발생 → PE가 새 Exception 처리 (Nested Interrupt)
    (이후 원래 인터럽트 처리 마저 진행)
  • No →  Preemption 불가 → 새 인터럽트는 현재 수행 중인 인터럽트 끝날 때까지 Pending 상태로 대기

 

 

전체적인 인터럽트 핸들링 흐름은?

GIC 처리 흐름을 전체적으로 살펴보자

  • (2) ~ (7)은 GIC Diestributor가 알아서 확인
  • (8) ~ (13)은 ISR 수행 과정
┌──────────────┐
│ Peripheral   │
└────┬─────────┘
     │ (1) Assert Interrupt (HW Signal or MSI)
┌────▼───────────────────┐
│ GIC Distributor (GICD) │
└────┬───────────────────┘
     │ (2) INTID → Pending 상태 전환
     │ (3) Group Enable 검사 (Distributor+CPU Interface)
     │ (4) Enable Bit 검사 (INTID별)
     │ (5) Routing 결정 (SPI→IROUTER, PPI/SGI→PE 고정)
     │ (6) Priority Mask 검사 (ICC_PMR_EL1)
     │ (7) Running Priority 검사 (ICC_RPR_EL1)
     ▼
┌────────────────┐
│ PE (CPU Core)  │
└────┬───────────┘
     │ (8) IRQ/FIQ Exception Entry (EL1, EL2 등)
     │ (9) 핸들러 진입 → IAR 읽기 (For INTID 파악)
     │     ┌───────────────┐
     │     │ ICC_IARx_ELn  │
     │     └───────────────┘
     │ (10) INTID 획득
     │ (11) 핸들러 수행
     │     (Nested 발생시 → Binary Point로 Preemption 결정)
     │ (12) 핸들러 종료 → EOI
     │     ┌───────────────────────┐
     │     │ ICC_EOIR_ELn          │
     │     │ (+ DIR if EOImode=1)  │
     │     └───────────────────────┘
     │ (13) Priority Drop + Deactivation 완료
     ▼
[다음 인터럽트 대기 → 위 과정 반복]

 

 

 

 

Reference

https://developer.arm.com/documentation/198123/0302?lang=en

 

Documentation – Arm Developer

 

developer.arm.com

 

728x90