Interrupt -1- (Interrupt Controller)

 

아키텍처별 인터럽트 컨트롤러 H/W 구성

  • 아키텍처마다 인터럽트 컨트롤러 구성이 다른데 간략히 아래 그림과 같이 다른 처리 방법을 갖는 것을 이해하자
    • x86 with PIC
      • 초기 CPU를 하나만 사용하는 X86 시스템에서는 8259 PIC(Programmable Interrupt Controller)를 하나 이상 사용하여 구성하였다.
    • x86 with APIC
      • x86에서도 SMP 구성을 하면서 APIC(Advanced Programmble Interrupt Controller)를 두 개의 칩에 나누어 하나는 cpu가 있는 코어 프로세서칩에 사용하고 I/O를 담당하는 south 칩셋에 APIC를 구성하였다.
    • ARM SoC
      • ARM은 무척 구성이 다양하다. SoC를 제작하는 회사마다 소유한 인터럽트 컨트롤러 로직을 SoC의 IP 블럭으로 구성하여 사용하는데 점차적으로 ARM사가 디자인한 GIC(Generic Interrupt Controller)를 사용하게 되는 경향이 있다.
        • GIC v1
          • 1020개 까지 인터럽트 소스 처리 가능
          • ARM Cortex-A5, A9 등에서 사용
        • GIC v2
          • 가상화(virtualization) 기능 추가
          • ARM Cortex-A7, A15, A53, A57 등에서 사용
        • GIC v3
          • 시그널이 아니라 메시지로 처리
          • non-secure와 secure 그룹에 따라 인터럽트 처리를 분리하는 진화된 security 기능 추가
          • ARM Cortex-A53, A57, A72 등에서 사용
        • GICv4
          • 가상 인터럽트의 직접 주입(injection) 기능
          • ARM Cortex-A53, A57, A72 등에서 사용

 

ARM의 다양한 인터럽트 컨트롤러 들

  • ARM社 design
    • gic
      • gic-400
      • arm11mp-gic
      • arm1176jzf-devchip-gic
      • cortex-a15-gic
      • cortex-a9-gic
      • cortex-a7-gic
      • qcom,msm-8660-qgic
      • qcom,msm-qgic2
    • gic-v2m
      • arm,gic-v2m-frame
    • gic-v3
      • arm,gic-v3
      • gic-v3-its
        arm,gic-v3-its
    • nvic
      • arm,armv7m-nvic
    • vic
      • arm,pl190-vic
      • arm,pl192-vic
      • arm,versatile-vic
  • Broadcom社 design
    • bcm2835-ic
      • rpi는 ARM의 GIC를 사용하지 않고 broadcom 인터럽트 컨트롤러를 사용한다.
        • 커널 소스 참고: https://github.com/raspberrypi/linux
        • 2가지 구현
          • architecture specific 인터럽트 핸들러로 구현 (머신 디스크립터 정의)
            • arch/arm/mach-bcm2708/bcm2708.c
          • DTB 기반 irq-domain 인터럽트 핸들러로 구현
            • drivers/irqchip/irq-bcm2835.c
    • bcm2836-ic
      • rpi2 역시 broadcom 사의 인터럽트 컨트롤러를 사용하는데 4개의 armv7 코어를 사용하면서 2835에 비해 더 복잡해졌다.
        • 커널 소스 참고: https://github.com/raspberrypi/linux
        • 2가지 구현 (커널 v4.4 이상)
          • architecture specific 인터럽트 핸들러로 구현 (머신 디스크립터 정의)
            • arch/arm/mach-bcm2709/bcm2709.c
          • DTB 기반 per-cpu irq-domain 인터럽트 핸들러로 구현
            • drivers/irqchip/irq-bcm2836.c
  • 그 외 제조사 custom 디자인 IP 블럭
    • exynos-combiner
    • armada-mpic
    • atmel-aic
    • hip04
    • keystone
    • omap-intc
    • xtensa-pic
    • (수십 종류라 생략…)

 

 

