요약·해설과 원문, 전문 번역을 서로 분리했습니다. API 이름, symbol, source path는 원문 표기를 사용합니다.
1. 요약·해설
원문의 핵심 논리와 kernel programming 관점의 보충 설명입니다. 아래의 전문 번역과는 별도로 작성했습니다.
2. 영어 원문 전체
번역 기준이 된 Linux v6.18.37 원문입니다. 줄 번호는 이 버전의 파일 좌표입니다.
원문 전체 펼치기
.. SPDX-License-Identifier: GPL-2.0
=======
IO-APIC
=======
:Author: Ingo Molnar <[email protected]>
Most (all) Intel-MP compliant SMP boards have the so-called 'IO-APIC',
which is an enhanced interrupt controller. It enables us to route
hardware interrupts to multiple CPUs, or to CPU groups. Without an
IO-APIC, interrupts from hardware will be delivered only to the
CPU which boots the operating system (usually CPU#0).
Linux supports all variants of compliant SMP boards, including ones with
multiple IO-APICs. Multiple IO-APICs are used in high-end servers to
distribute IRQ load further.
There are (a few) known breakages in certain older boards, such bugs are
usually worked around by the kernel. If your MP-compliant SMP board does
not boot Linux, then consult the linux-smp mailing list archives first.
If your box boots fine with enabled IO-APIC IRQs, then your
/proc/interrupts will look like this one::
hell:~> cat /proc/interrupts
CPU0
0: 1360293 IO-APIC-edge timer
1: 4 IO-APIC-edge keyboard
2: 0 XT-PIC cascade
13: 1 XT-PIC fpu
14: 1448 IO-APIC-edge ide0
16: 28232 IO-APIC-level Intel EtherExpress Pro 10/100 Ethernet
17: 51304 IO-APIC-level eth0
NMI: 0
ERR: 0
hell:~>
Some interrupts are still listed as 'XT PIC', but this is not a problem;
none of those IRQ sources is performance-critical.
In the unlikely case that your board does not create a working mp-table,
you can use the pirq= boot parameter to 'hand-construct' IRQ entries. This
is non-trivial though and cannot be automated. One sample /etc/lilo.conf
entry::
append="pirq=15,11,10"
The actual numbers depend on your system, on your PCI cards and on their
PCI slot position. Usually PCI slots are 'daisy chained' before they are
connected to the PCI chipset IRQ routing facility (the incoming PIRQ1-4
lines)::
,-. ,-. ,-. ,-. ,-.
PIRQ4 ----| |-. ,-| |-. ,-| |-. ,-| |--------| |
|S| \ / |S| \ / |S| \ / |S| |S|
PIRQ3 ----|l|-. `/---|l|-. `/---|l|-. `/---|l|--------|l|
|o| \/ |o| \/ |o| \/ |o| |o|
PIRQ2 ----|t|-./`----|t|-./`----|t|-./`----|t|--------|t|
|1| /\ |2| /\ |3| /\ |4| |5|
PIRQ1 ----| |- `----| |- `----| |- `----| |--------| |
`-' `-' `-' `-' `-'
Every PCI card emits a PCI IRQ, which can be INTA, INTB, INTC or INTD::
,-.
INTD--| |
|S|
INTC--|l|
|o|
INTB--|t|
|x|
INTA--| |
`-'
These INTA-D PCI IRQs are always 'local to the card', their real meaning
depends on which slot they are in. If you look at the daisy chaining diagram,
a card in slot4, issuing INTA IRQ, it will end up as a signal on PIRQ4 of
the PCI chipset. Most cards issue INTA, this creates optimal distribution
between the PIRQ lines. (distributing IRQ sources properly is not a
necessity, PCI IRQs can be shared at will, but it's a good for performance
to have non shared interrupts). Slot5 should be used for videocards, they
do not use interrupts normally, thus they are not daisy chained either.
so if you have your SCSI card (IRQ11) in Slot1, Tulip card (IRQ9) in
Slot2, then you'll have to specify this pirq= line::
append="pirq=11,9"
the following script tries to figure out such a default pirq= line from
your PCI configuration::
echo -n pirq=; echo `scanpci | grep T_L | cut -c56-` | sed 's/ /,/g'
note that this script won't work if you have skipped a few slots or if your
board does not do default daisy-chaining. (or the IO-APIC has the PIRQ pins
connected in some strange way). E.g. if in the above case you have your SCSI
card (IRQ11) in Slot3, and have Slot1 empty::
append="pirq=0,9,11"
[value '0' is a generic 'placeholder', reserved for empty (or non-IRQ emitting)
slots.]
Generally, it's always possible to find out the correct pirq= settings, just
permute all IRQ numbers properly ... it will take some time though. An
'incorrect' pirq line will cause the booting process to hang, or a device
won't function properly (e.g. if it's inserted as a module).
If you have 2 PCI buses, then you can use up to 8 pirq values, although such
boards tend to have a good configuration.
Be prepared that it might happen that you need some strange pirq line::
append="pirq=0,0,0,0,0,0,9,11"
Use smart trial-and-error techniques to find out the correct pirq line ...
Good luck and mail to [email protected] or
[email protected] if you have any problems that are not covered
by this document.
3. 한국어 전문 번역
영어 원문의 문단 순서와 의미를 유지한 전체 번역입니다. 코드, 함수명, symbol과 URL은 원문 표기를 유지합니다.
IO-APIC의 SMP interrupt routing
1-22이 `GPL-2.0` 문서의 저자는 Ingo Molnar `<[email protected]>`입니다. Intel MP-compliant SMP board 대부분 또는 전부에는 enhanced interrupt controller인 IO-APIC이 있습니다.
IO-APIC은 hardware interrupt를 여러 CPU 또는 CPU group으로 route합니다. IO-APIC이 없으면 hardware interrupt는 operating system을 boot한 CPU, 보통 `CPU#0`에만 전달됩니다.
Linux는 여러 IO-APIC을 가진 board를 포함해 compliant SMP board의 모든 variant를 지원합니다. high-end server는 IRQ load를 더 넓게 분산하기 위해 multiple IO-APIC을 사용합니다.
일부 오래된 board에는 알려진 결함이 있지만 보통 kernel workaround가 있습니다. MP-compliant SMP board가 Linux를 boot하지 못하면 먼저 `linux-smp` mailing-list archive를 확인합니다.
/proc/interrupts 확인
23-41IO-APIC IRQ를 enable한 상태로 정상 boot하면 `/proc/interrupts`에 `IO-APIC-edge`와 `IO-APIC-level` source가 다음처럼 나타납니다.
hell:~> cat /proc/interrupts
CPU0
0: 1360293 IO-APIC-edge timer
1: 4 IO-APIC-edge keyboard
2: 0 XT-PIC cascade
13: 1 XT-PIC fpu
14: 1448 IO-APIC-edge ide0
16: 28232 IO-APIC-level Intel EtherExpress Pro 10/100 Ethernet
17: 51304 IO-APIC-level eth0
NMI: 0
ERR: 0
hell:~>
일부 interrupt가 여전히 `XT-PIC`으로 표시돼도 문제는 아닙니다. 이 IRQ source들은 performance-critical하지 않습니다.
broken MP table과 PCI slot swizzling
42-64board가 동작하는 MP table을 만들지 않는 드문 경우 `pirq=` boot parameter로 IRQ entry를 수동 구성할 수 있습니다. 자동화할 수 없는 까다로운 작업이며 `/etc/lilo.conf` entry 예시는 다음과 같습니다.
append="pirq=15,11,10"
실제 number는 system, PCI card, PCI slot 위치에 따라 달라집니다. PCI slot은 chipset의 IRQ-routing facility로 들어가는 `PIRQ1-4` line에 연결되기 전에 보통 daisy-chain, 즉 PCI interrupt swizzling됩니다.
원문의 slot 1-4 daisy-chain ASCII 도식을 표준 PCI swizzle mapping으로 구조화했습니다. slot 4의 INTA가 PIRQ4가 된다는 원문 예와 일치합니다.
card-local INTA-D와 PIRQ 의미
65-85각 PCI card는 `INTA`, `INTB`, `INTC`, `INTD` 중 하나인 PCI IRQ를 발생시킵니다.
원문의 세로 slot ASCII 그림을 card connector의 네 local IRQ pin으로 구조화했습니다.
`INTA-D`는 항상 card-local name이므로 실제 의미는 card가 어느 slot에 있는지에 따라 달라집니다. 예를 들어 slot 4의 card가 `INTA`를 내면 PCI chipset의 `PIRQ4` signal이 됩니다.
대부분 card는 `INTA`를 사용하므로 PIRQ line 사이에 최적으로 분산됩니다. PCI IRQ는 자유롭게 share할 수 있어 균등 분산이 필수는 아니지만 non-shared interrupt가 performance에는 좋습니다. slot 5는 보통 interrupt를 사용하지 않는 video card용이며 daisy chain에도 넣지 않습니다.
pirq= 계산과 trial-and-error
86-123SCSI card `IRQ11`이 slot 1, Tulip card `IRQ9`가 slot 2에 있으면 다음 line을 지정합니다.
append="pirq=11,9"
다음 script는 PCI configuration에서 default `pirq=` line을 추정합니다.
echo -n pirq=; echo `scanpci | grep T_L | cut -c56-` | sed 's/ /,/g'
slot을 건너뛰었거나 board가 default daisy-chain을 사용하지 않거나 IO-APIC의 PIRQ pin wiring이 특이하면 script는 동작하지 않습니다. 앞 예에서 slot 1은 비어 있고 SCSI `IRQ11` card가 slot 3에 있으면 다음처럼 empty slot을 표시합니다.
append="pirq=0,9,11"
`0`은 empty slot 또는 IRQ를 내지 않는 slot을 위한 generic placeholder로 reserved되어 있습니다.
올바른 `pirq=` 설정은 IRQ number를 적절히 permute해 항상 찾을 수 있지만 시간이 걸립니다. 잘못된 line은 boot hang이나 module로 삽입한 device의 malfunction을 일으킵니다. PCI bus가 둘이면 최대 8개 PIRQ value를 사용할 수 있지만 이런 board는 대체로 configuration이 양호합니다.
아주 특이한 line이 필요할 수도 있습니다.
append="pirq=0,0,0,0,0,0,9,11"
smart trial-and-error로 올바른 line을 찾습니다. 문서에 없는 문제는 `[email protected]` 또는 `[email protected]`로 문의합니다.
요약과 해설
IO-APIC.rst:1-123IO-APIC은 hardware IRQ를 여러 CPU로 route해 SMP interrupt load를 분산합니다. 오래된 board가 MP table을 만들지 못하면 `pirq=`로 PCI slot의 swizzled `INTA-D`와 chipset `PIRQ1-4` mapping을 수동 지정할 수 있습니다.
수동 설정은 board wiring과 slot 배치를 알아야 하며 잘못된 값은 boot hang이나 device failure를 일으킵니다. `/proc/interrupts`, PCI enumeration, placeholder `0`, 신중한 trial-and-error로 검증합니다.