개요
Intel UIPI (Intel User interprocessor interrupt)는 기존의 커널 의존적 IPC 메커니즘을 대체하기 위해, 하드웨어 수준에서 메시지 큐와 인터럽트 전달 메커니즘을 통합하였다. 각 프로세스는 사용자 공간 내에 존재하는 UIPI 엔드포인트(Endpoint)를 통해 다른 프로세스와 직접 데이터를 교환할 수 있다. Intel UIPI는 인텔 사파이어 레피드부터 도입되었다. Intel UIPI는 한 Kerne thread(e.g., pthread)에서 다른 User-level thread로 인터럽트를 보낼 수 있다.
아키텍쳐
기본 구조
- Access control
- MSR Register에 User Interrupt Target Table (UITT)라는 테이블이 있어서, UIPI의 기능을 설정할 수 있다. UITT는 Per-process table로 <UPID, vector>의 값들을 저장할 수 있다. UPID는 User posted interrupt descriptor의 약자로, thread별로 존재하는 in-memory descriptor이다. UITT에 UPID가 있으면, 그 process는 thread에 Interrupt를 보낼 수 있다. UPID는 다음과 같은 항목으로 구성되어 있다.
| 이름 | 설명 | 비트 범위 |
|---|---|---|
| Outstanding Notification (ON) | 하나 이상의 User Interrupt(UI)에 대한 알림이 대기 중인 경우를 나타냄 | 0:0 |
| Suppressed Notification (SN) | 송신자가 알림을 보내지 않아야 하는지를 나타냄 | 1:1 |
| Notification Vector (NV) | UI(User Interrupt)가 전달되어야 하는 인터럽트 벡터를 지정함 | 23:16 |
| Notification Destination (NDST) | 이 스레드가 실행 중인 코어의 APIC ID | 63:32 |
| Posted Interrupt Requests (PIR) | 이 스레드에 게시(posted)된 인터럽트 요청 목록 | 127:64 |
- Routing Interrupts
- Routing은 하드웨어 이벤트(예: 장치, 타이머, 스레드 간 신호)를 적절한 코어(core)로 전달하는 과정이다. UIPI에서는 이 목표 지점(target) 을
APIC ID로 식별하며, 실제 인터럽트 메시지는 8비트 벡터(vector)값으로 표현된다. 즉, “어떤 이벤트를 어떤 코어의 어떤 벡터로 전달할지 결정하는 과정”이 Routing이다. 기존의 Kernel-level interrupt 라우팅은 User thread 환경에서 다음과 같은 한계를 가진다.
- 동적 스레드 이동성 문제
- User-level thread는 코어 간에 자유롭게 이동하지만, 기존 APIC 기반 라우팅은 “고정된 코어(APICID)” 기준으로 동작하기 때문에 이를 추적하기 어렵다.
- 제한된 벡터 공간
- APIC의 벡터 공간은 256개(8비트)로 제한되어 있으며, 이 좁은 공간에서 User IPI를 매핑하려 하면 충돌 또는 자원 고갈 문제가 발생한다.
- 비활성 스레드 문제
- 인터럽트가 도착했을 때 해당 스레드가 이미 context-out 상태일 수 있어, 실제 인터럽트를 받을 주체가 존재하지 않아 누락(lost interrupt)이 발생할 수 있다.
UIPI는 이러한 문제를 해결하기 위해 가상 네임스페이스(virtual namespace)와 가상 벡터 공간(virtual vector space)을 도입하였다.
| 개념 | 설명 |
|---|---|
| Virtual Namespace | 코어(APICID)에 직접 매핑하지 않고, 스레드나 실행 단위를 가상 식별자로 구분함으로써 스레드 이동 시에도 동일한 UI 채널을 유지함. |
| Virtual Vector Space | 실제 APIC 벡터 대신 소프트웨어가 관리하는 가상 벡터를 사용하여 더 많은 인터럽트 ID를 안전하게 표현하고 충돌 및 자원 제한 문제를 완화함. |
UIPI Sending and Receiving
UIPI가 전송되면, Sending core는 UITT에서 UPID의 목적지를 검색하고 기존의 IPI를 목적지 코어에 전송하여, Pending UIPI가 도착했음을 전송한다. Receiving core는 UPID를 활용해서 최종적으로 UIPI를 전송한다. UPID는 모든 코어가 공유하고 있기 때문에, 각각의 코어들은 UPID를 참고하여 UIPI를 처리할 수 있다.
이러한 처리를 위해서 Kernel은 여러 System call을 제공한다. Receiving thread는 register_handler(...)시스템콜을 사용해서 UPID를 할당할 수 있고, User-level interrupt가 도착했을때 실행할 Program code를 지정할 수 있다. 커널은 UITT에 새로운 엔트리를 생성하고, UPID에 Vector를 등록하여 어떤 코드가 실행될지 지정한다.
User-interrupt는 senduipi [UITT Index]명령어를 사용해서 보낼 수 있다. 이 명령어는 UITT에서 해당하는 Index의 UPID를 검색하여 PIR field에 On으로 마킹하고 (Conventional)IPI를 NDST의 APICID에 해당하는 코어에 NV값과 함께 보낸다. IPI가 도착하면, receiver core는 MSR레지스터의 UINV를 참고해서 UIPI notification vector와 일치하는지를 검사한다. 만약 일치하면, UPID의 PIR값을 참고해서 이 UIPI가 만약 코어에서 돌아가고 있는 thread와 일치하면 바로 thread에 UIPI를 전송하지만, 만약 불일치하면 OS를 통해서 인터럽트를 대상이 되는 thread를 context switch하고 보내게 된다. 커널은 다음 scheduling time에 해당하는 thread의 Local APIC을 통해서 self-UIPI형식으로 보내준다. Interrupt가 지속적으로 들어와서 전체 시스템을 Slow down시키지 못하게 하도록 위해서, Suppressed Notification (SN)bit field를 UPID에 지정할 수 있도록 하여서, Thread가 만약 Context out되어 있고 아직 Pending UIPI가 있으면, Kernel이 SN bit을 On시켜서 더이상 UIPI가 대상 thread에 오지않도록 할 수 있다.
Thread는 현재 인터럽트를 받을지 여부를 다음 명령어를 통해 제어할 수 있다.
clui— 현재 Thread의 User Interrupt 수신을 비활성화한다.stui— User Interrupt 수신을 활성화한다.testui— 현재 Thread가 인터럽트가 차단(blocked)된 상태인지 여부를 확인한다.
만약 Thread가 다른 코어로 마이그레이션되는 경우, 커널은 해당 스레드의 User Interrupt Descriptor 내 NDST 필드를 새로 할당된 코어의 APICID 값으로 업데이트한다. 이를 통해 UIPI는 스레드의 이동에도 불구하고 올바른 코어로 인터럽트를 라우팅할 수 있도록 보장한다.
Architeture View