1) GIC(Generic Interrupt Controller)

GIC 블럭다이아그램

  • GIC는 CPU Interface 레지스터들과 Distributor 레지스트들을 통해 제어한다.
  • CPU Interface 레지스터
    • core로 전달된 irq들 전체를 한꺼번에 통제한다.
    • core로 전달될 irq들에 대해 설정한 priority mask 값을 사용하여 통과시킨다.
      • priority 레벨링 (16 ~ 256 단계)
  • Distributor 레지스터
    • 진입된 인터럽트의 종류는 다음과 같이 구분된다.
      • PPIs(Private Peripherals Interrupts)
        • 각 core에 전용으로 사용될 수 있는 IRQ 들로 0 ~ 31 까지의 id를 사용한다.
      • SPIs(Shared Peripherals Interrupts)
        • core에 공용으로 사용될 수 있는 IRQ 들로 32 ~ 1020까지의 id를 사용한다.
      • SGIs(Software Generated Interrupts)
        • 각 core에 전용으로 사용되며, 외부 인터럽트가 아니라 소프트웨어에서 발생시킬 수 있는 내부 IRQ 들로 0 ~ 15 까지의 id를 사용한다.
    • secure 상태에 따라 group 0/1의 방향을 선택하게 한다. (irq/fiq)
      • non-secure extension 사용시 group은 항상 fiq로 forward된다.
      • secure extension 사용시 group-0은 fiq, group-1은 irq로 forward 된다.
    • Pending 인터럽트를 forward할 지 설정할 수 있다.
    • IRQ 별로 forward를 설정(Set-enable) 및 클리어(Set-Clear) 요청할 수 있다.
    • IRQ 별로 priority를 설정할 수 있다.
    • IRQ 별로 개별 cpu interface로의 전달여부를 비트마스크로 설정할 수 있다. (1=forward, 0=drop)
    • 하드웨어 IRQ 별로 인터럽트 트리거 타입을 설정할 수 있다.
      • 0=level sensitive (전압의 레벨이 지속되는 동안)
      • 1=edge trigger (high나 low로 바뀌는 순간만)
        • SGI는 edge 트리거를 사용한다.

GICv1 레지스터들 (GIC-390)

CPU Interface Registers

 

  • GICC_CTRL (CPU Interface Control Register)
    • Enable=1로 설정하여 인터럽트를 forward 한다.
    • secure mode 별로 레지스터가 bank 되어 사용된다.
  • GICC_PMR (Interrupt Priority Mask Register)
    • core로 전달될 irq들에 대해 설정한 priority 마스크와 and 연산하여 forward한다.
    • priority 레벨링 (16 ~ 256 단계)
      • 0xff: 256 단계
      • 0xfe: 128 단계
      • 0xfc: 64 단계
      • 0xf8: 32단계
      • 0xf0: 16 단계
  • GICC_BPR (Binary Point Register)
    • priority 값을 group/sub와 같이 두 그룹으로 나누어 그 중 group에 해당하는 priority를 가진 인터럽트에 대해 preemption interrupt로 분류한다.
  • GICC_IAR  (Interrupt Acknowledge Register)
    • 인터럽트 수신 시 이 레지스터를 읽어 인터럽트 id를 읽어오는 것으로 인터럽트 처리 루틴이 ack 처리되었음을 gic에 알린다.
  • GICC_EOIR  (End of Interrupt Register)
    • ISR(Interrupt Service Routine)에서 인터럽트 처리 완료 시 해당 인터럽트 id를 기록하여 eoi 처리하였음을 gic에 알린다.
  • GICC_RPR (Running Priority Register)
    • 읽기 전용으로 현재 동작하고 있는 인터럽트의 priority 값을 알아온다. idle 상태인 경우는 0xff
    • non-secure에서 읽은 경우 0x80을 mask 하여사용한다.
  • GICC_HPIR (Highest Pending Interrupt Register)
    • 읽기 전용으로 현재 하드웨어 인터럽트 (PPI&SPI)들 중 pending되고 있는 가장 높은 priority irq 번호와 cpu를 읽어온다.
    • 소프트 인터럽트(SGI)의 경우 cpu 값만 읽어올 수 있다.
  • GICC_IIDR (CPU Interface Identification Register)
    • 읽기 전용으로 GIC 제품 ID, 아키텍처 버전, 리비전, 구현회사 등의 정보를 읽어올 수 있다.

 

