본문 바로가기
시스템 반도체/Arm

Arm GIC, SGI ( interrupt controller, 인터럽트 컨트롤러 )

by 전컴반 2022. 5. 31.
반응형

많은 I/O device로부터 발생하는데, 이렇게 많은 장치들이 interrupt를 발생시키는데 cpu는 제한된 interrupt선을 가지고 있다. 어떻게 선택할 수 있을까?? interrupt controller (APIC, PIC, INTC, GIC..)라는 하드웨어를 가지고 구현한다.

 

 interrupt controller가 필요한 이유는 다음과 같다.

모든 I/O device는 상태 레지스터를 가지고 있는데.  ISR이 발생하면 cpu는 device의 state 레지스터 값을 읽어온 후에 동직 하는데 만약 device가 엄청나게 많다면 latency가 엄청나게 오래 걸릴 것이다. 

 

또한 여러 개의 device가 동시에 interrupt를 발생시키면 어떻게 할까?? 누구가 먼저 실행돼야 하나, 이런 문제가 발생한다. 즉 우선순위의 문제가 생긴다. 이런 문제를 해결하기 위해 interrupt controller가 필요하다.

 

 

GIC ( Generic Interrupt Controller )

 

GIC는 Arm에서 interrupt controller를 칭하는 명칭이다.

GIC안에는 굉장히 많은 종류의 레지스터가 있지만 여기선 중요한 대표적인 개요를 본다는 느낌으로 보겠다. 또한 GIC에도 버전이 있는데 가장 기본 버전을 기준으로 보겠다.

 

 

GIC안에는 Distributor라는 하드웨어와 CPU interface라는 하드웨어가 있다. 그리고 GIC와 CPU는 IRQ와 FIQ를 통해 정보를 보낸다. 이때 CPU는 최대 8개까지 연결할 수 있다. 그러니 CPU interface 또한 8개로 구성돼 있다. 하지만 Distributor는 1개만 존재한다. 말 그대로 분배하는 역할을 하기 때문에 1개만 있다.

정리하면 GIC에는 1개의 Distributor와 8개의 CPU interface가 있다. (만약 CPU가 8개가 없다면 맞게 커스터마이징 할 수 있다.)

 

interrupt를 받는데 1020개의 devie를 받을 수 있다. 그리고 각각의 device는 고유 번호를 부여받는다. 위의 예시에는 timer는 29번 UART는 61번 이런 식이다.

 

그렇다면 interrupt를 발생시킨 device를 어느 CPU에서 실행할지 정해야 한다. 이걸 정하는 register가 Target register다. CPU가 8개가 있으니 8bit로 구성돼 있다. 모든 device가 가지고 있으니 1020개가 있는데 target register는 4byte로 지정돼 있다. 그러니 4개의 target register가 하나의 target rigster가 된다. 255개의 target register가 있다.

 

뭔 소린가 싶다. 정리하면, 8bit로 구성된 target register 4개가 실제 target register다. target register0와 같이 index를 이용하여 찾을 수 있다. 위 그림을 보면 이해가 쉬울 것이다.

 

 

다음으로는 우선순위를 해결하는 방법이다. 각각의 device는 어떤 우선순위를 가질지 지정하는 Prioirty register인데 Target register와 똑같이 4byte를 가지고 1020개의 레지스터가 존재한다. 또한 4개의 레지스터가 1개의 레지스터를 구성한다. 실행 interrupt가 어떤 우선순위를 가질지 저장한다.

 

 

이제 CPU interface에 대해 보자, 안에는 엄청나게 많은 register가 존재한다. 그중에 중요한 기능 3가지만 보자.

 

1. PMR ( Priority Mask Register )

간단히 말해 우선순위를 평가하여 비교한다. threshold를 지정한다. 우선순위가 낮으면 대기하고 높으면 CPU로 진입시킨다. 이렇게 하여 우선순위의 역전을 막을 수 있다. 

 

2. IAR ( Interrupt Acknowledge Register )

- 간단히 말해 어떤 device가 interrupt를 발생시켰는지 저장해 놓는 register이다. 앞에서 말한 1020개 중에 어떤 번호를 받았는지 저장한다. ldr을 이용하여 읽어올 수 있다. 만약 UART가 interrupt를 발생했다면 IAR에는 61이 저장된다.

 

추가적으로 보면, CPUID가 있는데 아래서 보면 SGI를 발생시킨 CPU를 저장하는 bit다. SGI가 뭔지는 아래 설명하겠다.

 

 

3. EOIR ( End Of Interrupt Register )

- 간단히 말해 interrupt가 끝났다는 걸 알려주는 register다. 이때 IAR에 저장돼 있는 device의 값을 적어준다. 즉 어떤 device가 끝났는지 알려주고 다른 interrupt를 받을 준비가 됐다는 걸 의미한다. store 명령을 수행한다.

 

IAR과 마찬가지로 SGI를 발생시킨 CPU를 저장하는 CPUID를 저장하는 bit가 따로 있다.

 

 

 

SGI (Software Generated Interrupt)

 

하드웨어 Interrupt다. GIC에서는 1020개의 interrupt를 받는데, 각각 고유 index를 부여받는다.

이때, 0~15번까지를 SGI (software generated interrupt)로 할당한다. 또한 16~31번은 private I/O device interrupt를 할당하고 나머지 32~1019번까지는 shared I/O device에게 할당된다. 이 중에 0번에서 15번인 SGI를 알아보자.

 

SGI는 간단히 말해 자기 자신(CPU)이 다른 CPU혹은 자기 자신에게 interrupt를 발생시키는 동작이다. 즉 어떤 I/O device에 의해 생성되는 interrupt가 아닌 software에 의해 생성되는 interrupt다.

 

Distributor 안에 SGIR (Software Generated Interrupt register)가 있는데 포맷은 다음과 같다.

 

 

SGIINTID : 0~3bit는 할당된 ID를 적는다.

 

CPUTargetList : 16 ~ 23bit에는 어느 CPU에서 돌릴 건지 적는다. (8비트)

 

TargetListFilter : 24 ~ 25bit는 00이면 그냥 CPUTargetList로 쓰고, 01이면 interrupt 수신자가 자기 자신(CPU)이고, 10이면 자기를 제외한 모든 CPU를 말한다. 

 

 

 

이렇게 CPU가 다른 CPU혹은 자신 CPU에게 왜 interrupt를 걸까??

이런 동작을 전문용어로 IPI ( Inter Processor Interrupt )라고 한다. IPI를 하는 이유는 여러 가지가 있다.

 

가령, 컴퓨터를 켰을 때 먼저 켜진 하나의 CPU가 다른 CPU를 깨우거나 ( SIPI ), 운영체제에서 task를 놀고 있는 CPU에게 보낸다거나 ( Task Dispatch ) 등등 여러 이유가 있다.

반응형

댓글