- 송신 코어는 수신 스레드의 UPID를 UITT(User Interrupt Target Table)에서 조회한다. 이후 UPID의
PIR(Posted Interrupt Request) 필드를 갱신하여 전송할 인터럽트 벡터 정보를 기록하고, 인터럽트가 대기 중임을 나타내기 위해ON(Outstanding Notification) 비트를 설정한다. - 송신 코어는 수신 코어의
APICID와 인터럽트 벡터 정보를 UPID에서 읽어와 이를ICR(Interrupt Command Register)에 기록한다. 이 동작으로 로컬 APIC이 수신 코어로 인터럽트를 전송하게 된다. - IOAPIC은 시스템 버스를 통해 인터럽트 메시지를 수신 코어의 로컬 APIC으로 전달한다. 로컬 APIC은 인터럽트 신호선을 활성화하여 해당 코어에 인터럽트 발생을 알린다.
- 수신 코어는 전체 파이프라인 플러시를 수행한 뒤,
notification processing이라 불리는 마이크로코드 절차를 실행한다. 이 과정에서 현재 스레드의 UPID로부터 User Interrupt 벡터를 읽어UIRR(User Interrupt Request Register)에 저장하고, 해당 스레드의 UPID 내ON비트를 클리어한다. - 코어는 이어서 User Interrupt 전달용 마이크로코드 절차를 실행한다. 이 절차에서는 스택 포인터(SP), 프로그램 카운터(PC), 인터럽트 벡터를 스택에 저장하고, 인터럽트 플래그(
UIF)를 클리어하여 핸들러 실행 중에는 추가 인터럽트가 비활성화되도록 한다. 이후UIRR를 업데이트하여 인터럽트가 처리 중임을 표시하고,UINT_Handler레지스터에 지정된 사용자 수준 핸들러로 제어를 이동한다. - User Interrupt 핸들러가 실행된다.
- 핸들러는 종료 시
uiret명령을 실행하여, 스택에 저장된 스택 포인터와 프로그램 카운터를 복원하고,UIF플래그를 다시 설정하여 이후 인터럽트 처리를 재활성화한다.
UIPI Microarchitecture (Flush vs Drain)
Processor가 User Interrupt Handler를 실행하기 위해서는 현재 실행 중인 명령어의 흐름(Control Flow)을 변경해야 한다. 이 과정에서 파이프라인 내부의 In-flight buffer를 비워야 한다. In-flight buffer는 아직 커밋되지 않은 명령어들이 임시로 저장되어 있는 하드웨어 버퍼로, 주로 ROB(Reorder Buffer), Load/Store Queue, Reservation Station 등이 이에 해당한다. 파이프라인을 비우는 방법에는 Flush와 Drain 두 가지가 있다.
| 구분 | Pipeline Flush | Pipeline Drain |
|---|---|---|
| 의미 | 파이프라인의 모든 in-flight 명령을 즉시 무효화하고 폐기 | 파이프라인 내 명령을 정상적으로 완료(commit) 후 비움 |
| 트리거 예시 | 분기 예측 실패, 예외(Exception), 인터럽트 발생(UIPI 포함) | 컨텍스트 스위칭, 전력 모드 전환 등 |
| 결과 | 즉시 파이프라인이 비워지지만, 진행 중이던 명령은 모두 폐기됨 | 커밋 후 자연스럽게 파이프라인이 비워짐 |
| 성능 비용 | 매우 큼 (speculation window가 클수록 증가) | 상대적으로 작음 |
| 효과 | Reorder Buffer와 예측기 상태가 리셋됨 | 정상 커밋 후 파이프라인 안정 상태로 전환 |
Flush는 실행 중인 명령을 모두 폐기하므로 Drain보다 훨씬 큰 오버헤드를 초래한다. 그러나 Intel은 UIPI(User Interrupt Processing Interface)가 발생할 때, 빠르고 확실한 제어 흐름 전환을 위해 Pipeline Flush 방식을 사용한다. 즉, UIPI가 도착하면 프로세서는 speculation window 내의 모든 in-flight 명령을 폐기하고, 마이크로코드 수준의 Notification Processing 절차로 진입하여 User Interrupt 벡터를 처리한다.
성능
| End-to-End Latency | Receiver Cost | SENUIPI | CLUI | STUI |
|---|---|---|---|---|
| 1360 cycles | 720 cycles | 383 cycles | 2 cycles | 32 cycles |