Distributor Registers

  • GICD_CTRL (Distributor Control Register)
    • Pending 인터럽트에 대해 CPU interface로 올려보낼지 여부를 통제한다.
    • secure extension을 사용할 때 non-secure 모드에서는 group1에 대해서만 통제할 수 있다.
      • 1=forward enable
    • security extension 사용 시 bank 된다.
  • GICD_TYPER (Interrupt Controller Type Register)
    • 읽기 전용으로 Security Extension을 사용 시 최대 지원 cpu 수와 인터럽트 수를 알아낸기 위해 사용한다.
      • Lockable SPI
        • 최대 지원 lockable SPI 수
      • SecurityExtn (bit:10)
        • 1=security extension 사용
        • 0=security extension 사용하지 않음
      • CPU Number
        • 최대 지원 CPU 수
      • ITLinesNumber
        • 최대 지원 인터럽트 수
  • GICD_IIDR (Distributor Implementer Identification Register)
    • 읽기 전용으로 GIC implementor 정보를 알아온다.
  • GICD_IGROUPR (Interrupt Group Registers)
    • secure extension을 사용하는 경우 인터럽트별로 group 0와 group 1을 지정한다.
      • 0=group 0, 1=group 1
    • IRQ #0~31을 위해 첫 레지스트가 cpu별로 bank 되어 사용된다.
  • GICD_ISER (Interrupt Set Enable Registers)
    • IRQ 별로 통과(Set-Enable) 여부를 설정할 수 있다.
      • 1=set 요청
    • IRQ #0~31을 위해 첫 레지스트가 cpu별로 bank 되어 사용된다.
  • GICD_ICER (Interrupt Clear Enable Registers)
    • IRQ 별로 통제(Clear-Enable) 여부를 설정할 수 있다.
      • 1=clear 요청
    • IRQ #0~31을 위해 첫 레지스트가 cpu별로 bank 되어 사용된다.
  • GICD_ISPENDR (Interrupt Set PENDing Registers)
    • IRQ 별로 pending 상태를 설정할 수 있다.
      • 1=set 요청
    • IRQ #0~31을 위해 첫 레지스트가 cpu별로 bank 되어 사용된다.
  • GICD_ICPENDR (Interrupt Clear PENDing Registers)
    • IRQ 별로 pending 상태 해제를 요청할 수 있다.
      • 1=clear 요청
    • IRQ #0~31을 위해 첫 레지스트가 cpu별로 bank 되어 사용된다.
  • GICD_IPRIORITYR (Interrupt PRIORITY Registers)
    • IRQ 별로 priority를 설정할 수 있다.
      • 0~255 priority 설정
    • IRQ #0~31을 위해 첫 8개의 레지스트가 cpu별로 bank 되어 사용된다.
  • GICD_ITARGETR (Interrupt processor TARGET Registers)
    • IRQ 별로 개별 cpu interface로의 전달여부를 비트로 마스크 설정할 수 있다.
    • bit0=cpu#0 제어, bit1=cpu#1 제어…
      • 0=disable forward, 1=enable forward
    • IRQ #0~31을 위해 첫 8개의 레지스트가 cpu별로 bank 되어 사용된다.
  • GICD_ICFGR (Interrupt ConFiGuration Registers)
    • IRQ 별로 인터럽트 트리거 방향을 설정할 수 있다.
      • 0=상향 시 트리거, 1=하향 시 트리거
    • IRQ #160~31을 위해 두 번째 레지스트가 cpu별로 bank 되어 사용된다.
  • GICD_SGIR (Software Generated Interrupt Register)
    • TLF (Target List Filter)
      • 0=white list 제어 방식, CPU Target List에 설정된 cpu로만 forward
      • 1=black list 제어 방식, CPU Target List에 설정된 cpu만 drop
      • 2=위의 ACL 방식 제어를 사용하지 않는다.
      • 3=reserved
    • CPU Target List
      • 0~7개의 cpu bit
    • NSATT (Non-Secure
      • 0=SGI#에 대해 group-0으로 설정된 경우 CPU Target List로 forward
      • 1=SGI#에 대해 group-1로 설정된 경우 CPU Target List로 forward

 

GIC 인터럽트 상태

  • Inactive
    • 인터럽트가 발생하지 않은 상태
  • Pending
    • 하드웨어 또는 소프트웨어에서 인터럽트가 발생하였으나 타깃 프로세스에게 전달되지 않음
  • Active
    • 인터럽트가 발생하여 프로세스에게 전달되었고 처리 중이며 완료되지 않은 상태
  • Active & Pending
    • 인터럽트가 발생하여 프로세스에게 전달되었고, 동일한 인터럽트가 발생하여 보류중임

인터럽트 트리거

  • Level Sensitive
  • Edge Trigger

 

Prioritization

Preemption Interrupt

  • Binary Point
    • 3개의 비트를 사용한 0~7의 값으로 각 하드웨어 인터럽트에 설정된 priority 값을 두 그룹으로 분리한다.
    • 분리한 두 개의 그룹
      • Group Priority
        • fast interrupt 처리가 가능하도록 현재 처리하고 있는 인터럽트가 있다하더라도 더 높은 우선 순위의 인터럽트 발생 시 이를 먼저 처리하도록 한다.
      • Sub Priority
        • 현재 처리하고 있는 인터럽트의 우선 순위보다 더 높은 우선 순위의 인터럽트 발생 시 먼저 처리하지 않는다.

 

Priority Leveling

  • Priority Mask
    • 8개의 비트를 사용한다.
    • priority 값과 Priority Mask 값을 and 연산을 취한 값을 priority 값으로 사용하는 것으로 우선순위를 레벨링한다.
    • 최하 16 단계부터 256단계 까지 사용한다.

 

2) BCM2708(RPI) 인터럽트 컨트롤러

