PIC 컨트롤러란
PIC 컨트롤러는 프로세서와 디바이스 사이에서 인터럽트를 중계하는 역할이며, FS64 OS에서는 대부분의 디바이스를 인터럽트로 제어하므로 아주 중요합니다.
PIC 컨트롤러는 Programmable Interrupt Controller의 약자로 인터럽트 처리에 관련된 세부 기능을 프로그래밍할 수 있는 컨트롤러입니다.
PIC 컨트롤러는 옛날부터 PC 디바이스(키보드, 마우스, 하드디스크 등)의 인터럽트를 관리해왔으며, 지금도 여전히 사용됩니다.
PIC 컨트롤러는 1개당 인터럽트 입력 8개를 처리할 수 있고, PC는 PIC 컨트롤러 2개를 마스터-슬레이브(Master-Slave) 방식으로 연결하여 최대 15개의 인터럽트를 처리할 수 있습니다.
처리할 수 있는 인터럽트 수가 16개가 아닌 15개인 이유는 마스터 PIC 컨트롤러의 2번 핀을 슬레이브 PIC 컨트롤러와 연결하는 데 사용하기 때문입니다.
마스터 PIC 컨트롤러와 슬레이브 PIC 컨트롤러의 순으로 부여한 인터럽트 핀 번호를 IRQ(Interrupt Request) 번호라고 부르며, IRQ 0부터 IRQ 15까지 16개가 할당되어 있습니다.
16개의 IRQ는 PC 디바이스의 인터럽트 핀과 각자 연결되어 있으며, 핀에 연결된 디바이스는 아래의 그림과 같습니다.
참고)
현재 APIC(Advanced Programmable Interrupt Controller)와 IO APIC(Input/Output APIC) 컨트롤러가 개발되어 더 많은 인터럽트를 제어합니다.
하지만 더 효율적인 컨트롤러가 개발되었어도, 하위 호환성을 위해 PIC 컨트롤러를 완전히 배제할 수 없었기 때문에 PIC 컨트롤러를 완전히 대체하는 것은 아닙니다.
PIC 컨트롤러는 APIC나 I/O APIC보다 성능은 떨어지지만 제어하기가 쉬우므로 싱글 코어(Single Core) OS를 제작할 계획이라면 PIC 컨트롤러를 사용하는 것도 괜찮습니다.
FS64 OS 역시 멀티코어로 전환하기까지 PIC 컨트롤러로 인터럽트를 처리합니다.
→ PIC 컨트롤러의 구조와 동작 방식
PIC 컨트롤러는 내부에 8bit 크기의 IRR, ISR, IMR 레지스터가 있습니다.
레지스터의 각 bit는 PIC 컨트롤러에 연결된 8개의 인터럽트 핀에 대한 정보를 나타내며, 각 레지스터의 역할은 다음과 같습니다.
IRR(Interrupt Request Register) : 외부 디바이스와 연결된 인터럽트 핀 중에서 인터럽트가 발생한 핀의 정보를 관리합니다.
외부 디바이스가 인터럽트를 발생시키면 PIC 컨트롤러는 IRR 레지스터에 해당 bit를 1로 설정하여 인터럽트 발생 여부를 저장합니다.
ISR(In-Service Register) : 현재 인터럽트 핸들러가 실행 중인 인터럽트의 정보를 나타냅니다.
PIC 컨트롤러는 특별한 옵션을 사용하지 않는 한 IRQ 0에 가까울수록 우선순위를 높게 설정하므로 ISR 레지스터에 설정된 bit는 IRR 레지스터에 설정된 bit 중에서 bit 0에 가까운 비트와 같습니다.
IMR(Interrupt Mask Register) : 비트가 1로 설정된 인터럽트 핀에서 발생한 인터럽트 요청을 무시하는 역할을 합니다.
특정 디바이스의 인터럽트 신호를 무시하고 싶다면, IMR 레지스터의 해당 비트를 1로 설정하면 됩니다.
PIC 컨트롤러와 프로세서는 INT 핀과 /INTA 핀으로 연결되어 있으며, 인터럽트 발생 여부와 처리 여부를 서로 알려줍니다.
PIC 컨트롤러의 INT 핀은 프로세서의 INTR 핀과 직접 연결되어 있으며, 인터럽트가 발생했을 때 INT 핀에 신호를 발생시켜 프로세서가 인터럽트를 처리하게 합니다.
/INTA 핀은 인터럽트가 프로세서에 잘 전달되었음을 PIC 컨트롤러에 알려주는 핀입니다.
이처럼 프로세서와 PIC 컨트롤러는 INT와 /INTA 핀으로 서로에게 신호를 보내 인터럽트를 처리합니다. (위의 그림 참고)
아래는 INT 핀, /INTA 핀, 데이터 핀으로 프로세서와 PIC 컨트롤러가 인터럽트를 처리하는 과정입니다.
1. PIC 컨트롤러에 인터럽트 요청이 수신되고, PIC 컨트롤러는 IRR 레지스터의 해당 비트를 1로 설정
2. PIC 컨트롤러는 INT 핀으로 신호를 송신하여 프로세서에 인터럽트가 발생했음을 알림
3. 프로세서는 /INTA 핀으로 신호를 송신하여 인터럽트 요청이 정상적으로 수신되었음을 PIC 컨트롤러에 알림
4. PIC 컨트롤러는 IRR 레지스터에서 가장 우선순위가 높은 것을 찾아 삭제한 뒤 ISR 레지스터의 해당 bit에 1로 설정한 후 인터럽트 벡터의 번호를 프로세서에 전송
5. 프로세서는 인터럽트 처리 완료 후 EOI 커맨드를 PIC 컨트롤러에 전송하고, PIC 컨트롤러는 ISR 레지스터에 설정된 비트를 삭제
6. 인터럽트 완료 후 IRR 레지스터를 확인하여 처리되지 않은 인터럽트 요청이 있다면 2~5의 과정을 반복
메인 프로세서에 비하면 PIC 컨트롤러는 동작 방식이 단순하므로 이해하는데 큰 어려움이 없습니다.
PIC 컨트롤러 제어
이번에는 PIC 컨트롤러를 초기화하여 IRQ 0 ~ IRQ 15를 인터럽트 벡터(IDT 테이블의 인덱스) 32번 ~ 47번에 매핑하는 방법과 PIC 컨트롤러에 커맨드를 전송하거나 레지스터를 읽어 PIC 컨트롤러를 제어하는 방법을 알아봅니다.
PIC 컨트롤러는 전달 방식뿐만 아니라 인터럽트 벡터를 설정하는 기능과 인터럽트를 선택하는 기능을 제공하기 때문에 상황에 따라 인터럽트 처리 방식을 변경할 수 있습니다.
→ PIC 컨트롤러 초기화
PIC 컨트롤러는 키보드 컨트롤러와 마찬가지로 I/O 포트 방식으로 연결되어 있습니다.
사용하는 PC는 PIC 컨트롤러에 각각 두 개의 I/O 포트를 할당하며, 마스터 PIC 컨트롤러는 0x20과 0x21을 사용하고 슬레이브 PIC 컨트롤러는 0xA0와 0xA1를 사용합니다.
PIC 컨트롤러에 할당된 I/O 포트는 읽기와 쓰기가 모두 가능하고 이때 각 포트의 역할은 아래와 같습니다.
참고)
이번에는 PIC 컨트롤러를 제어하여 인터럽트를 처리하는 것이 목적이므로 PIC 컨트롤러의 제한적인 기능만 사용합니다.
다양한 기능을 알아보고자 하자면 8259A 컨트롤러 스펙에 대해 알아보시기 바랍니다.
PIC 컨트롤러는 크게 두 가지 타입의 커맨드를 제공하며, 초기화와 관련된 ICW(Initialization Command Word) 커맨드와 제어에 관련된 OCW(Operation Command Word) 커맨드가 있습니다.
ICW 커맨드에는 ICW1부터 ICW4까지 4가지가 있고, 각 커맨드의 필드는 아래와 같습니다.
PIC 컨트롤러를 초기화하는 작업은 ICW1 커맨드를 I/O 포트 0x20 또는 0xA0에 쓰는 것으로 시작하는데, 0x20나 0xA0 포트로 ICW1을 보내면 0x21나 0xA1 포트에 쓰는 데이터는 ICW2, ICW3, ICW4 순서대로 해석되고, 전송이 완료되면 PIC 컨트롤러는 수신된 데이터를 바탕으로 자신을 초기화합니다.
PIC 컨트롤러의 초기화 작업은 마스터 및 슬레이브 PIC 컨트롤러에 개별적으로 수행해야 합니다.
초기화에 사용하는 값은 마스터 PIC 컨트롤러와 슬레이브 PIC 컨트롤러가 거의 같으므로 공통적인 부분과 개별적인 부분으로 구분하여 알아봅니다.
ICW1 커맨드의 필드
ICW1 커맨드의 필드는 마스터와 슬레이브가 같으며, 트리거 모드와 캐스케이드 여부, ICW4의 사용 여부를 설정합니다.
키보드와 마우스 같은 PC 디바이스는 엣지 트리거 방식을 사용하고, PIC 컨트롤러는 마스터-슬레이브 방식으로 동작하므로 LTIM 비트 = 0, SNGL = 0으로 설정하며 또한, PC는 8086 호환 모드로 동작하므로 ICW4 커맨드가 필요하기 때문에 IC4=1로 설정하여 ICW4 커맨드를 사용하겠다는 것을 알립니다.
ICW2 커맨드의 필드
ICW2 커맨드의 필드도 ICW1과 같이 마스터와 슬레이브 모두 같고, 인터럽트가 발생했을 때 프로세서에 전달할 벡터 번호를 설정하는 역할을 합니다.
이전에 설명했듯이 벡터 0 ~ 31번은 프로세서가 예외를 처리하려고 예약한 영역이므로, 이 영역과의 충돌을 피하려면 32번 이후로 설정해야 합니다.
FS64 OS는 이를 위해 마스터 PIC 컨트롤러의 인터럽트를 32번부터 39번 영역에 할당하고, 슬레이브 PIC 컨트롤러의 인터럽트를 40번부터 47번 영역에 할당하여 사용합니다.
PIC 컨트롤러의 인터럽트를 벡터 32번부터 할당하려면 마스터 PIC 컨트롤러의 ICW2를 0x20(32)로 설정하고, 슬레이브 PIC 컨트롤러의 ICW2를 0x28(40)로 설정하면 됩니다.
ICW3 커맨드
ICW3 커맨드의 역할은 마스터 PIC 컨트롤러의 몇 번 핀에 슬레이브 PIC 컨트롤러가 연결되었나 하는 것이고, ICW3 커맨드의 의미는 두 컨트롤러가 같지만, 필드의 구성은 서로 다릅니다.
마스터 PIC 컨트롤러의 ICW3 커맨드는 슬레이브 PIC 컨트롤러가 연결된 핀의 위치를 비트로 설정하며, 슬레이브 PIC 컨트롤러의 ICW3 커맨드는 마스터 PIC 컨트롤러에 연결된 핀의 위치를 숫자로 설정합니다.
PC의 슬레이브 PIC 컨트롤러는 마스터 PIC 컨트롤러의 2번째 핀에 연결되어 있으므로 마스터 PIC 컨트롤러의 ICW3은 0x04(비트2=1)로 설정하고 슬레이브 PIC 컨트롤러의 ICW3은 0x02로 설정합니다.
ICW4 커맨드 필드
ICW4 커맨드 필드 역시 마스터와 슬레이브가 같고, EOI 전송 모드와 8086 모드, 확장 기능을 설정합니다.
FS64 OS는 EOI를 직접 전송하므로 AEOI 비트 = 0으로 설정하고, PC의 PIC 컨트롤러는 8086 시절과 별로 변한 것이 없으므로 uPM 비트 = 1로 설정하여 8086 모드로 지정합니다.
이를 제외한 버퍼 모드 같은 확장 기능은 PC에서 사용하지 않으므로 나머지 SFNM 비트, BUF 비트, M/S 비트는 모두 0으로 설정합니다.
아래는 위의 내용을 바탕으로 작성된 PIC 컨트롤러를 초기화하는 코드입니다.
초기화가 끝난 후 PIC 컨트롤러의 인터럽트는 벡터 32 ~ 47번으로 전달되어 해당 핸들러에 의해 처리됩니다.
→ 인터럽트 입력 선택
PIC 컨트롤러는 IRQ를 특정 벡터에 매핑하는 기능 외에 특정 인터럽트를 선택할 수 있는 기능이 있습니다.
특정 인터럽트를 선택하려면 IMR 레지스터에 무시할 인터럽트를 1로 설정해야 하며, OCW1 커맨드가 이런 역할을 담당합니다.
OCW1 커맨드의 필드는 아래와 같으며, 마스크를 설정하려면 마스터 PIC 컨트롤러는 0x21 포트, 슬레이브 PIC 컨트롤러는 0xA1 포트에 생성한 마스크 값을 씁니다.
마스크를 설정할 때는 IRQ 번호에 따라 마스터나 슬레이브 PIC 컨트롤러를 구분하여 처리해야 한다는 점에 주의해야 합니다.
마스터 PIC 컨트롤러는 IRQ0 ~ IRQ 7을 담당하고, 슬레이브 PIC 컨트롤러는 IRQ 8 ~ IRQ 15를 담당하므로 IRQ의 범위에 따라 PIC 컨트롤러를 선택해야 합니다.
아래는 IRQ 비트 마스크로 IMR 레지스터를 설정하는 코드입니다.
→ 인터럽트 종료 처리
인터럽트가 발생했음을 PIC 컨트롤러가 프로세서에 알려주면, 프로세서는 핸들러를 실행하여 인터럽트 처리를 완료(EOI, End Of Interrupt) 한 후 다시 PIC 컨트롤러에 이를 알려주어야 합니다.
만약 알려주지 않는다면 PIC 컨트롤러는 핸들러가 수행 중인 것으로 간주하고, 현재 발생한 인터럽트보다 우선순위가 낮은 인터럽트는 발생시키지 않습니다.
운 나쁘게도 IRQ 0 인터럽트가 발생했다면, PIC 컨트롤러는 IRQ 0에 가장 높은 우선순위를 부여하므로 EOI를 전송하기 전까지는 인터럽트가 전혀 발생하지 않을 것입니다.
PIC 컨트롤러에 EOI를 전송하려면 OCW2 커맨드를 사용해야 하며, 마스터 PIC 컨트롤러는 0x20 포트로, 슬레이브 PIC 컨트롤러는 0xA0 포트로 전송해야 합니다.
OCW2 커맨드는 특정 인터럽트에 대해서 EOI를 보낼 것인가, 인터럽트 완료 요청을 보낸 후 인터럽트의 우선순위를 자동으로 변경할 것인가에 대한 필드로 복잡하게 구성되어 있습니다. (위의 표를 참고)
하지만 FS64 OS에서는 특수한 기능보다는 PIC 컨트롤러가 알려준 인터럽트에 대해 완료를 전송하는 것이 목적이므로 위의 표에서 EOI 비트만 1로 설정하여 대상을 지정하지 않는 EOI 커맨드(Non-specific EOI Command)만 사용합니다.
EOI를 전송할 때 주의할 점이 한 가지 있는데, 슬레이브 PIC 컨트롤러에 EOI를 전송하면 마스터 PIC 컨트롤러에도 EOI를 전송해야 합니다.
PC의 PIC 컨트롤러는 위의 PIC 컨트롤러의 구성과 IRQ의 관계 그림에서와 같이 마스터 PIC 컨트롤러에 슬레이브 PIC 컨트롤러가 연결된 구조입니다.
슬레이브 PIC 컨트롤러에 인터럽트가 발생하면 마스터 PIC 컨트롤러를 통해 프로세서로 전달되기 때문에 슬레이브 PIC 컨트롤러에 인터럽트가 발생했을 때 마스터와 슬레이브 모두 EOI를 전송해야 합니다.
아래는 위의 내용을 바탕으로 작성된 EOI 전송 코드입니다.
'시작하지 말았어야 했던 것 > 64비트 멀티코어 OS' 카테고리의 다른 글
64비트 멀티코어 OS[13] - 1. 인터럽트 핸들러와 큐, 키보드 디바이스 드라이버 업그레이드 (0) | 2021.04.29 |
---|---|
64비트 멀티코어 OS[12] - 2. 인터럽트, 예외 핸들러, 콘텍스트 그리고 PIC 컨트롤러 제어 코드와 핸들러 코드의 통합과 빌드 (0) | 2021.04.22 |
64비트 멀티코어 OS[11] - 3. IDT, TSS 통합과 빌드 (0) | 2021.04.15 |
64비트 멀티코어 OS[11] - 2. GDT 테이블 교환과 TSS 세그먼트 디스크립터 추가 그리고 IDT 테이블 생성, 인터럽트, 예외 핸들러 등록 (0) | 2021.04.09 |
64비트 멀티코어 OS[11] - 1. 인터럽트와 예외 그리고 스택과 태스크 상태 세그먼트 (0) | 2021.04.08 |