최악의 PCIe MSI 인터럽트 지연 지터가 100us를 초과하는 것이 정상입니까?

최악의 PCIe MSI 인터럽트 지연 지터가 100us를 초과하는 것이 정상입니까?

특히 최악의 시나리오에서 Linux의 인터럽트 지터 값을 찾으려고 합니다. 두 가지 테스트 플랫폼이 고려되었습니다. 하나는 Raspberry Pi 4B이고 다른 하나는 Intel i9 CPU와 ASUS 마더보드가 장착된 고급 PC였습니다.

   +-+ +-+ +-+     Raspberry Pi 4B
   | | | | | |   -------------+
 --+ +-+ +-+ +-   1. GPIO     |              +--------------+
Signal Generator              |              |              |
                              +----> +-----+ |    Linux     |
                                     | CPU | | ------------ |
                              +----> +-----+ |    Kernel    |
       |  |                   |              |              |
     +-+--+-+     2. PCIe MSI |              +--------------+
   --+ FPGA +--   ------------+
     +-+--+-+      high-end PC (i9-9900K)
       |  |

Raspberry Pi의 경우 고정 주파수 구형파를 인터럽트 소스로 출력하는 신호 발생기를 사용합니다. 고급 PC의 경우 PCIe가 포함된 Xilinx FPGA 보드가 인터럽트 소스로 사용되며 인터럽트 유형은 MSI입니다. 신호 발생기와 Xilinx FPGA 보드 모두 매우 작은 타이밍 지터(<1us)로 인터럽트를 생성할 수 있습니다.

다음은 irq_handlerRaspberry Pi 4B의 드라이버 코드 기능 입니다.

static irqreturn_t gpio_ts_handler(int irq, void *arg) {

    struct timespec64 timestamp;
    struct gpio_ts_devinfo *devinfo;
    int nwritten;

    ktime_get_real_ts64(&timestamp);   // get the time

    // lock the data fifo and insert the timestamp
    spin_lock(&devinfo->spinlock);
    nwritten = gpio_fifo_write(devinfo->fifo, &timestamp, 1);
    spin_unlock(&devinfo->spinlock);
    if (nwritten != 1) {
        printk(KERN_ERR "GPIOTS: ISR fifo overflow\n");
    }

    // wake up the waiting thread which then read timestamp from the fifo
    wake_up(&devinfo->waitqueue);

    return IRQ_HANDLED;
}

irq_handler고급 PC의 드라이버 코드 기능은 다음과 같습니다 .

// IRQ handler
static irqreturn_t fPCI_event_isr (int irq, void *cookie)
{
    struct timespec64 tsc_now = {.tsc_high = 0; .tsc_low = 0};
    struct fPCI_dev *drv_data =  (struct fPCI_dev *) cookie;
    int nwritten;
    int fifo_size;
   
    // get TSC timestamp
    get_tsc_cpuid((tsc_now.tsc_high), (tsc_now.tsc_low));
    spin_lock(&(drv_data->spin_lock));
    nwritten = fpci_fifo_write(drv_data->fifo, &tsc_now, 1);
    spin_unlock(&(drv_data->spin_lock));
    if (nwritten != 1)
        printk(KERN_INFO, "fPCI_event_isr: fifo overflow!\n");
    
    fifo_size = fpci_fifo_size(drv_data->fifo);
    if (fifo_size > FIFO_SIZE/2)
        wake_up(&(drv_data->waitqueue));
    
    return IRQ_HANDLED;
}

IRQ 처리기 코드에서 먼저 현재 시간을 FIFO에 저장합니다. 그런 다음 사용자 공간 스레드는 FIFO에서 타이밍 데이터를 읽고 인터럽트 지터를 계산합니다. 결과는 다음 두 그림에 나와 있습니다.

여기에 이미지 설명을 입력하세요.

여기에 이미지 설명을 입력하세요.

내 질문은 다음과 같습니다

1 PCIe MSI 인터럽트가 GPIO 인터럽트보다 대기 시간 지터가 더 큰 이유는 무엇입니까?

2 최신 PCIe MSI 인터럽트가 최악의 경우 약 100us의 대기 시간 변화를 갖는 것이 정상입니까(제가 누락한 것이 있습니까)? 지연 시간(지터)의 변화를 최소화하는 방법.

관련 정보