BCM2708 인터럽트 컨트롤러

arm irq에 해당하는 박스에 색상이 있는 항목들은 실제 ARM 커널 드라이버에서 처리된다.

 

인터럽트 소스 구분

RPI에서 처리하는 인터럽트 소스는 다음과 같다.

  • Pending IRQ1:
    • GPU peripherals 인터럽트
    • irqnr = #0~31
      • 7, 9, 10, 18, 19번은 ARM과 share
  • Pending IRQ2:
    • GPU peripherals 인터럽트
    • irqnr = #32~63
      • 53~57, 62번은 ARM과 share
  • Pending Base IRQ0:
    • ARM peripherals 인터럽트
    • irqnr = #64~95
      • 64~71번은 timer, doorbell #0~1, mailbox, …
      • 72-73번은 pending #1-#2 레지스터 소스
      • 74~85번은 VideoCore와 share

 

 

관련 레지스터

  • 0x7E00_0000으로 시작하는 주소는 GPU(VC)에 연결된 I/O peripherals 기본 물리 주소이다. 따라서 ARM 리눅스에서 사용하는 물리주소와 가상주소로 변환하여 사용한다.
    • rpi (ARM 기본 주소):
      • GPU 물리 주소: 0x7e00_0000 (DTB에 구성된 주소로 ARM 관점에서 BUS 주소로 본다.)
      • ARM 물리 주소: 0x2000_0000
      • ARM 가상 주소: 0xf200_0000
    • rpi2 (ARM 기본 주소):
      • GPU 물리 주소: 0x7e00_0000 (DTB에 구성된 주소로 ARM 관점에서 BUS 주소로 본다.)
      • ARM 물리 주소: 0x3f00_0000
      • ARM 가상 주소: 0xf300_0000

 

