이 코드는 어떤 문제를 푸나요?
CPU가 IRQ를 처리했다는 사실을 GIC에도 반영해야 다음 알림을 정상적으로 처리할 수 있습니다. 아래는 물리 GICv3의 EOI 함수를 읽는 예입니다. vGIC의 가상 pending과 List Register는 별도 상태이므로 물리 EOI를 곧바로 게스트 EOI와 같은 동작으로 설명하지 않습니다.
줄별 풀이 범위: v6.18.37 · drivers/irqchip/irq-gic-v3.c · gic_eoi_irq 719–733행입니다. 아래에 이 범위의 원문과 각 줄의 설명을 실었습니다. 주제 전체의 흐름과 다른 경로는 기존 분석에서 함께 읽으실 수 있습니다.
먼저 알아둘 개념
물리와 가상 인터럽트
호스트가 실제 GIC에서 받은 요청과 게스트에 보여 주는 요청은 다른 상태 기계입니다.
EOImode
우선순위 종료와 비활성화가 한 동작인지 분리되는지를 좌우합니다.
List Register
GIC 가상화 인터페이스가 게스트에게 보여 줄 인터럽트 상태를 담는 자원이며 무한한 큐는 아닙니다.
처음 읽을 때
장치→호스트 GIC→KVM→게스트의 알림 경로를 나누어 설명하십시오.
더 깊이 살펴볼 때
물리 IRQ를 vCPU에 전달할 때 deactivate 책임이 어떻게 달라지는지 EOImode1 경로와 비교하십시오.
그림으로 보는 변화

gic_eoi_irq()의 일반 EOI와 조건부 erratum 마무리만 보여 줍니다. 아래 도식은 별도 KVM 가상 IRQ·LR 경로와의 경계를 설명합니다.물리 EOI와 가상 LR은 어디서 갈라질까?
호스트의 물리 GIC EOI
- 하드웨어 INTID.
irq_data에서 GIC 번호를 가져옵니다. 원문 721행 - EOI 기록.
ICC_EOIR1_EL1에 쓰고isb()로 동기화합니다. 원문 721–722행 - 조건부 마무리. erratum 2941627 보완이 필요할 때만
dsb(sy)뒤GICD_ICACTIVER를 갱신합니다. 원문 724–731행
KVM의 가상 GIC LR 경로
- 별도 주입 입구.
kvm_vgic_inject_irq()가 입력을 검증하고 level/edge에 따라 가상 상태를 갱신합니다. 원문 471–508행 - 대기와 LR 구성. 필요 시 vCPU의
ap_list에 놓고, GICv3 호스트 인터페이스의 일반 비중첩 경로에서 게스트 실행 전에vgic_flush_lr_state()가vgic_v3_populate_lr()를 거쳐 소프트웨어 LR 배열을 채웁니다. 대기 367–451행 · LR 구성 836–892행 · 배열 기록 108–187행 - 게스트 실행 뒤 반영.
kvm_vgic_sync_hwstate()가 사용한 LR 상태를 접어 가상 IRQ의 active/pending 상태에 반영합니다. 게스트 EOI 알림도 조건에 따라 처리합니다. 동기화 914–941행 · LR 해석 36–105행
두 경로의 경계: 물리 gic_eoi_irq()는 가상 IRQ를 주입하거나 LR을 직접 쓰지 않습니다. 게스트에 어떤 IRQ를 주입할지는 별도 장치·KVM 경로가 결정하므로, 왼쪽의 EOI에서 오른쪽의 주입 입구로 자동 연결되는 화살표를 그리지 않았습니다.
1. INTID 확보
irq_data에서 물리 하드웨어 번호를 찾습니다.
화살표는 irqdomain 번호 변환의 결과를 사용한다는 의미입니다.
2. 물리 EOI
ICC_EOIR1_EL1을 쓰고 동기화합니다.
이 화살표를 가상 List Register의 직접 갱신으로 읽지 않습니다.
3. 구현별 마무리
필요한 erratum 경로에서 추가 deactivate를 수행합니다.
조건부 작업이며 모든 GIC 경로가 동일하지 않습니다.
gic_eoi_irq를 한 줄씩 읽기
줄 번호는 v6.18.37 원문 기준입니다. 주석·빈 줄을 포함한 함수 전체를 먼저 보고, 그 아래에서 각 줄을 설명합니다.
static void gic_eoi_irq(struct irq_data *d)
{
write_gicreg(irqd_to_hwirq(d), ICC_EOIR1_EL1);
isb();
if (gic_arm64_erratum_2941627_needed(d)) {
/*
* Make sure the GIC stream deactivate packet
* issued by ICC_EOIR1_EL1 has completed before
* deactivating through GICD_IACTIVER.
*/
dsb(sy);
gic_poke_irq(d, GICD_ICACTIVER);
}
}static void gic_eoi_irq(struct irq_data *d)일반 GIC EOI 경로의 IRQ chip 콜백입니다. 다른 EOImode용 콜백도 있으므로 모든 GIC 종료를 이 한 함수로 일반화하지 않습니다.
write_gicreg(irqd_to_hwirq(d), ICC_EOIR1_EL1);irq_data에서 하드웨어 INTID를 얻어 ICC_EOIR1_EL1에 씁니다. Linux IRQ 번호를 그대로 쓰는 것이 아니라 GIC가 이해하는 번호를 사용합니다.
isb();ISB로 CPU 인터페이스 시스템 레지스터 접근 뒤의 명령 실행을 동기화합니다.
if (gic_arm64_erratum_2941627_needed(d)) {해당 인터럽트 처리에 Arm erratum 2941627 보완이 필요한지 검사합니다. 참인 시스템에서만 추가 경로를 실행합니다.
dsb(sy);EOIR로 발생한 GIC stream deactivate가 필요한 완료 조건을 만족하도록 DSB SY를 수행합니다. 앞의 ISB와 다른 역할입니다.
gic_poke_irq(d, GICD_ICACTIVER);해당 인터럽트의 active 상태를 GICD_ICACTIVER에 쓰는 방식으로 지웁니다. active는 현재 처리 중임을 나타내는 상태이며 IRQ의 enable 비트를 내려 앞으로의 수신을 차단하는 동작과 다릅니다. 앞의 완료 처리만으로 충분하지 않은 하드웨어 erratum 조건에서 추가로 수행합니다.
함께 생각해 볼 질문
게스트 EOI가 항상 같은 함수에 도착합니까?
아닙니다. 가상화 인터페이스와 KVM의 경로를 구분해야 합니다.
LPI도 항상 DIR을 써서 끝냅니까?
아닙니다. LPI와 전달된 인터럽트에는 다른 완료 규칙이 있습니다.
GIC 번호와 Linux IRQ를 혼용하면 무엇이 문제입니까?
잘못된 인터럽트의 상태를 변경하거나 잘못된 handler를 연결할 수 있습니다.
출처와 읽은 범위
Linux stable v6.18.37 · drivers/irqchip/irq-gic-v3.c
추가 비교 근거: v6.18.37 · KVM vgic.c의 주입·LR 동기화 · v6.18.37 · vgic-v3.c의 LR 해석·구성. 이 두 KVM 파일은 기존 719–733행 줄별 풀이의 범위를 넓히지 않고, 위 비교 도식의 근거로만 사용했습니다.
해당 버전 원본 파일 · 기존 코드 분석 · 설명 원고