특징
- 낮은 지연시간 — 커널 모드 전환 없이 사용자 공간 간 통신 가능
- 높은 처리량 — 대용량 메시지 및 고빈도 이벤트 처리 지원
- 유연한 인터럽트 처리 — 비동기, 동기 이벤트 모두 지원
- 보안성 강화 — 커널 경로를 우회하지만, 권한 격리 정책은 하드웨어 수준에서 유지
기존 방식과 비교
| 구분 | Signal 기반 IPC | Poll 기반 IPC | Intel UIPI |
|---|---|---|---|
| 커널 개입 | O | △ | X |
| 응답 지연 | 높음 | 중간 | 매우 낮음 |
| CPU 사용률 | 낮음 | 높음 | 낮음 |
| 이벤트 지원 | 비동기 한정 | 동기 한정 | 동기 / 비동기 모두 |
| 주요 장점 | 단순 구현 | 빠른 반응성 | 효율적 / 고성능 IPC |
활용
Intel UIPI는 다음과 같은 영역에서의 응용이 가능하다.
- Microkernel 및 Unikernel 환경에서의 프로세스 간 통신 최적화
- Virtual Machine Monitor (VMM)와 게스트 OS 간의 이벤트 신호 처리
- User-level Filesystem이나 Network Stack에서의 고속 메시징
- Cloud Native 환경에서의 경량 프로세스 간 협업
한계
- 기존의 커널 IPC와의 호환성 부족
- 하드웨어 종속적 구조, Intel 아키텍처 이외의 환경에서는 지원 불가
- 보안 정책 커스터마이징의 제약
참고
- Intel Architecture Software Developer’s Manual, Vol.3: System Programming Guide
- “Hardware-Accelerated Inter-Process Messaging in Intel CPUs”, Intel Research (2023)
- Userfaultfd
- Shared Memory
- Message Passing Interface (MPI)