3) BCM2709(RPI2) 인터럽트 컨트롤러

BCM2709 인터럽트 컨트롤러

arm irq에 해당하는 박스에 색상이 있는 항목들은 실제 ARM 커널 드라이버에서 처리된다.

인터럽트 소스 구분

RPI2에서 처리하는 인터럽트 소스는 다음과 같다. Machine Specific 함수에서 초기화한 경우와 Device Tree로 초기화할 때의 구성이 다르다.

  • HARD IRQs
    • GPU Pending IRQ1:
      • GPU peripherals 인터럽트
      • Machine Specific irqnr = #0~31
        • 7, 9, 10, 18, 19번은 ARM과 share
      • Device Tree virq=30~61, hwirq=32~63
    • GPU Pending IRQ2:
      • GPU peripherals 인터럽트
      • Machine Specific irqnr = #32~63
        • 53~57, 62번은 ARM과 share
      • Device Tree virq=62~93, hwirq=64~95
    • ARM Pending Base IRQ0:
      • ARM peripherals 인터럽트
      • irqnr = #64~95
        • 64~71번은 timer, doorbell #0~1, mailbox, …
        • 72-73번은 pending #1-#2 레지스터 소스
        • 74~85번은 VideoCore와 share
      • Device Tree virq=22~29, hwirq=0~7
    • LOCAL:
      • 인터럽트 소스로 해당 비트가 설정되는 경우 각각의 레지스터를 통해 해당 IRQ를 얻어낸다.
      • irqnr = #96~127
        • 100~103번은 mailbox0~3 interrupt controller 레지스터 소스
        • 104 번은 pending #0 레지스터 소스
        • 105번은 PMU 레지스터 소스
      • Device Tree virq=16~21, hwirq=0~9
  • Soft IRQs:
    • IPI (mailbox #0)
      • ipinr = #0~31
        • 8~31번은 리눅스에서 사용하지 않는다.
    • mailbox #1~3, doorbell, timer, …

 

BCM2709 인터럽트 컨트롤러 레지스터 (Machine Specific)

관련 레지스터

BCM2708의 10개의 (IRQ basic pending ~ ) 기본 레지스터들과 동일하고 BCM2709는 ARM 전용으로 다음과 같이 추가되었다.

이 레지스터들은 GPU(VC)에서 사용하지 않고 ARM 전용으로 사용된다.

  • rpi2 (ARM LOCAL 기본 주소):
    • ARM 물리 주소: 0x4000_0000
    • ARM 가상 주소: 0xf400_0000

RPI2 인터럽트 확인 (Machine-Specific)

rpi2를 machine specific 코드 기반으로 초기화된 인터럽트 정보이다.

  • 보여주는 정보 순서
    • irq 번호
    • cpu별 인터럽트 통계
    • irq_chip.name
    • irq_domain.hwirq
      • irq_domain이 설정되지 않아 출력되지 않음
    • 트리거 레벨
      • CONFIG_GENERIC_IRQ_SHOW_LEVEL이 설정되지 않아 출력되지 않음
    • irq name
      • 이름이 설정되지 않아 아무것도 출력되지 않음
    • action list
      • 1개 이상은 컴마로 분리됨
$ cat /proc/interrupts
           CPU0       CPU1       CPU2       CPU3
 16:          0          0          0          0   ARMCTRL  bcm2708_fb dma
 24:      12845          0          0          0   ARMCTRL  DMA IRQ
 25:       2980          0          0          0   ARMCTRL  DMA IRQ
 32:  128848277          0          0          0   ARMCTRL  dwc_otg, dwc_otg_pcd, dwc_otg_hcd:usb1
 52:          0          0          0          0   ARMCTRL  BCM2708 GPIO catchall handler
 65:         11          0          0          0   ARMCTRL  bcm2708_vcio
 66:          2          0          0          0   ARMCTRL  VCHIQ doorbell
 75:          1          0          0          0   ARMCTRL
 83:          2          0          0          0   ARMCTRL  uart-pl011
 84:     497931          0          0          0   ARMCTRL  mmc0
 99:    4675934    2099819     568663      90331   ARMCTRL  arch_timer
FIQ:              usb_fiq
IPI0:          0          0          0          0  CPU wakeup interrupts
IPI1:          0          0          0          0  Timer broadcast interrupts
IPI2:     137529      40597      36229      25588  Rescheduling interrupts
IPI3:         14         17         11         15  Function call interrupts
IPI4:          1          5          1          3  Single function call interrupts
IPI5:          0          0          0          0  CPU stop interrupts
IPI6:          0          0          0          0  IRQ work interrupts
IPI7:          0          0          0          0  completion interrupts
Err:

 

RPI2 인터럽트 확인 (Device Tree)

Device Tree로 구성한 인터럽트 정보이다..

  • 보여주는 정보 순서
    • irq 번호
    • cpu별 인터럽트 통계
    • irq_chip.name
    • irq_domain.hwirq
    • 트리거 레벨
    • irq name
      • 이름이 설정되지 않아 아무것도 출력되지 않음
    • action list
      • 1개 이상은 컴마로 분리됨
$ cat /proc/interrupts
           CPU0       CPU1       CPU2       CPU3
 16:          0          0          0          0  bcm2836-timer   0 Edge      arch_timer
 17:   37228140   22280702  154598435   50544784  bcm2836-timer   1 Edge      arch_timer
 23:      24375          0          0          0  ARMCTRL-level   1 Edge      3f00b880.mailbox
 24:        216          0          0          0  ARMCTRL-level   2 Edge      VCHIQ doorbell
 39:          1          0          0          0  ARMCTRL-level  41 Edge
 46:          0          0          0          0  ARMCTRL-level  48 Edge      bcm2708_fb dma
 48:     545428          0          0          0  ARMCTRL-level  50 Edge      DMA IRQ
 50:          0          0          0          0  ARMCTRL-level  52 Edge      DMA IRQ
 62:  925102072          0          0          0  ARMCTRL-level  64 Edge      dwc_otg, dwc_otg_pcd, dwc_otg_hcd:usb1
 79:          0          0          0          0  ARMCTRL-level  81 Edge      3f200000.gpio:bank0
 80:          0          0          0          0  ARMCTRL-level  82 Edge      3f200000.gpio:bank1
 86:     540806          0          0          0  ARMCTRL-level  88 Edge      mmc0
 87:       5053          0          0          0  ARMCTRL-level  89 Edge      uart-pl011
 92:    9308589          0          0          0  ARMCTRL-level  94 Edge      mmc1
FIQ:              usb_fiq
IPI0:          0          0          0          0  CPU wakeup interrupts
IPI1:          0          0          0          0  Timer broadcast interrupts
IPI2:    1160150    6582642    1541946    1893722  Rescheduling interrupts
IPI3:          3          5          8          8  Function call interrupts
IPI4:        114         91         79         97  Single function call interrupts
IPI5:          0          0          0          0  CPU stop interrupts
IPI6:          0          0          0          0  IRQ work interrupts
IPI7:          0          0          0          0  completion interrupts
Err:          0

 

참고

답글 남기기

이메일은 공개되지 않습니다. 필수 입력창은 * 로 표시되어 있습니다.